Merged major refactoring of x509write module into development

This refactoring adds support for proper CSR writing and X509
certificate generation / signing
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2a25057..cb2718f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -46,3 +46,9 @@
 ADD_CUSTOM_TARGET(apidoc
                   COMMAND doxygen doxygen/polarssl.doxyfile
                   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+
+ADD_CUSTOM_TARGET(memcheck
+    COMMAND ctest -R aes -O memcheck.log -D ExperimentalMemCheck
+    COMMAND tail -n1 memcheck.log | grep 'Memory checking results:' > /dev/null
+    COMMAND rm -f memcheck.log
+    )
diff --git a/ChangeLog b/ChangeLog
index 9f24244..8a15b6e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -22,6 +22,7 @@
    * Support for session tickets (RFC 5077)
    * Certificate Request (CSR) generation with extensions (key_usage,
      ns_cert_type)
+   * Optional blinding for RSA, DHM and EC
 
 Changes
    * Ability to enable / disable SSL v3 / TLS 1.0 / TLS 1.1 / TLS 1.2
@@ -40,11 +41,13 @@
      (Ability to keep old as well with POLARSSL_ERROR_STRERROR_BC)
    * SHA2 renamed to SHA256, SHA4 renamed to SHA512 and functions accordingly
    * All RSA operations require a random generator for blinding purposes
+   * x509_verify() now case insensitive for cn (RFC 6125 6.4)
 
 Bugfix
    * Fixed parse error in ssl_parse_certificate_request()
    * zlib compression/decompression skipped on empty blocks
    * Support for AIX header locations in net.c module
+   * Fixed file descriptor leaks
 
 Security
    * RSA blinding on CRT operations to counter timing attacks
diff --git a/DartConfiguration.tcl b/DartConfiguration.tcl
index 63f2d3e..da4c741 100644
--- a/DartConfiguration.tcl
+++ b/DartConfiguration.tcl
@@ -1,3 +1,4 @@
 Site: localhost
 BuildName: PolarSSL-test
 CoverageCommand: /usr/bin/gcov
+MemoryCheckCommand: /usr/bin/valgrind
diff --git a/doxygen/input/doc_encdec.h b/doxygen/input/doc_encdec.h
index a1b7e16..a78a869 100644
--- a/doxygen/input/doc_encdec.h
+++ b/doxygen/input/doc_encdec.h
@@ -5,33 +5,47 @@
 
 /**
  * @addtogroup encdec_module Encryption/decryption module
- * 
- * The Encryption/decryption module provides encryption/decryption functions. 
- * One can differtiate between symmetric and asymetric algorithms; the 
- * symmetric ones are mostly used for message confidentiality and the asymmetric 
- * ones for key exchange and message integrity.
- * Some symmetric algorithms provide different block cipher modes, mainly 
- * Electronic Code Book (ECB) which is used for short (64-bit) messages and 
- * Cipher Block Chaining (CBC) which provides the structure needed for longer 
- * messages. In addition the Cipher Feedback Mode (CFB-128) stream cipher mode
- * is implemented for specific algorithms.
  *
- * Sometimes the same functions are used for encryption and decryption.
+ * The Encryption/decryption module provides encryption/decryption functions.
+ * One can differentiate between symmetric and asymmetric algorithms; the
+ * symmetric ones are mostly used for message confidentiality and the asymmetric
+ * ones for key exchange and message integrity.
+ * Some symmetric algorithms provide different block cipher modes, mainly
+ * Electronic Code Book (ECB) which is used for short (64-bit) messages and
+ * Cipher Block Chaining (CBC) which provides the structure needed for longer
+ * messages. In addition the Cipher Feedback Mode (CFB-128) stream cipher mode,
+ * Counter mode (CTR) and Galois Counter Mode (GCM) are implemented for
+ * specific algorithms.
+ *
+ * All symmetric encryption algorithms are accessible via the generic cipher layer
+ * (see \c cipher_init_ctx()).
+ *
+ * The asymmetric encryptrion algorithms are accessible via the generic public
+ * key layer (see \c pk_init()).
+ *
  * The following algorithms are provided:
  * - Symmetric:
- *   - AES (see \c aes_crypt_ecb(), \c aes_crypt_cbc() and \c aes_crypt_cfb128()).
+ *   - AES (see \c aes_crypt_ecb(), \c aes_crypt_cbc(), \c aes_crypt_cfb128() and
+ *     \c aes_crypt_ctr()).
  *   - ARCFOUR (see \c arc4_crypt()).
- *   - Camellia (see \c camellia_crypt_ecb(), \c camellia_crypt_cbc() and \c camellia_crypt_cfb128()).
- *   - DES/3DES (see \c des_crypt_ecb(), \c des_crypt_cbc(), \c des3_crypt_ecb() 
+ *   - Blowfish / BF (see \c blowfish_crypt_ecb(), \c blowfish_crypt_cbc(),
+ *     \c blowfish_crypt_cfb64() and \c blowfish_crypt_ctr())
+ *   - Camellia (see \c camellia_crypt_ecb(), \c camellia_crypt_cbc(),
+ *     \c camellia_crypt_cfb128() and \c camellia_crypt_ctr()).
+ *   - DES/3DES (see \c des_crypt_ecb(), \c des_crypt_cbc(), \c des3_crypt_ecb()
  *     and \c des3_crypt_cbc()).
  *   - XTEA (see \c xtea_crypt_ecb()).
  * - Asymmetric:
- *   - Diffie-Hellman-Merkle (see \c dhm_read_public(), \c dhm_make_public() 
+ *   - Diffie-Hellman-Merkle (see \c dhm_read_public(), \c dhm_make_public()
  *     and \c dhm_calc_secret()).
  *   - RSA (see \c rsa_public() and \c rsa_private()).
+ *   - Elliptic Curves over GF(p) (see \c ecp_point_init()).
+ *   - Elliptic Curve Digital Signature Algorithm (ECDSA) (see \c ecdsa_init()).
+ *   - Elliptic Curve Diffie Hellman (ECDH) (see \c ecdh_init()).
  *
- * This module provides encryption/decryption which can be used to provide 
+ * This module provides encryption/decryption which can be used to provide
  * secrecy.
- * It also provides asymmetric key functions which can be used for 
- * confidentiality, integrity, authentication and non-repudiation. 
+ *
+ * It also provides asymmetric key functions which can be used for
+ * confidentiality, integrity, authentication and non-repudiation.
  */
diff --git a/doxygen/input/doc_hashing.h b/doxygen/input/doc_hashing.h
index 95fb887..38f8e81 100644
--- a/doxygen/input/doc_hashing.h
+++ b/doxygen/input/doc_hashing.h
@@ -5,16 +5,20 @@
 
 /**
  * @addtogroup hashing_module Hashing module
- * 
+ *
  * The Hashing module provides one-way hashing functions. Such functions can be
- * used for creating a hash message authentication code (HMAC) when sending a 
+ * used for creating a hash message authentication code (HMAC) when sending a
  * message. Such a HMAC can be used in combination with a private key
- * for authentication, which is a message integrity control. 
+ * for authentication, which is a message integrity control.
+ *
+ * All hash algorithms can be accessed via the generic MD layer (see
+ * \c md_init_ctx())
+ *
  * The following hashing-algorithms are provided:
- * - MD2, MD4, MD5 128-bit one-way hash functions by Ron Rivest (see 
+ * - MD2, MD4, MD5 128-bit one-way hash functions by Ron Rivest (see
  *   \c md2_hmac(), \c md4_hmac() and \c md5_hmac()).
- * - SHA-1, SHA-256, SHA-384/512 160-bit or more one-way hash functions by 
- *   NIST and NSA (see\c sha1_hmac(), \c sha2_hmac() and \c sha4_hmac()).
+ * - SHA-1, SHA-256, SHA-384/512 160-bit or more one-way hash functions by
+ *   NIST and NSA (see\c sha1_hmac(), \c sha256_hmac() and \c sha512_hmac()).
  *
  * This module provides one-way hashing which can be used for authentication.
  */
diff --git a/doxygen/input/doc_mainpage.h b/doxygen/input/doc_mainpage.h
index dc98951..44d961f 100644
--- a/doxygen/input/doc_mainpage.h
+++ b/doxygen/input/doc_mainpage.h
@@ -5,23 +5,22 @@
 
 /**
  * @mainpage PolarSSL v1.2.6 source code documentation
- * 
+ *
  * This documentation describes the internal structure of PolarSSL.  It was
  * automatically generated from specially formatted comment blocks in
  * PolarSSL's source code using Doxygen.  (See
  * http://www.stack.nl/~dimitri/doxygen/ for more information on Doxygen)
- * 
- * PolarSSL has a simple setup: it provides the ingredients for an SSL/TLS 
- * implementation. These ingredients are listed as modules in the 
- * \ref mainpage_modules "Modules section". This "Modules section" introduces 
- * the high-level module concepts used throughout this documentation.\n 
+ *
+ * PolarSSL has a simple setup: it provides the ingredients for an SSL/TLS
+ * implementation. These ingredients are listed as modules in the
+ * \ref mainpage_modules "Modules section". This "Modules section" introduces
+ * the high-level module concepts used throughout this documentation.\n
  * Some examples of PolarSSL usage can be found in the \ref mainpage_examples
  * "Examples section".
- * 
- * 
+ *
  * @section mainpage_modules Modules
- * 
- * PolarSSL supports SSLv3 up to TLSv1.2 communication by providing the 
+ *
+ * PolarSSL supports SSLv3 up to TLSv1.2 communication by providing the
  * following:
  * - TCP/IP communication functions: listen, connect, accept, read/write.
  * - SSL/TLS communication functions: init, handshake, read/write.
@@ -30,19 +29,19 @@
  * - Hashing
  * - Encryption/decryption
  *
- * Above functions are split up neatly into logical interfaces. These can be 
- * used separately to provide any of the above functions or to mix-and-match 
- * into an SSL server/client solution that utilises a X.509 PKI. Examples of 
- * such implementations are amply provided with the source code. Note that 
- * there is also an OpenSSL wrapper provided.\n
+ * Above functions are split up neatly into logical interfaces. These can be
+ * used separately to provide any of the above functions or to mix-and-match
+ * into an SSL server/client solution that utilises a X.509 PKI. Examples of
+ * such implementations are amply provided with the source code.
+ *
  * Note that PolarSSL does not provide a control channel or (multiple) session
- * handling. 
+ * handling without additional work from the developer.
  *
  * @section mainpage_examples Examples
- * 
+ *
  * Example server setup:
  *
- * \b Prerequisites: 
+ * \b Prerequisites:
  * - X.509 certificate and private key
  * - session handling functions
  *
@@ -57,7 +56,6 @@
  * - Read/write data (SSL/TLS interface)
  * - Close and cleanup (all interfaces)
  *
- *
  * Example client setup:
  *
  * \b Prerequisites:
@@ -75,6 +73,4 @@
  * - Verify the server certificate (SSL/TLS interface)
  * - Write/read data (SSL/TLS interface)
  * - Close and cleanup (all interfaces)
- *
- * 
  */
diff --git a/doxygen/input/doc_rng.h b/doxygen/input/doc_rng.h
index 40852ee..8b482f1 100644
--- a/doxygen/input/doc_rng.h
+++ b/doxygen/input/doc_rng.h
@@ -5,18 +5,19 @@
 
 /**
  * @addtogroup rng_module Random number generator (RNG) module
- * 
- * The Random number generator (RNG) module provides random number
- * generation, see \c ctr_dbrg_random() or \c havege_random().
  *
- * The former uses the block-cipher counter-mode based deterministic random
+ * The Random number generator (RNG) module provides random number
+ * generation, see \c ctr_dbrg_random().
+ *
+ * The block-cipher counter-mode based deterministic random
  * bit generator (CTR_DBRG) as specified in NIST SP800-90. It needs an external
  * source of entropy. For these purposes \c entropy_func() can be used. This is
  * an implementation based on a simple entropy accumulator design.
  *
- * The latter random number generator uses the HAVEGE (HArdware Volatile
- * Entropy Gathering and Expansion) software heuristic which is claimed 
- * to be an unpredictable or empirically strong* random number generation.
+ * The other number generator that is included is less strong and uses the HAVEGE
+ * (HArdware Volatile Entropy Gathering and Expansion) software heuristic
+ * which considered unsafe for primary usage, but provides additional random
+ * to the entropy pool if enables.
  *
  * \* Meaning that there seems to be no practical algorithm that can guess
  * the next bit with a probability larger than 1/2 in an output sequence.
diff --git a/doxygen/input/doc_ssltls.h b/doxygen/input/doc_ssltls.h
index 06ba480..150c106 100644
--- a/doxygen/input/doc_ssltls.h
+++ b/doxygen/input/doc_ssltls.h
@@ -5,16 +5,16 @@
 
 /**
  * @addtogroup ssltls_communication_module SSL/TLS communication module
- * 
+ *
  * The SSL/TLS communication module provides the means to create an SSL/TLS
- * communication channel. 
+ * communication channel.
+ *
  * The basic provisions are:
  * - initialise an SSL/TLS context (see \c ssl_init()).
  * - perform an SSL/TLS handshake (see \c ssl_handshake()).
  * - read/write (see \c ssl_read() and \c ssl_write()).
  * - notify a peer that conection is being closed (see \c ssl_close_notify()).
  *
- *
  * Many aspects of such a channel are set through parameters and callback
  * functions:
  * - the endpoint role: client or server.
@@ -24,7 +24,6 @@
  * - the ciphers to use for encryption/decryption.
  * - session control functions.
  * - X.509 parameters for certificate-handling and key exchange.
- * 
  *
  * This module can be used to create an SSL/TLS server and client and to provide a basic
  * framework to setup and communicate through an SSL/TLS communication channel.\n
diff --git a/doxygen/input/doc_tcpip.h b/doxygen/input/doc_tcpip.h
index 53076bc..c9309a7 100644
--- a/doxygen/input/doc_tcpip.h
+++ b/doxygen/input/doc_tcpip.h
@@ -5,12 +5,12 @@
 
 /**
  * @addtogroup tcpip_communication_module TCP/IP communication module
- * 
+ *
  * The TCP/IP communication module provides for a channel of
- * communication for the \link ssltls_communication_module SSL/TLS communication 
- * module\endlink to use. 
- * In the TCP/IP-model it provides for communication up to the Transport 
- * (or Host-to-host) layer. 
+ * communication for the \link ssltls_communication_module SSL/TLS communication
+ * module\endlink to use.
+ * In the TCP/IP-model it provides for communication up to the Transport
+ * (or Host-to-host) layer.
  * SSL/TLS resides on top of that, in the Application layer, and makes use of
  * its basic provisions:
  * - listening on a port (see \c net_bind()).
@@ -18,9 +18,9 @@
  * - read/write (through \c net_recv()/\c net_send()).
  * - close a connection (through \c net_close()).
  *
- * This way you have the means to, for example, implement and use an UDP or 
+ * This way you have the means to, for example, implement and use an UDP or
  * IPSec communication solution as a basis.
- * 
+ *
  * This module can be used at server- and clientside to provide a basic
  * means of communication over the internet.
  */
diff --git a/doxygen/input/doc_x509.h b/doxygen/input/doc_x509.h
index 16fe75a..3798814 100644
--- a/doxygen/input/doc_x509.h
+++ b/doxygen/input/doc_x509.h
@@ -5,17 +5,19 @@
 
 /**
  * @addtogroup x509_module X.509 module
- * 
+ *
  * The X.509 module provides X.509 support which includes:
  * - X.509 certificate (CRT) reading (see \c x509parse_crt() and
  *   \c x509parse_crtfile()).
  * - X.509 certificate revocation list (CRL) reading (see \c x509parse_crl()
  *   and\c x509parse_crlfile()).
- * - X.509 (RSA) private key reading (see \c x509parse_key_rsa() and
- *   \c x509parse_keyfile_rsa()).
+ * - X.509 (RSA and ECC) private key reading (see \c x509parse_key() and
+ *   \c x509parse_keyfile()).
  * - X.509 certificate signature verification (see \c x509parse_verify())
+ * - X.509 certificate writing and certificate request writing (see
+ *   \c x509write_crt_der() and \c x509write_csr_der()).
  *
  * This module can be used to build a certificate authority (CA) chain and
- * verify its signature. It is also used to get a (RSA) private key for signing
- * and decryption.
+ * verify its signature. It is also used to generate Certificate Signing
+ * Requests and X509 certificates just as a CA would do.
  */
diff --git a/doxygen/polarssl.doxyfile b/doxygen/polarssl.doxyfile
index 5fbc133..5182743 100644
--- a/doxygen/polarssl.doxyfile
+++ b/doxygen/polarssl.doxyfile
@@ -1,14 +1,16 @@
-# Doxyfile 1.6.3
+# Doxyfile 1.8.4
 
 # This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project
+# doxygen (www.doxygen.org) for a project.
 #
-# All text after a hash (#) is considered a comment and will be ignored
+# All text after a double hash (##) is considered a comment and is placed
+# in front of the TAG it is preceding .
+# All text after a hash (#) is considered a comment and will be ignored.
 # The format is:
 #       TAG = value [value, ...]
 # For lists items can also be appended using:
 #       TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ")
+# Values that contain spaces should be placed between quotes (" ").
 
 #---------------------------------------------------------------------------
 # Project related configuration options
@@ -22,8 +24,9 @@
 
 DOXYFILE_ENCODING      = UTF-8
 
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
-# by quotes) that should identify the project.
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
 
 PROJECT_NAME           = "PolarSSL v1.2.6"
 
@@ -33,6 +36,19 @@
 
 PROJECT_NUMBER         =
 
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO           =
+
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
 # base path where the generated documentation will be put.
 # If a relative path is entered, it will be relative to the location
@@ -56,9 +72,9 @@
 # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
 # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
 # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
-# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
-# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
-# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+# messages), Korean, Korean-en, Latvian, Lithuanian, Norwegian, Macedonian,
+# Persian, Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic,
+# Slovak, Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
 
 OUTPUT_LANGUAGE        = English
 
@@ -122,9 +138,11 @@
 # only done if one of the specified strings matches the left-hand part of
 # the path. The tag can be used to show relative paths in the file list.
 # If left blank the directory from which doxygen is run is used as the
-# path to strip.
+# path to strip. Note that you specify absolute paths here, but also
+# relative paths, which will be relative from the directory where doxygen is
+# started.
 
-STRIP_FROM_PATH        = 
+STRIP_FROM_PATH        =
 
 # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
 # the path mentioned in the documentation of a class, which tells
@@ -136,7 +154,7 @@
 STRIP_FROM_INC_PATH    =
 
 # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
-# (but less readable) file names. This can be useful is your file systems
+# (but less readable) file names. This can be useful if your file system
 # doesn't support long names like on DOS, Mac, or CD-ROM.
 
 SHORT_NAMES            = NO
@@ -191,6 +209,13 @@
 
 ALIASES                =
 
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST              =
+
 # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
 # sources only. Doxygen will then generate output that is more tailored for C.
 # For instance, some of the names that are used will be different. The list
@@ -217,22 +242,40 @@
 
 OPTIMIZE_OUTPUT_VHDL   = NO
 
-# Doxygen selects the parser to use depending on the extension of the files it parses.
-# With this tag you can assign which parser to use for a given extension.
-# Doxygen has a built-in mapping, but you can override or extend it using this tag.
-# The format is ext=language, where ext is a file extension, and language is one of
-# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
-# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
-# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
-# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension,
+# and language is one of the parsers supported by doxygen: IDL, Java,
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
+# C++. For instance to make doxygen treat .inc files as Fortran files (default
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the
+# files are not read by doxygen.
 
 EXTENSION_MAPPING      =
 
+# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all
+# comments according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you
+# can mix doxygen, HTML, and XML commands with Markdown formatting.
+# Disable only in case of backward compatibilities issues.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT       = YES
+
 # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
 # to include (a tag file for) the STL sources as input, then you should
 # set this tag to YES in order to let doxygen match functions declarations and
 # definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
-# func(std::string) {}). This also make the inheritance and collaboration
+# func(std::string) {}). This also makes the inheritance and collaboration
 # diagrams that involve STL classes more complete and accurate.
 
 BUILTIN_STL_SUPPORT    = NO
@@ -248,10 +291,10 @@
 
 SIP_SUPPORT            = NO
 
-# For Microsoft's IDL there are propget and propput attributes to indicate getter
-# and setter methods for a property. Setting this option to YES (the default)
-# will make doxygen to replace the get and set methods by a property in the
-# documentation. This will only work if the methods are indeed getting or
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES (the
+# default) will make doxygen replace the get and set methods by a property in
+# the documentation. This will only work if the methods are indeed getting or
 # setting a simple type. If this is not the case, or you want to show the
 # methods anyway, you should set this option to NO.
 
@@ -272,6 +315,22 @@
 
 SUBGROUPING            = YES
 
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields or simple typedef fields will be shown
+# inline in the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO (the default), structs, classes, and unions are shown on a separate
+# page (for HTML and Man pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS  = NO
+
 # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
 # is documented as struct, union, or enum with the name of the typedef. So
 # typedef struct TypeS {} TypeT, will appear in the documentation as a struct
@@ -282,21 +341,16 @@
 
 TYPEDEF_HIDES_STRUCT   = NO
 
-# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
-# determine which symbols to keep in memory and which to flush to disk.
-# When the cache is full, less often used symbols will be written to disk.
-# For small to medium size projects (<1000 input files) the default value is
-# probably good enough. For larger projects a too small cache size can cause
-# doxygen to be busy swapping symbols to and from disk most of the time
-# causing a significant performance penality.
-# If the system has enough physical memory increasing the cache will improve the
-# performance by keeping more symbols in memory. Note that the value works on
-# a logarithmic scale so increasing the size by one will rougly double the
-# memory usage. The cache size is given by this formula:
-# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can
+# be an expensive process and often the same symbol appear multiple times in
+# the code, doxygen keeps a cache of pre-resolved symbols. If the cache is too
+# small doxygen will become slower. If the cache is too large, memory is wasted.
+# The cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid
+# range is 0..9, the default is 0, corresponding to a cache size of 2^16 = 65536
+# symbols.
 
-SYMBOL_CACHE_SIZE      = 0
+LOOKUP_CACHE_SIZE      = 0
 
 #---------------------------------------------------------------------------
 # Build related configuration options
@@ -305,7 +359,7 @@
 # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
 # documentation are documented, even if no documentation was available.
 # Private class members and static file members will be hidden unless
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+# the EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES
 
 EXTRACT_ALL            = YES
 
@@ -314,6 +368,11 @@
 
 EXTRACT_PRIVATE        = YES
 
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+
+EXTRACT_PACKAGE        = NO
+
 # If the EXTRACT_STATIC tag is set to YES all static members of a file
 # will be included in the documentation.
 
@@ -336,7 +395,7 @@
 # extracted and appear in the documentation as a namespace called
 # 'anonymous_namespace{file}', where file will be replaced with the base
 # name of the file that contains the anonymous namespace. By default
-# anonymous namespace are hidden.
+# anonymous namespaces are hidden.
 
 EXTRACT_ANON_NSPACES   = YES
 
@@ -421,7 +480,13 @@
 
 SORT_BRIEF_DOCS        = NO
 
-# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
 
 SORT_MEMBERS_CTORS_1ST = NO
 
@@ -441,6 +506,15 @@
 
 SORT_BY_SCOPE_NAME     = NO
 
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING  = NO
+
 # The GENERATE_TODOLIST tag can be used to enable (YES) or
 # disable (NO) the todo list. This list is created by putting \todo
 # commands in the documentation.
@@ -466,15 +540,16 @@
 GENERATE_DEPRECATEDLIST= YES
 
 # The ENABLED_SECTIONS tag can be used to enable conditional
-# documentation sections, marked by \if sectionname ... \endif.
+# documentation sections, marked by \if section-label ... \endif
+# and \cond section-label ... \endcond blocks.
 
 ENABLED_SECTIONS       =
 
 # The MAX_INITIALIZER_LINES tag determines the maximum number of lines
-# the initial value of a variable or define consists of for it to appear in
+# the initial value of a variable or macro consists of for it to appear in
 # the documentation. If the initializer consists of more lines than specified
 # here it will be hidden. Use a value of 0 to hide initializers completely.
-# The appearance of the initializer of individual variables and defines in the
+# The appearance of the initializer of individual variables and macros in the
 # documentation can be controlled using \showinitializer or \hideinitializer
 # command in the documentation regardless of this setting.
 
@@ -486,12 +561,6 @@
 
 SHOW_USED_FILES        = YES
 
-# If the sources in your project are distributed over multiple directories
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES       = YES
-
 # Set the SHOW_FILES tag to NO to disable the generation of the Files page.
 # This will remove the Files entry from the Quick Index and from the
 # Folder Tree View (if specified). The default is YES.
@@ -515,15 +584,26 @@
 
 FILE_VERSION_FILTER    =
 
-# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
-# doxygen. The layout file controls the global structure of the generated output files
-# in an output format independent way. The create the layout file that represents
-# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
-# file name after the option, if omitted DoxygenLayout.xml will be used as the name
-# of the layout file.
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
 
 LAYOUT_FILE            =
 
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path. Do not use
+# file names with spaces, bibtex cannot handle them.
+
+CITE_BIB_FILES         =
+
 #---------------------------------------------------------------------------
 # configuration options related to warning and progress messages
 #---------------------------------------------------------------------------
@@ -552,7 +632,7 @@
 
 WARN_IF_DOC_ERROR      = YES
 
-# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
 # functions that are documented, but have no documentation for their parameters
 # or return value. If set to NO (the default) doxygen will only warn about
 # wrong or incomplete parameter documentation, but not about the absence of
@@ -598,8 +678,9 @@
 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
 # and *.h) to filter out the source-files in the directories. If left
 # blank the following patterns are tested:
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
-# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
 
 FILE_PATTERNS          = *.c \
                          *.h
@@ -610,16 +691,18 @@
 
 RECURSIVE              = YES
 
-# The EXCLUDE tag can be used to specify files and/or directories that should
+# The EXCLUDE tag can be used to specify files and/or directories that should be
 # excluded from the INPUT source files. This way you can easily exclude a
 # subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
 
 EXCLUDE                = tests/fct.h \
                          programs \
                          CMakeFiles
 
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
-# directories that are symbolic links (a Unix filesystem feature) are excluded
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
 # from the input.
 
 EXCLUDE_SYMLINKS       = NO
@@ -672,8 +755,10 @@
 # is the value of the INPUT_FILTER tag, and <input-file> is the name of an
 # input file. Doxygen will then use the output that the filter program writes
 # to standard output.
-# If FILTER_PATTERNS is specified, this tag will be
-# ignored.
+# If FILTER_PATTERNS is specified, this tag will be ignored.
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
 
 INPUT_FILTER           =
 
@@ -683,8 +768,8 @@
 # filter if there is a match.
 # The filters are a list of the form:
 # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
-# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
-# is applied to all files.
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
 
 FILTER_PATTERNS        =
 
@@ -694,6 +779,21 @@
 
 FILTER_SOURCE_FILES    = NO
 
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
 #---------------------------------------------------------------------------
 # configuration options related to source browsing
 #---------------------------------------------------------------------------
@@ -712,7 +812,7 @@
 
 # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
 # doxygen to hide any special comment blocks from generated source code
-# fragments. Normal C and C++ comments will always remain visible.
+# fragments. Normal C, C++ and Fortran comments will always remain visible.
 
 STRIP_CODE_COMMENTS    = YES
 
@@ -796,7 +896,14 @@
 
 # The HTML_HEADER tag can be used to specify a personal HTML header for
 # each generated HTML page. If it is left blank doxygen will generate a
-# standard header.
+# standard header. Note that when using a custom header you are responsible
+#  for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
 
 HTML_HEADER            =
 
@@ -808,33 +915,80 @@
 
 # The HTML_STYLESHEET tag can be used to specify a user-defined cascading
 # style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet. Note that doxygen will try to copy
-# the style sheet file to the HTML output directory, so don't put your own
-# stylesheet in the HTML output directory as well, or it will be erased!
+# fine-tune the look of the HTML output. If left blank doxygen will
+# generate a default style sheet. Note that it is recommended to use
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
+# tag will in the future become obsolete.
 
 HTML_STYLESHEET        =
 
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
+# user-defined cascading style sheet that is included after the standard
+# style sheets created by doxygen. Using this option one can overrule
+# certain style aspects. This is preferred over using HTML_STYLESHEET
+# since it does not replace the standard style sheet and is therefor more
+# robust against future updates. Doxygen will copy the style sheet file to
+# the output directory.
+
+HTML_EXTRA_STYLESHEET  =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
 # page will contain the date and time when the page was generated. Setting
 # this to NO can help when comparing the output of multiple runs.
 
 HTML_TIMESTAMP         = YES
 
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
-# files or namespaces will be aligned in HTML using tables. If set to
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS     = YES
-
 # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
 # documentation will contain sections that can be hidden and shown after the
-# page has loaded. For this to work a browser that supports
-# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
-# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+# page has loaded.
 
 HTML_DYNAMIC_SECTIONS  = NO
 
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
+# entries shown in the various tree structured indices initially; the user
+# can expand and collapse entries dynamically later on. Doxygen will expand
+# the tree to such a level that at most the specified number of entries are
+# visible (unless a fully collapsed tree already exceeds this amount).
+# So setting the number of entries 1 will produce a full collapsed tree by
+# default. 0 is a special value representing an infinite number of entries
+# and will result in a full expanded tree by default.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
 # If the GENERATE_DOCSET tag is set to YES, additional index files
 # will be generated that can be used as input for Apple's Xcode 3
 # integrated development environment, introduced with OSX 10.5 (Leopard).
@@ -843,7 +997,8 @@
 # directory and running "make install" will install the docset in
 # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
 # it at startup.
-# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
 
 GENERATE_DOCSET        = NO
 
@@ -861,6 +1016,16 @@
 
 DOCSET_BUNDLE_ID       = org.doxygen.Project
 
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
+# identify the documentation publisher. This should be a reverse domain-name
+# style string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
 # If the GENERATE_HTMLHELP tag is set to YES, additional index files
 # will be generated that can be used as input for tools like the
 # Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
@@ -905,10 +1070,10 @@
 
 TOC_EXPAND             = NO
 
-# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
-# are set, an additional index file will be generated that can be used as input for
-# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
-# HTML documentation.
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
 
 GENERATE_QHP           = NO
 
@@ -930,20 +1095,24 @@
 
 QHP_VIRTUAL_FOLDER     = doc
 
-# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
-# For more information please see
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
 # http://doc.trolltech.com/qthelpproject.html#custom-filters
 
 QHP_CUST_FILTER_NAME   =
 
-# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
-# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
 
 QHP_CUST_FILTER_ATTRS  =
 
-# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
 # filter section matches.
-# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
 
 QHP_SECT_FILTER_ATTRS  =
 
@@ -956,11 +1125,12 @@
 
 # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
 #  will be generated, which together with the HTML files, form an Eclipse help
-#  plugin. To install this plugin and make it available under the help contents
+# plugin. To install this plugin and make it available under the help contents
 # menu in Eclipse, the contents of the directory containing the HTML and XML
 # files needs to be copied into the plugins directory of eclipse. The name of
 # the directory within the plugins directory should be the same as
-# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before the help appears.
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
 
 GENERATE_ECLIPSEHELP   = NO
 
@@ -970,17 +1140,14 @@
 
 ECLIPSE_DOC_ID         = org.doxygen.Project
 
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
-# top of each HTML page. The value NO (the default) enables the index and
-# the value YES disables it.
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
 
 DISABLE_INDEX          = NO
 
-# This tag can be used to set the number of enum values (range [1..20])
-# that doxygen will group on one line in the generated HTML documentation.
-
-ENUM_VALUES_PER_LINE   = 4
-
 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
 # structure should be generated to display hierarchical information.
 # If the tag value is set to YES, a side panel will be generated
@@ -988,13 +1155,17 @@
 # is generated for HTML Help). For this to work a browser that supports
 # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
 # Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
 
 GENERATE_TREEVIEW      = NO
 
-# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
-# and Class Hierarchy pages using a tree view instead of an ordered list.
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
 
-USE_INLINE_TREES       = NO
+ENUM_VALUES_PER_LINE   = 4
 
 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
 # used to set the initial width (in pixels) of the frame in which the tree
@@ -1002,6 +1173,11 @@
 
 TREEVIEW_WIDTH         = 250
 
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW    = NO
+
 # Use this tag to change the font size of Latex formulas included
 # as images in the HTML documentation. The default is 10. Note that
 # when you change the font size after a successful doxygen run you need
@@ -1010,19 +1186,112 @@
 
 FORMULA_FONTSIZE       = 10
 
-# When the SEARCHENGINE tag is enabled doxygen will generate a search box for the HTML output. The underlying search engine uses javascript
-# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) there is already a search function so this one should
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you may also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and
+# SVG. The default value is HTML-CSS, which is slower, but has the best
+# compatibility.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to
+# the MathJax Content Delivery Network so you can quickly see the result without
+# installing MathJax.
+# However, it is strongly recommended to install a local
+# copy of MathJax from http://www.mathjax.org before deployment.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript
+# pieces of code that will be used on startup of the MathJax code.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
 # typically be disabled. For large projects the javascript based search engine
 # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
 
 SEARCHENGINE           = NO
 
-# When the SERVER_BASED_SEARCH tag is enabled the search engine will be implemented using a PHP enabled web server instead of at the web client using Javascript. Doxygen will generate the search PHP script and index
-# file to put on the web server. The advantage of the server based approach is that it scales better to large projects and allows full text search. The disadvances is that it is more difficult to setup
-# and does not have live searching capabilities.
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript.
+# There are two flavours of web server based search depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools.
+# See the manual for details.
 
 SERVER_BASED_SEARCH    = NO
 
+# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain
+# the search results. Doxygen ships with an example indexer (doxyindexer) and
+# search engine (doxysearch.cgi) which are based on the open source search
+# engine library Xapian. See the manual for configuration details.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will returned the search results when EXTERNAL_SEARCH is enabled.
+# Doxygen ships with an example search engine (doxysearch) which is based on
+# the open source search engine library Xapian. See the manual for configuration
+# details.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id
+# of to a relative location where the documentation can be found.
+# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ...
+
+EXTRA_SEARCH_MAPPINGS  =
+
 #---------------------------------------------------------------------------
 # configuration options related to the LaTeX output
 #---------------------------------------------------------------------------
@@ -1059,8 +1328,8 @@
 COMPACT_LATEX          = YES
 
 # The PAPER_TYPE tag can be used to set the paper type that is used
-# by the printer. Possible values are: a4, a4wide, letter, legal and
-# executive. If left blank a4wide will be used.
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4 will be used.
 
 PAPER_TYPE             = a4wide
 
@@ -1076,6 +1345,20 @@
 
 LATEX_HEADER           =
 
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images
+# or other source files which should be copied to the LaTeX output directory.
+# Note that the files will be copied as-is; there are no commands or markers
+# available.
+
+LATEX_EXTRA_FILES      =
+
 # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
 # is prepared for conversion to pdf (using ps2pdf). The pdf file will
 # contain links (just like the HTML output) instead of page references
@@ -1102,10 +1385,19 @@
 
 LATEX_HIDE_INDICES     = NO
 
-# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER.
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
 
 LATEX_SOURCE_CODE      = NO
 
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE        = plain
+
 #---------------------------------------------------------------------------
 # configuration options related to the RTF output
 #---------------------------------------------------------------------------
@@ -1137,7 +1429,7 @@
 
 RTF_HYPERLINKS         = NO
 
-# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# Load style sheet definitions from file. Syntax is similar to doxygen's
 # config file, i.e. a series of assignments. You only have to provide
 # replacements, missing definitions are set to their default value.
 
@@ -1212,6 +1504,21 @@
 XML_PROGRAMLISTING     = YES
 
 #---------------------------------------------------------------------------
+# configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES Doxygen will generate DOCBOOK files
+# that can be used to generate PDF.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the DOCBOOK pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it. If left blank docbook will be used as the default path.
+
+DOCBOOK_OUTPUT         = docbook
+
+#---------------------------------------------------------------------------
 # configuration options for the AutoGen Definitions output
 #---------------------------------------------------------------------------
 
@@ -1282,7 +1589,7 @@
 EXPAND_ONLY_PREDEF     = NO
 
 # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
-# in the INCLUDE_PATH (see below) will be search if a #include is found.
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
 
 SEARCH_INCLUDES        = YES
 
@@ -1323,15 +1630,15 @@
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
 # this tag can be used to specify a list of macro names that should be expanded.
 # The macro definition that is found in the sources will be used.
-# Use the PREDEFINED tag if you want to use a different macro definition.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
 
 EXPAND_AS_DEFINED      =
 
 # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
-# doxygen's preprocessor will remove all function-like macros that are alone
-# on a line, have an all uppercase name, and do not end with a semicolon. Such
-# function macros are typically used for boiler-plate code, and will confuse
-# the parser if not removed.
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
 
 SKIP_FUNCTION_MACROS   = YES
 
@@ -1339,22 +1646,18 @@
 # Configuration::additions related to external references
 #---------------------------------------------------------------------------
 
-# The TAGFILES option can be used to specify one or more tagfiles.
-# Optionally an initial location of the external documentation
-# can be added for each tagfile. The format of a tag file without
-# this location is as follows:
+# The TAGFILES option can be used to specify one or more tagfiles. For each
+# tag file the location of the external documentation should be added. The
+# format of a tag file without this location is as follows:
 #
 # TAGFILES = file1 file2 ...
 # Adding location for the tag files is done as follows:
 #
 # TAGFILES = file1=loc1 "file2 = loc2" ...
-# where "loc1" and "loc2" can be relative or absolute paths or
-# URLs. If a location is present for each tag, the installdox tool
-# does not have to be run to correct the links.
-# Note that each tag file must have a unique name
-# (where the name does NOT include the path)
-# If a tag file is not located in the directory in which doxygen
-# is run, you must also specify the path to the tagfile here.
+# where "loc1" and "loc2" can be relative or absolute paths
+# or URLs. Note that each tag file must have a unique name (where the name does
+# NOT include the path). If a tag file is not located in the directory in which
+# doxygen is run, you must also specify the path to the tagfile here.
 
 TAGFILES               =
 
@@ -1375,6 +1678,12 @@
 
 EXTERNAL_GROUPS        = YES
 
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed
+# in the related pages index. If set to NO, only the current project's
+# pages will be listed.
+
+EXTERNAL_PAGES         = YES
+
 # The PERL_PATH should be the absolute path and name of the perl script
 # interpreter (i.e. the result of `which perl').
 
@@ -1387,9 +1696,8 @@
 # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
 # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
 # or super classes. Setting the tag to NO turns the diagrams off. Note that
-# this option is superseded by the HAVE_DOT option below. This is only a
-# fallback. It is recommended to install and use dot, since it yields more
-# powerful graphs.
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
 
 CLASS_DIAGRAMS         = NO
 
@@ -1415,33 +1723,38 @@
 
 HAVE_DOT               = YES
 
-# By default doxygen will write a font called FreeSans.ttf to the output
-# directory and reference it in all dot files that doxygen generates. This
-# font does not include all possible unicode characters however, so when you need
-# these (or just want a differently looking font) you can specify the font name
-# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
-# which can be done by putting it in a standard location or by setting the
-# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
-# containing the font.
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
 
-DOT_FONTNAME           = FreeSans
+DOT_NUM_THREADS        = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME           = Helvetica
 
 # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
 # The default size is 10pt.
 
 DOT_FONTSIZE           = 10
 
-# By default doxygen will tell dot to use the output directory to look for the
-# FreeSans.ttf font (which doxygen will put there itself). If you specify a
-# different font using DOT_FONTNAME you can set the path where dot
-# can find it using this tag.
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
 
 DOT_FONTPATH           =
 
 # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
 # will generate a graph for each documented class showing the direct and
 # indirect inheritance relations. Setting this tag to YES will force the
-# the CLASS_DIAGRAMS tag to NO.
+# CLASS_DIAGRAMS tag to NO.
 
 CLASS_GRAPH            = YES
 
@@ -1463,6 +1776,15 @@
 
 UML_LOOK               = NO
 
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside
+# the class node. If there are many fields or methods and many nodes the
+# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
+# threshold limits the number of items for each type to make the size more
+# manageable. Set this to 0 for no limit. Note that the threshold may be
+# exceeded by 50% before the limit is enforced.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
 # If set to YES, the inheritance and collaboration graphs will show the
 # relations between templates and their instances.
 
@@ -1499,11 +1821,11 @@
 CALLER_GRAPH           = NO
 
 # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
-# will graphical hierarchy of all classes instead of a textual one.
+# will generate a graphical hierarchy of all classes instead of a textual one.
 
 GRAPHICAL_HIERARCHY    = YES
 
-# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES
 # then doxygen will show the dependencies a directory has on other directories
 # in a graphical way. The dependency relations are determined by the #include
 # relations between the files in the directories.
@@ -1511,15 +1833,26 @@
 DIRECTORY_GRAPH        = YES
 
 # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
-# generated by dot. Possible values are png, jpg, or gif
-# If left blank png will be used.
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
 
 DOT_IMAGE_FORMAT       = png
 
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG        = NO
+
 # The tag DOT_PATH can be used to specify the path where the dot tool can be
 # found. If left blank, it is assumed the dot tool can be found in the path.
 
-DOT_PATH               = 
+DOT_PATH               =
 
 # The DOTFILE_DIRS tag can be used to specify one or more directories that
 # contain dot files that are included in the documentation (see the
@@ -1527,6 +1860,12 @@
 
 DOTFILE_DIRS           =
 
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS           =
+
 # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
 # nodes that will be shown in the graph. If the number of nodes in a graph
 # becomes larger than this value, doxygen will truncate the graph, which is
@@ -1535,7 +1874,7 @@
 # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
 # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
 
-DOT_GRAPH_MAX_NODES    = 50
+DOT_GRAPH_MAX_NODES    = 200
 
 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
 # graphs generated by dot. A depth value of 3 means that only nodes reachable
diff --git a/include/polarssl/aes.h b/include/polarssl/aes.h
index dfb9a0a..16721dd 100644
--- a/include/polarssl/aes.h
+++ b/include/polarssl/aes.h
@@ -128,7 +128,6 @@
  * both encryption and decryption. So a context initialized with
  * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
  *
- * both 
  * \param ctx      AES context
  * \param mode     AES_ENCRYPT or AES_DECRYPT
  * \param length   length of the input data
@@ -156,6 +155,7 @@
  * 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
diff --git a/include/polarssl/arc4.h b/include/polarssl/arc4.h
index aa8feaa..9333265 100644
--- a/include/polarssl/arc4.h
+++ b/include/polarssl/arc4.h
@@ -55,7 +55,7 @@
  *
  * \param ctx      ARC4 context to be initialized
  * \param key      the secret key
- * \param keylen   length of the key
+ * \param keylen   length of the key, in bytes
  */
 void arc4_setup( arc4_context *ctx, const unsigned char *key, unsigned int keylen );
 
diff --git a/include/polarssl/blowfish.h b/include/polarssl/blowfish.h
index b1932e7..a2cbd46 100644
--- a/include/polarssl/blowfish.h
+++ b/include/polarssl/blowfish.h
@@ -116,7 +116,6 @@
 /**
  * \brief          Blowfish CFB buffer encryption/decryption.
  *
- * both 
  * \param ctx      Blowfish context
  * \param mode     BLOWFISH_ENCRYPT or BLOWFISH_DECRYPT
  * \param length   length of the input data
@@ -140,6 +139,7 @@
  *
  * 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
diff --git a/include/polarssl/camellia.h b/include/polarssl/camellia.h
index e46e175..86e2125 100644
--- a/include/polarssl/camellia.h
+++ b/include/polarssl/camellia.h
@@ -134,7 +134,7 @@
  * \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,
@@ -154,6 +154,7 @@
  * 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
diff --git a/include/polarssl/cipher.h b/include/polarssl/cipher.h
index 0ab2b56..e5bde35 100644
--- a/include/polarssl/cipher.h
+++ b/include/polarssl/cipher.h
@@ -30,6 +30,12 @@
 #ifndef POLARSSL_CIPHER_H
 #define POLARSSL_CIPHER_H
 
+#include "config.h"
+
+#if defined(POLARSSL_GCM_C)
+#define POLARSSL_CIPHER_MODE_AEAD
+#endif
+
 #include <string.h>
 
 #if defined(_MSC_VER) && !defined(inline)
@@ -64,6 +70,9 @@
 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,
@@ -74,7 +83,11 @@
     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,
@@ -84,9 +97,13 @@
     POLARSSL_CIPHER_CAMELLIA_128_CTR,
     POLARSSL_CIPHER_CAMELLIA_192_CTR,
     POLARSSL_CIPHER_CAMELLIA_256_CTR,
+    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,
@@ -95,7 +112,7 @@
 
 typedef enum {
     POLARSSL_MODE_NONE = 0,
-    POLARSSL_MODE_NULL,
+    POLARSSL_MODE_ECB,
     POLARSSL_MODE_CBC,
     POLARSSL_MODE_CFB,
     POLARSSL_MODE_OFB,
@@ -139,6 +156,10 @@
     /** Base Cipher type (e.g. POLARSSL_CIPHER_ID_AES) */
     cipher_id_t cipher;
 
+    /** Encrypt using ECB */
+    int (*ecb_func)( void *ctx, operation_t mode,
+            const unsigned char *input, unsigned char *output );
+
     /** Encrypt using CBC */
     int (*cbc_func)( void *ctx, operation_t mode, size_t length, unsigned char *iv,
             const unsigned char *input, unsigned char *output );
@@ -151,6 +172,10 @@
     int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, unsigned char *nonce_counter,
             unsigned char *stream_block, const unsigned char *input, unsigned char *output );
 
+    /** Encrypt using STREAM */
+    int (*stream_func)( void *ctx, size_t length,
+                        const unsigned char *input, unsigned char *output );
+
     /** Set key for encryption purposes */
     int (*setkey_enc_func)( void *ctx, const unsigned char *key, unsigned int key_length);
 
@@ -182,9 +207,13 @@
     /** Name of the cipher */
     const char * name;
 
-    /** IV size, in bytes */
+    /** IV/NONCE size, in bytes.
+     *  For cipher that accept many sizes: recommended size */
     unsigned int iv_size;
 
+    /** Flag for ciphers that accept many sizes of IV/NONCE */
+    int accepts_variable_iv_size;
+
     /** block size, in bytes */
     unsigned int block_size;
 
@@ -219,6 +248,9 @@
     /** 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;
@@ -254,6 +286,22 @@
 const cipher_info_t *cipher_info_from_type( const cipher_type_t cipher_type );
 
 /**
+ * \brief               Returns the cipher information structure associated
+ *                      with the given cipher id, key size and mode.
+ *
+ * \param cipher_id     Id of the cipher to search for
+ *                      (e.g. POLARSSL_CIPHER_ID_AES)
+ * \param key_length    Length of the key in bits
+ * \param mode          Cipher mode (e.g. POLARSSL_MODE_CBC)
+ *
+ * \return              the cipher information structure associated with the
+ *                      given cipher_type, or NULL if not found.
+ */
+const cipher_info_t *cipher_info_from_values( const cipher_id_t cipher_id,
+                                              int key_length,
+                                              const cipher_mode_t mode );
+
+/**
  * \brief               Initialises and fills the cipher context structure with
  *                      the appropriate values.
  *
@@ -312,18 +360,22 @@
 }
 
 /**
- * \brief               Returns the size of the cipher's IV.
+ * \brief               Returns the size of the cipher's IV/NONCE in bytes.
  *
  * \param ctx           cipher's context. Must have been initialised.
  *
- * \return              size of the cipher's IV, or 0 if ctx has not 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 ctx->iv_size;
+
     return ctx->cipher_info->iv_size;
 }
 
@@ -425,15 +477,50 @@
 int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode );
 
 /**
- * \brief               Reset the given context, setting the IV to iv
+ * \brief               Set the initialization vector (IV) or nonce
  *
  * \param ctx           generic cipher context
- * \param iv            IV to use or NONCE_COUNTER in the case of a CTR-mode cipher
+ * \param iv            IV to use (or NONCE_COUNTER for CTR-mode ciphers)
+ * \param iv_len        IV length for ciphers with variable-size IV;
+ *                      discarded by ciphers with fixed-size IV.
+ *
+ * \returns             O on success, or POLARSSL_ERR_CIPHER_BAD_INPUT_DATA
+ *
+ * \note                Some ciphers don't use IVs nor NONCE. For these
+ *                      ciphers, this function has no effect.
+ */
+int cipher_set_iv( cipher_context_t *ctx,
+                   const unsigned char *iv, size_t iv_len );
+
+/**
+ * \brief               Finish preparation of the given context
+ *
+ * \param ctx           generic cipher context
  *
  * \returns             0 on success, POLARSSL_ERR_CIPHER_BAD_INPUT_DATA
  *                      if parameter verification fails.
  */
-int cipher_reset( cipher_context_t *ctx, const unsigned char *iv );
+int cipher_reset( cipher_context_t *ctx );
+
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+/**
+ * \brief               Add additional data (for AEAD ciphers).
+ *                      This function has no effect for non-AEAD ciphers.
+ *                      For AEAD ciphers, it may or may not be called
+ *                      repeatedly, and/or interleaved with calls to
+ *                      cipher_udpate(), depending on the cipher.
+ *                      E.g. for GCM is must be called exactly once, right
+ *                      after cipher_reset().
+ *
+ * \param ctx           generic cipher context
+ * \param ad            Additional data to use.
+ * \param ad_len        Length of ad.
+ *
+ * \returns             0 on success, or a specific error code.
+ */
+int cipher_update_ad( cipher_context_t *ctx,
+                      const unsigned char *ad, size_t ad_len );
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
 
 /**
  * \brief               Generic cipher update function. Encrypts/decrypts
@@ -442,6 +529,8 @@
  *                      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
@@ -457,6 +546,10 @@
  *                      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 );
@@ -468,7 +561,7 @@
  *                      the last block, and written to the output buffer.
  *
  * \param ctx           Generic cipher context
- * \param output        buffer to write data to. Needs block_size data available.
+ * \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
@@ -478,7 +571,39 @@
  *                      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);
+int cipher_finish( cipher_context_t *ctx,
+                   unsigned char *output, size_t *olen );
+
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+/**
+ * \brief               Write tag for AEAD ciphers.
+ *                      No effect for other ciphers.
+ *                      Must be called after cipher_finish().
+ *
+ * \param ctx           Generic cipher context
+ * \param tag           buffer to write the tag
+ * \param tag_len       Length of the tag to write
+ *
+ * \return              0 on success, or a specific error code.
+ */
+int cipher_write_tag( cipher_context_t *ctx,
+                      unsigned char *tag, size_t tag_len );
+
+/**
+ * \brief               Check tag for AEAD ciphers.
+ *                      No effect for other ciphers.
+ *                      Calling time depends on the cipher:
+ *                      for GCM, must be called after cipher_finish().
+ *
+ * \param ctx           Generic cipher context
+ * \param tag           Buffer holding the tag
+ * \param tag_len       Length of the tag to check
+ *
+ * \return              0 on success, or a specific error code.
+ */
+int cipher_check_tag( cipher_context_t *ctx,
+                      const unsigned char *tag, size_t tag_len );
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
 
 /**
  * \brief          Checkup routine
diff --git a/include/polarssl/cipher_wrap.h b/include/polarssl/cipher_wrap.h
index 4dabb44..9c26a10 100644
--- a/include/polarssl/cipher_wrap.h
+++ b/include/polarssl/cipher_wrap.h
@@ -38,6 +38,10 @@
 
 #if defined(POLARSSL_AES_C)
 
+extern const cipher_info_t aes_128_ecb_info;
+extern const cipher_info_t aes_192_ecb_info;
+extern const cipher_info_t aes_256_ecb_info;
+
 extern const cipher_info_t aes_128_cbc_info;
 extern const cipher_info_t aes_192_cbc_info;
 extern const cipher_info_t aes_256_cbc_info;
@@ -56,6 +60,7 @@
 
 #if defined(POLARSSL_GCM_C)
 extern const cipher_info_t aes_128_gcm_info;
+extern const cipher_info_t aes_192_gcm_info;
 extern const cipher_info_t aes_256_gcm_info;
 #endif /* POLARSSL_GCM_C */
 
@@ -63,6 +68,10 @@
 
 #if defined(POLARSSL_CAMELLIA_C)
 
+extern const cipher_info_t camellia_128_ecb_info;
+extern const cipher_info_t camellia_192_ecb_info;
+extern const cipher_info_t camellia_256_ecb_info;
+
 extern const cipher_info_t camellia_128_cbc_info;
 extern const cipher_info_t camellia_192_cbc_info;
 extern const cipher_info_t camellia_256_cbc_info;
@@ -83,6 +92,10 @@
 
 #if defined(POLARSSL_DES_C)
 
+extern const cipher_info_t des_ecb_info;
+extern const cipher_info_t des_ede_ecb_info;
+extern const cipher_info_t des_ede3_ecb_info;
+
 extern const cipher_info_t des_cbc_info;
 extern const cipher_info_t des_ede_cbc_info;
 extern const cipher_info_t des_ede3_cbc_info;
@@ -90,6 +103,7 @@
 #endif /* defined(POLARSSL_DES_C) */
 
 #if defined(POLARSSL_BLOWFISH_C)
+extern const cipher_info_t blowfish_ecb_info;
 extern const cipher_info_t blowfish_cbc_info;
 
 #if defined(POLARSSL_CIPHER_MODE_CFB)
diff --git a/include/polarssl/config.h b/include/polarssl/config.h
index d19c737..e738dee 100644
--- a/include/polarssl/config.h
+++ b/include/polarssl/config.h
@@ -1102,7 +1102,6 @@
  * Enable the TCP/IP networking routines.
  *
  * Module:  library/net.c
- * Caller:
  *
  * This module provides TCP/IP networking routines.
  */
@@ -1347,8 +1346,8 @@
  * Caller:  library/havege.c
  *
  * This module is used by the HAVEGE random number generator.
-#define POLARSSL_TIMING_C
  */
+#define POLARSSL_TIMING_C
 
 /**
  * \def POLARSSL_VERSION_C
diff --git a/include/polarssl/ctr_drbg.h b/include/polarssl/ctr_drbg.h
index 4c0fc17..756b5a3 100644
--- a/include/polarssl/ctr_drbg.h
+++ b/include/polarssl/ctr_drbg.h
@@ -201,6 +201,7 @@
 /**
  * \brief               Write a seed file
  *
+ * \param ctx           CTR_DRBG context
  * \param path          Name of the file
  *
  * \return              0 if successful, 1 on file error, or
@@ -212,6 +213,7 @@
  * \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, 1 on file error,
diff --git a/include/polarssl/dhm.h b/include/polarssl/dhm.h
index da787c3..09de70b 100644
--- a/include/polarssl/dhm.h
+++ b/include/polarssl/dhm.h
@@ -147,6 +147,9 @@
     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 _X;     /*!<  previous X        */
 }
 dhm_context;
 
@@ -219,11 +222,23 @@
  * \param ctx      DHM context
  * \param output   destination buffer
  * \param olen     number of chars written
+ * \param f_rng    RNG function, for blinding purposes
+ * \param p_rng    RNG parameter
  *
  * \return         0 if successful, or an POLARSSL_ERR_DHM_XXX error code
+ *
+ * \note           If f_rng is not NULL, it is used to blind the input as
+ *                 countermeasure against timing attacks. This is only useful
+ *                 when this function is called repeatedly with the same
+ *                 secret value (X field), eg when using DH key exchange as
+ *                 opposed to DHE. It is recommended to use a non-NULL f_rng
+ *                 only when needed, since otherwise this countermeasure has
+ *                 high overhead.
  */
 int dhm_calc_secret( dhm_context *ctx,
-                     unsigned char *output, size_t *olen );
+                     unsigned char *output, size_t *olen,
+                     int (*f_rng)(void *, unsigned char *, size_t),
+                     void *p_rng );
 
 /**
  * \brief          Free the components of a DHM key
diff --git a/include/polarssl/ecdh.h b/include/polarssl/ecdh.h
index 2184ab9..08de72c 100644
--- a/include/polarssl/ecdh.h
+++ b/include/polarssl/ecdh.h
@@ -70,12 +70,20 @@
  * \param z         Destination MPI (shared secret)
  * \param Q         Public key from other party
  * \param d         Our secret exponent
+ * \param f_rng     RNG function (see notes)
+ * \param p_rng     RNG parameter
  *
  * \return          0 if successful,
  *                  or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code
+ *
+ * \note            If f_rng is not NULL, it is used to implement
+ *                  countermeasures against potential elaborate timing
+ *                  attacks, see \c ecp_mul() for details.
  */
 int ecdh_compute_shared( const ecp_group *grp, mpi *z,
-                         const ecp_point *Q, const mpi *d );
+                         const ecp_point *Q, const mpi *d,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng );
 
 /**
  * \brief           Initialize context
@@ -95,8 +103,9 @@
  * \brief           Setup and write the ServerKeyExhange parameters
  *
  * \param ctx       ECDH context
- * \param buf       destination buffer
  * \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
  *
@@ -114,7 +123,7 @@
  * \brief           Parse the ServerKeyExhange parameters
  *
  * \param ctx       ECDH context
- * \param buf       $(start of input buffer)
+ * \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
@@ -129,6 +138,8 @@
  * \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
  */
@@ -156,11 +167,15 @@
  * \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 );
+                      unsigned char *buf, size_t blen,
+                      int (*f_rng)(void *, unsigned char *, size_t),
+                      void *p_rng );
 
 /**
  * \brief          Checkup routine
diff --git a/include/polarssl/ecdsa.h b/include/polarssl/ecdsa.h
index 47382e5..3159d89 100644
--- a/include/polarssl/ecdsa.h
+++ b/include/polarssl/ecdsa.h
@@ -132,7 +132,7 @@
  * \brief           Generate an ECDSA keypair on the given curve
  *
  * \param ctx       ECDSA context in which the keypair should be stored
- * \param grp       Group (elliptic curve) to use. One of the various
+ * \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
diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h
index c7689c1..346b3a8 100644
--- a/include/polarssl/ecp.h
+++ b/include/polarssl/ecp.h
@@ -316,7 +316,7 @@
  * \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 id );
+int ecp_use_known_dp( ecp_group *grp, ecp_group_id index );
 
 /**
  * \brief           Set a group from a TLS ECParameters record
@@ -366,8 +366,9 @@
  * \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 len       Buffer length
+ * \param blen      Buffer length
  *
  * \return          0 if successful,
  *                  or POLARSSL_ERR_ECP_BAD_INPUT_DATA
@@ -412,17 +413,31 @@
  * \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_MPI_MALLOC_FAILED if memory allocation failed
- *                  POLARSSL_ERR_ECP_GENERIC if m < 0 of m has greater bit
- *                  length than N, the number of points in the group.
+ *                  POLARSSL_ERR_ECP_BAD_INPUT_DATA if m < 0 of m has greater
+ *                  bit length than N, the number of points in the group.
  *
- * \note            This function executes a constant number of operations
- *                  for random m in the allowed range.
+ * \note            In order to prevent simple timing attacks, this function
+ *                  executes a constant number of operations (that is, point
+ *                  doubling and addition of distinct points) for random m in
+ *                  the allowed range.
+ *
+ * \note            If f_rng is not NULL, it is used to randomize projective
+ *                  coordinates of indermediate results, in order to prevent
+ *                  more elaborate timing attacks relying on intermediate
+ *                  operations. (This is a prophylactic measure since no such
+ *                  attack has been published yet.) Since this contermeasure
+ *                  has very low overhead, it is recommended to always provide
+ *                  a non-NULL f_rng parameter when using secret inputs.
  */
 int ecp_mul( const ecp_group *grp, ecp_point *R,
-             const mpi *m, const ecp_point *P );
+             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
diff --git a/include/polarssl/gcm.h b/include/polarssl/gcm.h
index 2bed342..1997c4b 100644
--- a/include/polarssl/gcm.h
+++ b/include/polarssl/gcm.h
@@ -1,7 +1,7 @@
 /**
  * \file gcm.h
  *
- * \brief Galois/Counter mode for AES
+ * \brief Galois/Counter mode for 128-bit block ciphers
  *
  *  Copyright (C) 2006-2013, Brainspark B.V.
  *
@@ -27,7 +27,7 @@
 #ifndef POLARSSL_GCM_H
 #define POLARSSL_GCM_H
 
-#include "aes.h"
+#include "cipher.h"
 
 #ifdef _MSC_VER
 #include <basetsd.h>
@@ -50,7 +50,7 @@
  * \brief          GCM context structure
  */
 typedef struct {
-    aes_context aes_ctx;        /*!< AES context used */
+    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 */
@@ -66,15 +66,17 @@
  * \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 POLARSSL_ERR_AES_INVALID_KEY_LENGTH
+ * \return          0 if successful, or a cipher specific error code
  */
-int gcm_init( gcm_context *ctx, const unsigned char *key, unsigned int keysize );
+int gcm_init( gcm_context *ctx, cipher_id_t cipher, const unsigned char *key,
+              unsigned int keysize );
 
 /**
- * \brief           GCM buffer encryption/decryption using AES
+ * \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.
@@ -108,7 +110,7 @@
                        unsigned char *tag );
 
 /**
- * \brief           GCM buffer authenticated decryption using AES
+ * \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
@@ -146,7 +148,7 @@
  * \param mode      GCM_ENCRYPT or GCM_DECRYPT
  * \param iv        initialization vector
  * \param iv_len    length of IV
- * \param add       additional data
+ * \param add       additional data (or NULL if length is 0)
  * \param add_len   length of additional data
  *
  * \return         0 if successful
@@ -182,14 +184,14 @@
 
 /**
  * \brief           Generic GCM finalisation function. Wraps up the GCM stream
- *                  and generated the tag. The tag can have a maximum length of
+ *                  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
+ * \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
+ * \return          0 if successful or POLARSSL_ERR_GCM_BAD_INPUT
  */
 int gcm_finish( gcm_context *ctx,
                 unsigned char *tag,
diff --git a/include/polarssl/md.h b/include/polarssl/md.h
index f7b8bd3..eecf781 100644
--- a/include/polarssl/md.h
+++ b/include/polarssl/md.h
@@ -60,7 +60,11 @@
     POLARSSL_MD_SHA512,
 } 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
diff --git a/include/polarssl/pk.h b/include/polarssl/pk.h
index 3bf68f3..f8c6cc8 100644
--- a/include/polarssl/pk.h
+++ b/include/polarssl/pk.h
@@ -184,7 +184,7 @@
 /**
  * \brief           Return information associated with the given PK type
  *
- * \param type      PK type to search for.
+ * \param pk_type   PK type to search for.
  *
  * \return          The PK info associated with the type or NULL if not found.
  */
@@ -321,6 +321,8 @@
  * \param output    Decrypted output
  * \param olen      Decrypted message lenght
  * \param osize     Size of the output buffer
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
  *
  * \return          0 on success, or a specific error code.
  */
@@ -338,6 +340,8 @@
  * \param output    Encrypted output
  * \param olen      Encrypted output length
  * \param osize     Size of the output buffer
+ * \param f_rng     RNG function
+ * \param p_rng     RNG parameter
  *
  * \return          0 on success, or a specific error code.
  */
diff --git a/include/polarssl/pkcs5.h b/include/polarssl/pkcs5.h
index 6c5b21a..dfff381 100644
--- a/include/polarssl/pkcs5.h
+++ b/include/polarssl/pkcs5.h
@@ -1,5 +1,5 @@
 /**
- * \file pkcs#5.h
+ * \file pkcs5.h
  *
  * \brief PKCS#5 functions
  *
@@ -59,7 +59,7 @@
  * \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 plen       length of password
+ * \param pwdlen     length of password
  * \param data       data to process
  * \param datalen    length of data
  * \param output     output buffer
diff --git a/include/polarssl/rsa.h b/include/polarssl/rsa.h
index 4e85ca6..71fbff2 100644
--- a/include/polarssl/rsa.h
+++ b/include/polarssl/rsa.h
@@ -89,6 +89,11 @@
     mpi RP;                     /*!<  cached R^2 mod P  */
     mpi RQ;                     /*!<  cached R^2 mod Q  */
 
+#if !defined(POLARSSL_RSA_NO_CRT)
+    mpi Vi;                     /*!<  cached blinding value     */
+    mpi Vf;                     /*!<  cached un-blinding value  */
+#endif
+
     int padding;                /*!<  RSA_PKCS_V15 for 1.5 padding and
                                       RSA_PKCS_v21 for OAEP/PSS         */
     int hash_id;                /*!<  Hash identifier of md_type_t as
diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h
index 354c6c2..cc60a4e 100644
--- a/include/polarssl/ssl.h
+++ b/include/polarssl/ssl.h
@@ -49,30 +49,15 @@
 #include "sha512.h"
 #endif
 
+// for session tickets
 #if defined(POLARSSL_AES_C)
 #include "aes.h"
 #endif
-#if defined(POLARSSL_ARC4_C)
-#include "arc4.h"
-#endif
-#if defined(POLARSSL_DES_C)
-#include "des.h"
-#endif
-#if defined(POLARSSL_CAMELLIA_C)
-#include "camellia.h"
-#endif
-#if defined(POLARSSL_GCM_C)
-#include "gcm.h"
-#endif
 
 #if defined(POLARSSL_X509_PARSE_C)
 #include "x509.h"
 #endif
 
-#if defined(POLARSSL_RSA_C)
-#include "rsa.h"
-#endif
-
 #if defined(POLARSSL_DHM_C)
 #include "dhm.h"
 #endif
@@ -442,40 +427,6 @@
 };
 
 /*
- * Helpers to find the correct size of the context in _ssl_transform
- * (in the long run, we'll use the cipher layer, but for now...)
- */
-#define SSL_MAX(a, b)       ( a > b ? a : b )
-#define SSL_CTX_MAX_0       0
-#if defined(POLARSSL_AES_C)
-#define SSL_CTX_MAX_1       SSL_MAX( SSL_CTX_MAX_0, sizeof( aes_context ) )
-#else
-#define SSL_CTX_MAX_1       SSL_CTX_MAX_0
-#endif
-#if defined(POLARSSL_ARC4_C)
-#define SSL_CTX_MAX_2       SSL_MAX( SSL_CTX_MAX_1, sizeof( arc4_context ) )
-#else
-#define SSL_CTX_MAX_2       SSL_CTX_MAX_1
-#endif
-#if defined(POLARSSL_DES_C)
-#define SSL_CTX_MAX_3       SSL_MAX( SSL_CTX_MAX_2, sizeof( des_context ) )
-#define SSL_CTX_MAX_4       SSL_MAX( SSL_CTX_MAX_3, sizeof( des3_context ) )
-#else
-#define SSL_CTX_MAX_4       SSL_CTX_MAX_2
-#endif
-#if defined(POLARSSL_CAMELLIA_C)
-#define SSL_CTX_MAX_5       SSL_MAX( SSL_CTX_MAX_4, sizeof( camellia_context ) )
-#else
-#define SSL_CTX_MAX_5       SSL_CTX_MAX_4
-#endif
-#if defined(POLARSSL_GCM_C)
-#define SSL_CTX_MAX_6       SSL_MAX( SSL_CTX_MAX_5, sizeof( gcm_context ) )
-#else
-#define SSL_CTX_MAX_6       SSL_CTX_MAX_5
-#endif
-#define SSL_CTX_MAX         SSL_CTX_MAX_6
-
-/*
  * This structure contains a full set of runtime transform parameters
  * either in negotiation or active.
  */
@@ -504,8 +455,8 @@
     md_context_t md_ctx_enc;            /*!<  MAC (encryption)        */
     md_context_t md_ctx_dec;            /*!<  MAC (decryption)        */
 
-    uint32_t ctx_enc[SSL_CTX_MAX / 4];  /*!<  encryption context      */
-    uint32_t ctx_dec[SSL_CTX_MAX / 4];  /*!<  decryption context      */
+    cipher_context_t cipher_ctx_enc;    /*!<  encryption context      */
+    cipher_context_t cipher_ctx_dec;    /*!<  decryption context      */
 
     /*
      * Session specific compression layer
@@ -516,17 +467,6 @@
 #endif
 };
 
-/* Not needed any more */
-#undef SSL_MAX
-#undef SSL_CTX_MAX_0
-#undef SSL_CTX_MAX_1
-#undef SSL_CTX_MAX_2
-#undef SSL_CTX_MAX_3
-#undef SSL_CTX_MAX_4
-#undef SSL_CTX_MAX_5
-#undef SSL_CTX_MAX_6
-#undef SSL_CTX_MAX
-
 /*
  * This structure contains the parameters only needed during handshake.
  */
@@ -1060,9 +1000,9 @@
  * \param ssl      SSL context
  * \param own_cert own public certificate chain
  * \param rsa_key  alternate implementation private RSA key
- * \param rsa_decrypt_func  alternate implementation of \c rsa_pkcs1_decrypt()
- * \param rsa_sign_func     alternate implementation of \c rsa_pkcs1_sign()
- * \param rsa_key_len_func  function returning length of RSA key in bytes
+ * \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.
  */
@@ -1195,7 +1135,7 @@
  *                 negotiate with the server during handshake)
  *
  * \param ssl      SSL context
- * \param mfl      Code for maximum fragment length (allowed values:
+ * \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)
  *
diff --git a/include/polarssl/x509write.h b/include/polarssl/x509write.h
index 715a646..552d453 100644
--- a/include/polarssl/x509write.h
+++ b/include/polarssl/x509write.h
@@ -97,6 +97,7 @@
 }
 x509write_cert;
 
+/* \} name */
 /* \} addtogroup x509_module */
 
 /**
@@ -134,7 +135,7 @@
  *                  (e.g. POLARSSL_MD_SHA1)
  *
  * \param ctx       CSR context to use
- * \param md_ald    MD algorithm to use
+ * \param md_alg    MD algorithm to use
  */
 void x509write_csr_set_md_alg( x509write_csr *ctx, md_type_t md_alg );
 
@@ -425,7 +426,7 @@
  *                        return value to determine where you should start
  *                        using the buffer
  *
- * \param rsa       CSR to write away
+ * \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)
@@ -490,7 +491,7 @@
  * \brief           Write a CSR (Certificate Signing Request) to a
  *                  PEM string
  *
- * \param rsa       CSR to write away
+ * \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)
diff --git a/library/cipher.c b/library/cipher.c
index 826d8fc..8fded81 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -34,8 +34,16 @@
 #include "polarssl/cipher.h"
 #include "polarssl/cipher_wrap.h"
 
+#if defined(POLARSSL_GCM_C)
+#include "polarssl/gcm.h"
+#endif
+
 #include <stdlib.h>
 
+#if defined(POLARSSL_ARC4_C) || defined(POLARSSL_CIPHER_NULL_CIPHER)
+#define POLARSSL_CIPHER_MODE_STREAM
+#endif
+
 #if defined _MSC_VER && !defined strcasecmp
 #define strcasecmp _stricmp
 #endif
@@ -43,6 +51,9 @@
 static const int supported_ciphers[] = {
 
 #if defined(POLARSSL_AES_C)
+        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,
@@ -59,9 +70,22 @@
         POLARSSL_CIPHER_AES_256_CTR,
 #endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
 
+#if defined(POLARSSL_GCM_C)
+        POLARSSL_CIPHER_AES_128_GCM,
+        POLARSSL_CIPHER_AES_192_GCM,
+        POLARSSL_CIPHER_AES_256_GCM,
+#endif /* defined(POLARSSL_GCM_C) */
+
 #endif /* defined(POLARSSL_AES_C) */
 
+#if defined(POLARSSL_ARC4_C)
+        POLARSSL_CIPHER_ARC4_128,
+#endif
+
 #if defined(POLARSSL_CAMELLIA_C)
+        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,
@@ -81,12 +105,16 @@
 #endif /* defined(POLARSSL_CAMELLIA_C) */
 
 #if defined(POLARSSL_DES_C)
+        POLARSSL_CIPHER_DES_ECB,
+        POLARSSL_CIPHER_DES_EDE_ECB,
+        POLARSSL_CIPHER_DES_EDE3_ECB,
         POLARSSL_CIPHER_DES_CBC,
         POLARSSL_CIPHER_DES_EDE_CBC,
         POLARSSL_CIPHER_DES_EDE3_CBC,
 #endif /* defined(POLARSSL_DES_C) */
 
 #if defined(POLARSSL_BLOWFISH_C)
+        POLARSSL_CIPHER_BLOWFISH_ECB,
         POLARSSL_CIPHER_BLOWFISH_CBC,
 
 #if defined(POLARSSL_CIPHER_MODE_CFB)
@@ -117,6 +145,13 @@
     switch ( cipher_type )
     {
 #if defined(POLARSSL_AES_C)
+        case POLARSSL_CIPHER_AES_128_ECB:
+            return &aes_128_ecb_info;
+        case POLARSSL_CIPHER_AES_192_ECB:
+            return &aes_192_ecb_info;
+        case POLARSSL_CIPHER_AES_256_ECB:
+            return &aes_256_ecb_info;
+
         case POLARSSL_CIPHER_AES_128_CBC:
             return &aes_128_cbc_info;
         case POLARSSL_CIPHER_AES_192_CBC:
@@ -145,6 +180,8 @@
 #if defined(POLARSSL_GCM_C)
         case POLARSSL_CIPHER_AES_128_GCM:
             return &aes_128_gcm_info;
+        case POLARSSL_CIPHER_AES_192_GCM:
+            return &aes_192_gcm_info;
         case POLARSSL_CIPHER_AES_256_GCM:
             return &aes_256_gcm_info;
 #endif /* defined(POLARSSL_GCM_C) */
@@ -152,6 +189,13 @@
 #endif
 
 #if defined(POLARSSL_CAMELLIA_C)
+        case POLARSSL_CIPHER_CAMELLIA_128_ECB:
+            return &camellia_128_ecb_info;
+        case POLARSSL_CIPHER_CAMELLIA_192_ECB:
+            return &camellia_192_ecb_info;
+        case POLARSSL_CIPHER_CAMELLIA_256_ECB:
+            return &camellia_256_ecb_info;
+
         case POLARSSL_CIPHER_CAMELLIA_128_CBC:
             return &camellia_128_cbc_info;
         case POLARSSL_CIPHER_CAMELLIA_192_CBC:
@@ -180,6 +224,13 @@
 #endif
 
 #if defined(POLARSSL_DES_C)
+        case POLARSSL_CIPHER_DES_ECB:
+            return &des_ecb_info;
+        case POLARSSL_CIPHER_DES_EDE_ECB:
+            return &des_ede_ecb_info;
+        case POLARSSL_CIPHER_DES_EDE3_ECB:
+            return &des_ede3_ecb_info;
+
         case POLARSSL_CIPHER_DES_CBC:
             return &des_cbc_info;
         case POLARSSL_CIPHER_DES_EDE_CBC:
@@ -194,6 +245,9 @@
 #endif
 
 #if defined(POLARSSL_BLOWFISH_C)
+        case POLARSSL_CIPHER_BLOWFISH_ECB:
+            return &blowfish_ecb_info;
+
         case POLARSSL_CIPHER_BLOWFISH_CBC:
             return &blowfish_cbc_info;
 
@@ -277,6 +331,20 @@
     if( !strcasecmp( "AES-256-CTR", cipher_name ) )
         return cipher_info_from_type( POLARSSL_CIPHER_AES_256_CTR );
 #endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+
+#if defined(POLARSSL_GCM_C)
+    if( !strcasecmp( "AES-128-GCM", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_AES_128_GCM );
+    if( !strcasecmp( "AES-192-GCM", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_AES_192_GCM );
+    if( !strcasecmp( "AES-256-GCM", cipher_name ) )
+        return cipher_info_from_type( POLARSSL_CIPHER_AES_256_GCM );
+#endif
+#endif /* POLARSSL_AES_C */
+
+#if defined(POLARSSL_ARC4_C)
+    if( !strcasecmp( "ARC4-128", cipher_name ) )
+        return( cipher_info_from_type( POLARSSL_CIPHER_ARC4_128 ) );
 #endif
 
 #if defined(POLARSSL_DES_C)
@@ -311,6 +379,185 @@
     return NULL;
 }
 
+const cipher_info_t *cipher_info_from_values( const cipher_id_t cipher_id,
+                                              int key_length,
+                                              const cipher_mode_t mode )
+{
+#if defined(POLARSSL_AES_C)
+    if( cipher_id == POLARSSL_CIPHER_ID_AES )
+    {
+        if( mode == POLARSSL_MODE_ECB )
+        {
+            if( key_length == 128 )
+                return &aes_128_ecb_info;
+            if( key_length == 192 )
+                return &aes_192_ecb_info;
+            if( key_length == 256 )
+                return &aes_256_ecb_info;
+        }
+
+        if( mode == POLARSSL_MODE_CBC )
+        {
+            if( key_length == 128 )
+                return &aes_128_cbc_info;
+            if( key_length == 192 )
+                return &aes_192_cbc_info;
+            if( key_length == 256 )
+                return &aes_256_cbc_info;
+        }
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+        if( mode == POLARSSL_MODE_CFB )
+        {
+            if( key_length == 128 )
+                return &aes_128_cfb128_info;
+            if( key_length == 192 )
+                return &aes_192_cfb128_info;
+            if( key_length == 256 )
+                return &aes_256_cfb128_info;
+        }
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+        if( mode == POLARSSL_MODE_CTR )
+        {
+            if( key_length == 128 )
+                return &aes_128_ctr_info;
+            if( key_length == 192 )
+                return &aes_192_ctr_info;
+            if( key_length == 256 )
+                return &aes_256_ctr_info;
+        }
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+
+#if defined(POLARSSL_GCM_C)
+        if( mode == POLARSSL_MODE_GCM )
+        {
+            if( key_length == 128 )
+                return &aes_128_gcm_info;
+            if( key_length == 192 )
+                return &aes_192_gcm_info;
+            if( key_length == 256 )
+                return &aes_256_gcm_info;
+        }
+#endif /* defined(POLARSSL_GCM_C) */
+    }
+#endif
+
+#if defined(POLARSSL_CAMELLIA_C)
+    if( cipher_id == POLARSSL_CIPHER_ID_CAMELLIA )
+    {
+        if( mode == POLARSSL_MODE_ECB )
+        {
+            if( key_length == 128 )
+                return &camellia_128_ecb_info;
+            if( key_length == 192 )
+                return &camellia_192_ecb_info;
+            if( key_length == 256 )
+                return &camellia_256_ecb_info;
+        }
+
+        if( mode == POLARSSL_MODE_CBC )
+        {
+            if( key_length == 128 )
+                return &camellia_128_cbc_info;
+            if( key_length == 192 )
+                return &camellia_192_cbc_info;
+            if( key_length == 256 )
+                return &camellia_256_cbc_info;
+        }
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+        if( mode == POLARSSL_MODE_CFB )
+        {
+            if( key_length == 128 )
+                return &camellia_128_cfb128_info;
+            if( key_length == 192 )
+                return &camellia_192_cfb128_info;
+            if( key_length == 256 )
+                return &camellia_256_cfb128_info;
+        }
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+        if( mode == POLARSSL_MODE_CTR )
+        {
+            if( key_length == 128 )
+                return &camellia_128_ctr_info;
+            if( key_length == 192 )
+                return &camellia_192_ctr_info;
+            if( key_length == 256 )
+                return &camellia_256_ctr_info;
+        }
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+    }
+#endif
+
+#if defined(POLARSSL_DES_C)
+    if( cipher_id == POLARSSL_CIPHER_ID_DES && key_length == 64 )
+    {
+        if( mode == POLARSSL_MODE_ECB )
+            return &des_ecb_info;
+
+        if( mode == POLARSSL_MODE_CBC )
+            return &des_cbc_info;
+    }
+
+    if( cipher_id == POLARSSL_CIPHER_ID_3DES )
+    {
+        if( mode == POLARSSL_MODE_ECB )
+        {
+            if( key_length == 128 )
+                return &des_ede_ecb_info;
+            if( key_length == 192 )
+                return &des_ede3_ecb_info;
+        }
+
+        if( mode == POLARSSL_MODE_CBC )
+        {
+            if( key_length == 128 )
+                return &des_ede_cbc_info;
+            if( key_length == 192 )
+                return &des_ede3_cbc_info;
+        }
+    }
+#endif
+
+#if defined(POLARSSL_ARC4_C)
+    if( cipher_id == POLARSSL_CIPHER_ID_ARC4 &&
+        key_length == 128 && mode == POLARSSL_MODE_STREAM )
+            return &arc4_128_info;
+#endif
+
+#if defined(POLARSSL_BLOWFISH_C)
+    if( cipher_id == POLARSSL_CIPHER_ID_BLOWFISH && key_length == 128 )
+    {
+        if( mode == POLARSSL_MODE_ECB )
+            return &blowfish_ecb_info;
+
+        if( mode == POLARSSL_MODE_CBC )
+            return &blowfish_cbc_info;
+
+#if defined(POLARSSL_CIPHER_MODE_CFB)
+        if( mode == POLARSSL_MODE_CFB )
+            return &blowfish_cfb64_info;
+#endif /* defined(POLARSSL_CIPHER_MODE_CFB) */
+
+#if defined(POLARSSL_CIPHER_MODE_CTR)
+        if( mode == POLARSSL_MODE_CTR )
+            return &blowfish_ctr_info;
+#endif /* defined(POLARSSL_CIPHER_MODE_CTR) */
+    }
+#endif
+
+#if defined(POLARSSL_CIPHER_NULL_CIPHER)
+    if( cipher_id == POLARSSL_CIPHER_ID_NULL )
+            return &null_cipher_info;
+#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
+
+    return NULL;
+}
+
 int cipher_init_ctx( cipher_context_t *ctx, const cipher_info_t *cipher_info )
 {
     if( NULL == cipher_info || NULL == ctx )
@@ -354,11 +601,6 @@
     ctx->key_length = key_length;
     ctx->operation = operation;
 
-#if defined(POLARSSL_CIPHER_NULL_CIPHER)
-    if( ctx->cipher_info->mode == POLARSSL_MODE_NULL )
-        return 0;
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
     /*
      * For CFB and CTR mode always use the encryption key schedule
      */
@@ -377,17 +619,53 @@
     return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
 }
 
-int cipher_reset( cipher_context_t *ctx, const unsigned char *iv )
+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;
 
+    if( ctx->cipher_info->accepts_variable_iv_size )
+        actual_iv_size = iv_len;
+    else
+        actual_iv_size = ctx->cipher_info->iv_size;
+
+    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;
 
-    memcpy( ctx->iv, iv, cipher_get_iv_size( ctx ) );
+    return 0;
+}
+
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+int cipher_update_ad( cipher_context_t *ctx,
+                      const unsigned char *ad, size_t ad_len )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+#if defined(POLARSSL_GCM_C)
+    if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
+    {
+        return gcm_starts( ctx->cipher_ctx, ctx->operation,
+                           ctx->iv, ctx->iv_size, ad, ad_len );
+    }
+#endif
 
     return 0;
 }
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
 
 int cipher_update( cipher_context_t *ctx, const unsigned char *input, size_t ilen,
         unsigned char *output, size_t *olen )
@@ -402,25 +680,36 @@
         return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
+    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( 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_NULL_CIPHER)
-    if( ctx->cipher_info->mode == POLARSSL_MODE_NULL )
-    {
-        *olen = ilen;
-
-        if( output == input )
-            return( 0 );
-
-        memcpy( output, input, ilen );
-        return 0;
-    }
-#endif /* defined(POLARSSL_CIPHER_NULL_CIPHER) */
-
     if( ctx->cipher_info->mode == POLARSSL_MODE_CBC )
     {
         /*
@@ -489,6 +778,7 @@
             {
                 return ret;
             }
+
             *olen += ilen;
         }
 
@@ -527,6 +817,21 @@
     }
 #endif
 
+#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
+
     return POLARSSL_ERR_CIPHER_FEATURE_UNAVAILABLE;
 }
 
@@ -686,7 +991,8 @@
     return 0;
 }
 
-int cipher_finish( cipher_context_t *ctx, unsigned char *output, size_t *olen)
+int cipher_finish( cipher_context_t *ctx,
+                   unsigned char *output, size_t *olen )
 {
     int ret = 0;
 
@@ -697,11 +1003,20 @@
 
     if( POLARSSL_MODE_CFB == ctx->cipher_info->mode ||
         POLARSSL_MODE_CTR == ctx->cipher_info->mode ||
-        POLARSSL_MODE_NULL == 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( POLARSSL_MODE_CBC == ctx->cipher_info->mode )
     {
         if( POLARSSL_ENCRYPT == ctx->operation )
@@ -797,6 +1112,63 @@
     return 0;
 }
 
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+int cipher_write_tag( cipher_context_t *ctx,
+                      unsigned char *tag, size_t tag_len )
+{
+    if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+    if( POLARSSL_ENCRYPT != ctx->operation )
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+#if defined(POLARSSL_GCM_C)
+    if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
+        return gcm_finish( ctx->cipher_ctx, tag, tag_len );
+#endif
+
+    return 0;
+}
+ 
+int cipher_check_tag( cipher_context_t *ctx,
+                      const unsigned char *tag, size_t tag_len )
+{
+    int ret;
+
+    if( NULL == ctx || NULL == ctx->cipher_info ||
+        POLARSSL_DECRYPT != ctx->operation )
+    {
+        return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+    }
+
+#if defined(POLARSSL_GCM_C)
+    if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
+    {
+        unsigned char check_tag[16];
+        size_t i;
+        int diff;
+
+        if( tag_len > sizeof( check_tag ) )
+            return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
+
+        if( 0 != ( ret = gcm_finish( 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_GCM_AUTH_FAILED );
+
+        return( 0 );
+    }
+#endif
+
+    return( 0 );
+}
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
+
 #if defined(POLARSSL_SELF_TEST)
 
 #include <stdio.h>
diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c
index baff2aa..862328f 100644
--- a/library/cipher_wrap.c
+++ b/library/cipher_wrap.c
@@ -37,6 +37,10 @@
 #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
@@ -49,6 +53,10 @@
 #include "polarssl/blowfish.h"
 #endif
 
+#if defined(POLARSSL_GCM_C)
+#include "polarssl/gcm.h"
+#endif
+
 #if defined(POLARSSL_MEMORY_C)
 #include "polarssl/memory.h"
 #else
@@ -60,6 +68,12 @@
 
 #if defined(POLARSSL_AES_C)
 
+static int aes_crypt_ecb_wrap( void *ctx, operation_t operation,
+        const unsigned char *input, unsigned char *output )
+{
+    return aes_crypt_ecb( (aes_context *) ctx, operation, input, output );
+}
+
 static int aes_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
         unsigned char *iv, const unsigned char *input, unsigned char *output )
 {
@@ -126,21 +140,57 @@
 
 const cipher_base_t aes_info = {
     POLARSSL_CIPHER_ID_AES,
+    aes_crypt_ecb_wrap,
     aes_crypt_cbc_wrap,
     aes_crypt_cfb128_wrap,
     aes_crypt_ctr_wrap,
+    NULL,
     aes_setkey_enc_wrap,
     aes_setkey_dec_wrap,
     aes_ctx_alloc,
     aes_ctx_free
 };
 
+const cipher_info_t aes_128_ecb_info = {
+    POLARSSL_CIPHER_AES_128_ECB,
+    POLARSSL_MODE_ECB,
+    128,
+    "AES-128-ECB",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_192_ecb_info = {
+    POLARSSL_CIPHER_AES_192_ECB,
+    POLARSSL_MODE_ECB,
+    192,
+    "AES-192-ECB",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
+const cipher_info_t aes_256_ecb_info = {
+    POLARSSL_CIPHER_AES_256_ECB,
+    POLARSSL_MODE_ECB,
+    256,
+    "AES-256-ECB",
+    16,
+    0,
+    16,
+    &aes_info
+};
+
 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
 };
@@ -151,6 +201,7 @@
     192,
     "AES-192-CBC",
     16,
+    0,
     16,
     &aes_info
 };
@@ -161,6 +212,7 @@
     256,
     "AES-256-CBC",
     16,
+    0,
     16,
     &aes_info
 };
@@ -172,6 +224,7 @@
     128,
     "AES-128-CFB128",
     16,
+    0,
     16,
     &aes_info
 };
@@ -182,6 +235,7 @@
     192,
     "AES-192-CFB128",
     16,
+    0,
     16,
     &aes_info
 };
@@ -192,6 +246,7 @@
     256,
     "AES-256-CFB128",
     16,
+    0,
     16,
     &aes_info
 };
@@ -204,6 +259,7 @@
     128,
     "AES-128-CTR",
     16,
+    0,
     16,
     &aes_info
 };
@@ -214,6 +270,7 @@
     192,
     "AES-192-CTR",
     16,
+    0,
     16,
     &aes_info
 };
@@ -224,20 +281,62 @@
     256,
     "AES-256-CTR",
     16,
+    0,
     16,
     &aes_info
 };
 #endif /* POLARSSL_CIPHER_MODE_CTR */
 
 #if defined(POLARSSL_GCM_C)
+static void *gcm_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( gcm_context ) );
+}
+
+static void gcm_ctx_free( void *ctx )
+{
+    polarssl_free( ctx );
+}
+
+static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+    return gcm_init( (gcm_context *) ctx, POLARSSL_CIPHER_ID_AES,
+                     key, key_length );
+}
+
+const cipher_base_t gcm_aes_info = {
+    POLARSSL_CIPHER_ID_AES,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    gcm_aes_setkey_wrap,
+    gcm_aes_setkey_wrap,
+    gcm_ctx_alloc,
+    gcm_ctx_free,
+};
+
 const cipher_info_t aes_128_gcm_info = {
     POLARSSL_CIPHER_AES_128_GCM,
     POLARSSL_MODE_GCM,
     128,
     "AES-128-GCM",
+    12,
+    1,
     16,
+    &gcm_aes_info
+};
+
+const cipher_info_t aes_192_gcm_info = {
+    POLARSSL_CIPHER_AES_192_GCM,
+    POLARSSL_MODE_GCM,
+    192,
+    "AES-192-GCM",
+    12,
+    1,
     16,
-    &aes_info
+    &gcm_aes_info
 };
 
 const cipher_info_t aes_256_gcm_info = {
@@ -245,9 +344,10 @@
     POLARSSL_MODE_GCM,
     256,
     "AES-256-GCM",
+    12,
+    1,
     16,
-    16,
-    &aes_info
+    &gcm_aes_info
 };
 #endif /* POLARSSL_GCM_C */
 
@@ -255,6 +355,12 @@
 
 #if defined(POLARSSL_CAMELLIA_C)
 
+static int camellia_crypt_ecb_wrap( void *ctx, operation_t operation,
+        const unsigned char *input, unsigned char *output )
+{
+    return camellia_crypt_ecb( (camellia_context *) ctx, operation, input, output );
+}
+
 static int camellia_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
         unsigned char *iv, const unsigned char *input, unsigned char *output )
 {
@@ -321,21 +427,57 @@
 
 const cipher_base_t camellia_info = {
     POLARSSL_CIPHER_ID_CAMELLIA,
+    camellia_crypt_ecb_wrap,
     camellia_crypt_cbc_wrap,
     camellia_crypt_cfb128_wrap,
     camellia_crypt_ctr_wrap,
+    NULL,
     camellia_setkey_enc_wrap,
     camellia_setkey_dec_wrap,
     camellia_ctx_alloc,
     camellia_ctx_free
 };
 
+const cipher_info_t camellia_128_ecb_info = {
+    POLARSSL_CIPHER_CAMELLIA_128_ECB,
+    POLARSSL_MODE_ECB,
+    128,
+    "CAMELLIA-128-ECB",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+const cipher_info_t camellia_192_ecb_info = {
+    POLARSSL_CIPHER_CAMELLIA_192_ECB,
+    POLARSSL_MODE_ECB,
+    192,
+    "CAMELLIA-192-ECB",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
+const cipher_info_t camellia_256_ecb_info = {
+    POLARSSL_CIPHER_CAMELLIA_256_ECB,
+    POLARSSL_MODE_ECB,
+    256,
+    "CAMELLIA-256-ECB",
+    16,
+    0,
+    16,
+    &camellia_info
+};
+
 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
 };
@@ -346,6 +488,7 @@
     192,
     "CAMELLIA-192-CBC",
     16,
+    0,
     16,
     &camellia_info
 };
@@ -356,6 +499,7 @@
     256,
     "CAMELLIA-256-CBC",
     16,
+    0,
     16,
     &camellia_info
 };
@@ -367,6 +511,7 @@
     128,
     "CAMELLIA-128-CFB128",
     16,
+    0,
     16,
     &camellia_info
 };
@@ -377,6 +522,7 @@
     192,
     "CAMELLIA-192-CFB128",
     16,
+    0,
     16,
     &camellia_info
 };
@@ -387,6 +533,7 @@
     256,
     "CAMELLIA-256-CFB128",
     16,
+    0,
     16,
     &camellia_info
 };
@@ -399,6 +546,7 @@
     128,
     "CAMELLIA-128-CTR",
     16,
+    0,
     16,
     &camellia_info
 };
@@ -409,6 +557,7 @@
     192,
     "CAMELLIA-192-CTR",
     16,
+    0,
     16,
     &camellia_info
 };
@@ -419,6 +568,7 @@
     256,
     "CAMELLIA-256-CTR",
     16,
+    0,
     16,
     &camellia_info
 };
@@ -428,6 +578,20 @@
 
 #if defined(POLARSSL_DES_C)
 
+static int des_crypt_ecb_wrap( void *ctx, operation_t operation,
+        const unsigned char *input, unsigned char *output )
+{
+    ((void) operation);
+    return des_crypt_ecb( (des_context *) ctx, input, output );
+}
+
+static int des3_crypt_ecb_wrap( void *ctx, operation_t operation,
+        const unsigned char *input, unsigned char *output )
+{
+    ((void) operation);
+    return des3_crypt_ecb( (des3_context *) ctx, input, output );
+}
+
 static int des_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
         unsigned char *iv, const unsigned char *input, unsigned char *output )
 {
@@ -528,63 +692,104 @@
 
 const cipher_base_t des_info = {
     POLARSSL_CIPHER_ID_DES,
+    des_crypt_ecb_wrap,
     des_crypt_cbc_wrap,
     des_crypt_cfb128_wrap,
     des_crypt_ctr_wrap,
+    NULL,
     des_setkey_enc_wrap,
     des_setkey_dec_wrap,
     des_ctx_alloc,
     des_ctx_free
 };
 
+const cipher_info_t des_ecb_info = {
+    POLARSSL_CIPHER_DES_ECB,
+    POLARSSL_MODE_ECB,
+    POLARSSL_KEY_LENGTH_DES,
+    "DES-ECB",
+    8,
+    0,
+    8,
+    &des_info
+};
+
 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
 };
 
 const cipher_base_t des_ede_info = {
     POLARSSL_CIPHER_ID_DES,
+    des3_crypt_ecb_wrap,
     des3_crypt_cbc_wrap,
     des_crypt_cfb128_wrap,
     des_crypt_ctr_wrap,
+    NULL,
     des3_set2key_enc_wrap,
     des3_set2key_dec_wrap,
     des3_ctx_alloc,
     des_ctx_free
 };
 
+const cipher_info_t des_ede_ecb_info = {
+    POLARSSL_CIPHER_DES_EDE_ECB,
+    POLARSSL_MODE_ECB,
+    POLARSSL_KEY_LENGTH_DES_EDE,
+    "DES-EDE-ECB",
+    8,
+    0,
+    8,
+    &des_ede_info
+};
+
 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
 };
 
 const cipher_base_t des_ede3_info = {
     POLARSSL_CIPHER_ID_DES,
+    des3_crypt_ecb_wrap,
     des3_crypt_cbc_wrap,
     des_crypt_cfb128_wrap,
     des_crypt_ctr_wrap,
+    NULL,
     des3_set3key_enc_wrap,
     des3_set3key_dec_wrap,
     des3_ctx_alloc,
     des_ctx_free
 };
 
+const cipher_info_t des_ede3_ecb_info = {
+    POLARSSL_CIPHER_DES_EDE3_ECB,
+    POLARSSL_MODE_ECB,
+    POLARSSL_KEY_LENGTH_DES_EDE3,
+    "DES-EDE3-ECB",
+    8,
+    0,
+    8,
+    &des_ede3_info
+};
 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
 };
@@ -592,6 +797,12 @@
 
 #if defined(POLARSSL_BLOWFISH_C)
 
+static int blowfish_crypt_ecb_wrap( void *ctx, operation_t operation,
+        const unsigned char *input, unsigned char *output )
+{
+    return blowfish_crypt_ecb( (blowfish_context *) ctx, operation, input, output );
+}
+
 static int blowfish_crypt_cbc_wrap( void *ctx, operation_t operation, size_t length,
         unsigned char *iv, const unsigned char *input, unsigned char *output )
 {
@@ -636,12 +847,7 @@
 #endif
 }
 
-static int blowfish_setkey_dec_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
-{
-    return blowfish_setkey( (blowfish_context *) ctx, key, key_length );
-}
-
-static int blowfish_setkey_enc_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+static int blowfish_setkey_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
 {
     return blowfish_setkey( (blowfish_context *) ctx, key, key_length );
 }
@@ -658,21 +864,35 @@
 
 const cipher_base_t blowfish_info = {
     POLARSSL_CIPHER_ID_BLOWFISH,
+    blowfish_crypt_ecb_wrap,
     blowfish_crypt_cbc_wrap,
     blowfish_crypt_cfb64_wrap,
     blowfish_crypt_ctr_wrap,
-    blowfish_setkey_enc_wrap,
-    blowfish_setkey_dec_wrap,
+    NULL,
+    blowfish_setkey_wrap,
+    blowfish_setkey_wrap,
     blowfish_ctx_alloc,
     blowfish_ctx_free
 };
 
+const cipher_info_t blowfish_ecb_info = {
+    POLARSSL_CIPHER_BLOWFISH_ECB,
+    POLARSSL_MODE_ECB,
+    128,
+    "BLOWFISH-ECB",
+    8,
+    0,
+    8,
+    &blowfish_info
+};
+
 const cipher_info_t blowfish_cbc_info = {
     POLARSSL_CIPHER_BLOWFISH_CBC,
     POLARSSL_MODE_CBC,
     128,
     "BLOWFISH-CBC",
     8,
+    0,
     8,
     &blowfish_info
 };
@@ -684,6 +904,7 @@
     128,
     "BLOWFISH-CFB64",
     8,
+    0,
     8,
     &blowfish_info
 };
@@ -696,6 +917,7 @@
     128,
     "BLOWFISH-CTR",
     8,
+    0,
     8,
     &blowfish_info
 };
@@ -703,15 +925,32 @@
 #endif /* POLARSSL_BLOWFISH_C */
 
 #if defined(POLARSSL_ARC4_C)
-static void * arc4_ctx_alloc( void )
+static int arc4_crypt_stream_wrap( void *ctx, size_t length,
+                                   const unsigned char *input,
+                                   unsigned char *output )
 {
-    return (void *) 1;
+    return( arc4_crypt( (arc4_context *) ctx, length, input, output ) );
 }
 
+static int arc4_setkey_wrap( void *ctx, const unsigned char *key,
+                             unsigned int key_length )
+{
+    /* we get key_length in bits, arc4 expects it in bytes */
+    if( key_length % 8 != 0)
+        return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA );
+
+    arc4_setup( (arc4_context *) ctx, key, key_length / 8 );
+    return( 0 );
+}
+
+static void * arc4_ctx_alloc( void )
+{
+    return polarssl_malloc( sizeof( arc4_context ) );
+}
 
 static void arc4_ctx_free( void *ctx )
 {
-    ((void) ctx);
+    polarssl_free( ctx );
 }
 
 const cipher_base_t arc4_base_info = {
@@ -720,7 +959,9 @@
     NULL,
     NULL,
     NULL,
-    NULL,
+    arc4_crypt_stream_wrap,
+    arc4_setkey_wrap,
+    arc4_setkey_wrap,
     arc4_ctx_alloc,
     arc4_ctx_free
 };
@@ -731,18 +972,37 @@
     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);
@@ -754,17 +1014,20 @@
     NULL,
     NULL,
     NULL,
-    NULL,
+    null_crypt_stream,
+    null_setkey,
+    null_setkey,
     null_ctx_alloc,
     null_ctx_free
 };
 
 const cipher_info_t null_cipher_info = {
     POLARSSL_CIPHER_NULL,
-    POLARSSL_MODE_NULL,
+    POLARSSL_MODE_STREAM,
     0,
     "NULL",
     0,
+    0,
     1,
     &null_base_info
 };
diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c
index 970de52..54fb791 100644
--- a/library/ctr_drbg.c
+++ b/library/ctr_drbg.c
@@ -242,7 +242,7 @@
     memset( seed, 0, CTR_DRBG_MAX_SEED_INPUT );
 
     /*
-     * Gather enropy_len bytes of entropy to seed state
+     * Gather entropy_len bytes of entropy to seed state
      */
     if( 0 != ctx->f_entropy( ctx->p_entropy, seed,
                              ctx->entropy_len ) )
diff --git a/library/dhm.c b/library/dhm.c
index 0c65dfe..b95f899 100644
--- a/library/dhm.c
+++ b/library/dhm.c
@@ -246,27 +246,112 @@
 }
 
 /*
+ * 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;
+
+    /*
+     * If Vi is initialized, update it by squaring it
+     */
+    if( ctx->Vi.p != NULL )
+    {
+        MPI_CHK( mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
+        MPI_CHK( mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
+    }
+    else
+    {
+        /* 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_shift_r( &ctx->Vi, 1 );
+
+            if( count++ > 10 )
+                return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE );
+        }
+        while( mpi_cmp_int( &ctx->Vi, 1 ) <= 0 );
+    }
+
+    /*
+     * If X did not change, update Vf by squaring it too
+     */
+    if( mpi_cmp_mpi( &ctx->X, &ctx->_X ) == 0 )
+    {
+        MPI_CHK( mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
+        MPI_CHK( mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
+        return( 0 );
+    }
+
+    /*
+     * Otherwise, compute Vf from scratch
+     */
+
+    /* 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 ) );
+
+    /* Remember secret associated with Vi and Vf */
+    MPI_CHK( mpi_copy( &ctx->_X, &ctx->X ) );;
+
+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 )
+                     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 );
 
-    MPI_CHK( mpi_exp_mod( &ctx->K, &ctx->GY, &ctx->X,
-                          &ctx->P, &ctx->RP ) );
-
     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 );
@@ -279,6 +364,7 @@
  */
 void dhm_free( dhm_context *ctx )
 {
+    mpi_free( &ctx->Vi ); mpi_free( &ctx->Vf );
     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 );
diff --git a/library/ecdh.c b/library/ecdh.c
index d76596e..8ef02f5 100644
--- a/library/ecdh.c
+++ b/library/ecdh.c
@@ -50,7 +50,9 @@
  * Compute shared secret (SEC1 3.3.1)
  */
 int ecdh_compute_shared( const ecp_group *grp, mpi *z,
-                         const ecp_point *Q, const mpi *d )
+                         const ecp_point *Q, const mpi *d,
+                         int (*f_rng)(void *, unsigned char *, size_t),
+                         void *p_rng )
 {
     int ret;
     ecp_point P;
@@ -62,7 +64,7 @@
      */
     MPI_CHK( ecp_check_pubkey( grp, Q ) );
 
-    MPI_CHK( ecp_mul( grp, &P, d, Q ) );
+    MPI_CHK( ecp_mul( grp, &P, d, Q, f_rng, p_rng ) );
 
     if( ecp_is_zero( &P ) )
     {
@@ -202,16 +204,20 @@
  * Derive and export the shared secret
  */
 int ecdh_calc_secret( ecdh_context *ctx, size_t *olen,
-                      unsigned char *buf, size_t blen )
+                      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 ) )
-                != 0 )
+    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 );
diff --git a/library/ecdsa.c b/library/ecdsa.c
index 67774c9..dc169ce 100644
--- a/library/ecdsa.c
+++ b/library/ecdsa.c
@@ -161,9 +161,12 @@
 
     /*
      * 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 ) );
-    MPI_CHK( ecp_mul( grp, &P, &u2, Q ) );
+    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 ) )
@@ -217,8 +220,8 @@
                            void *p_rng )
 {
     int ret;
-    unsigned char buf[MAX_SIG_LEN];
-    unsigned char *p = buf + MAX_SIG_LEN - 1;
+    unsigned char buf[MAX_SIG_LEN + 3];
+    unsigned char *p = buf + MAX_SIG_LEN;
     size_t len = 0;
 
     if( ( ret = ecdsa_sign( &ctx->grp, &ctx->r, &ctx->s, &ctx->d,
diff --git a/library/ecp.c b/library/ecp.c
index 09a021b..a80ddac 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -30,6 +30,17 @@
  * 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
+ *
+ * [1] OKEYA, Katsuyuki and TAKAGI, Tsuyoshi. The width-w NAF method provides
+ *     small memory and fast elliptic scalar multiplications secure against
+ *     side channel attacks. In : Topics in Cryptology—CT-RSA 2003. Springer
+ *     Berlin Heidelberg, 2003. p. 328-343.
+ *     <http://rd.springer.com/chapter/10.1007/3-540-36563-X_23>.
+ *
+ * [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>
  */
 
 #include "polarssl/config.h"
@@ -51,7 +62,7 @@
 #if defined(POLARSSL_SELF_TEST)
 /*
  * Counts of point addition and doubling operations.
- * Used to test resistance of point multiplication to SPA/timing attacks.
+ * Used to test resistance of point multiplication to simple timing attacks.
  */
 unsigned long add_count, dbl_count;
 #endif
@@ -777,7 +788,7 @@
  * (See for example Cohen's "A Course in Computational Algebraic Number
  * Theory", Algorithm 10.3.4.)
  *
- * Warning: fails if one of the points is zero!
+ * Warning: fails (returning an error) if one of the points is zero!
  * This should never happen, see choice of w in ecp_mul().
  */
 static int ecp_normalize_many( const ecp_group *grp,
@@ -1049,11 +1060,10 @@
 
 /*
  * Compute a modified width-w non-adjacent form (NAF) of a number,
- * with a fixed pattern for resistance to SPA/timing attacks,
- * see <http://rd.springer.com/chapter/10.1007/3-540-36563-X_23>.
- * (The resulting multiplication algorithm can also been seen as a
- * modification of 2^w-ary multiplication, with signed coefficients,
- * all of them odd.)
+ * with a fixed pattern for resistance to simple timing attacks (even SPA),
+ * see [1]. (The resulting multiplication algorithm can also been seen as a
+ * modification of 2^w-ary multiplication, with signed coefficients, all of
+ * them odd.)
  *
  * Input:
  * m must be an odd positive mpi less than w * k bits long
@@ -1145,6 +1155,51 @@
 }
 
 /*
+ * 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().
+ */
+static int ecp_randomize_coordinates( 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_shift_r( &l, 1 );
+
+        if( count++ > 10 )
+            return( POLARSSL_ERR_ECP_GENERIC );
+    }
+    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 );
+}
+
+/*
  * Maximum length of the precomputed table
  */
 #define MAX_PRE_LEN     ( 1 << (POLARSSL_ECP_WINDOW_SIZE - 1) )
@@ -1159,14 +1214,19 @@
 /*
  * Integer multiplication: R = m * P
  *
- * Based on fixed-pattern width-w NAF, see comments of ecp_w_naf_fixed()
- * and <http://rd.springer.com/chapter/10.1007/3-540-36563-X_23>.
+ * Based on fixed-pattern width-w NAF, see comments of ecp_w_naf_fixed().
  *
  * This function executes a fixed number of operations for
  * random m in the range 0 .. 2^nbits - 1.
+ *
+ * As an additional countermeasure against potential elaborate timing attacks,
+ * we randomize coordinates after each addition. This was suggested as a
+ * countermeasure against DPA in 5.3 of [2] (with the obvious adaptation that
+ * we use jacobian coordinates, not standard projective coordinates).
  */
 int ecp_mul( const ecp_group *grp, ecp_point *R,
-             const mpi *m, const ecp_point *P )
+             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;
@@ -1176,17 +1236,17 @@
     mpi M;
 
     if( mpi_cmp_int( m, 0 ) < 0 || mpi_msb( m ) > grp->nbits )
-        return( POLARSSL_ERR_ECP_GENERIC );
+        return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
 
     w = grp->nbits >= 521 ? 6 :
         grp->nbits >= 224 ? 5 :
-        4;
+                            4;
 
     /*
      * Make sure w is within the limits.
      * The last test ensures that none of the precomputed points is zero,
      * which wouldn't be handled correctly by ecp_normalize_many().
-     * It is only useful for small curves, as used in the test suite.
+     * It is only useful for very small curves, as used in the test suite.
      */
     if( w > POLARSSL_ECP_WINDOW_SIZE )
         w = POLARSSL_ECP_WINDOW_SIZE;
@@ -1237,6 +1297,10 @@
             MPI_CHK( ecp_add_mixed( grp, &Q, &Q, &T[ naf[i] ], +1 ) );
         }
 
+        /* Countermeasure (see comments above) */
+        if( f_rng != NULL )
+            ecp_randomize_coordinates( grp, &Q, f_rng, p_rng );
+
         if( i == 0 )
             break;
         i--;
@@ -1348,7 +1412,7 @@
     }
     while( mpi_cmp_int( d, 1 ) < 0 );
 
-    return( ecp_mul( grp, Q, d, &grp->G ) );
+    return( ecp_mul( grp, Q, d, &grp->G, f_rng, p_rng ) );
 }
 
 #if defined(POLARSSL_SELF_TEST)
@@ -1402,12 +1466,12 @@
 #endif /* POLARSSL_ECP_DP_SECP192R1_ENABLED */
 
     if( verbose != 0 )
-        printf( "  ECP test #1 (SPA resistance): " );
+        printf( "  ECP test #1 (resistance to simple timing attacks): " );
 
     add_count = 0;
     dbl_count = 0;
     MPI_CHK( mpi_read_string( &m, 16, exponents[0] ) );
-    MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G ) );
+    MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
 
     for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ )
     {
@@ -1417,7 +1481,7 @@
         dbl_count = 0;
 
         MPI_CHK( mpi_read_string( &m, 16, exponents[i] ) );
-        MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G ) );
+        MPI_CHK( ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) );
 
         if( add_count != add_c_prev || dbl_count != dbl_c_prev )
         {
diff --git a/library/gcm.c b/library/gcm.c
index 3e9969d..1dfc199 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -54,15 +54,17 @@
 }
 #endif
 
-static void gcm_gen_table( gcm_context *ctx )
+static int gcm_gen_table( gcm_context *ctx )
 {
-    int i, j;
+    int ret, i, j;
     uint64_t hi, lo;
     uint64_t vl, vh;
     unsigned char h[16];
+    size_t olen = 0;
 
     memset( h, 0, 16 );
-    aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, h, h );
+    if( ( ret = cipher_update( &ctx->cipher_ctx, h, 16, h, &olen ) ) != 0 )
+        return( ret );
 
     ctx->HH[0] = 0;
     ctx->HL[0] = 0;
@@ -99,18 +101,36 @@
             HiL[j] = vl ^ ctx->HL[j];
         }
     }
+
+    return( 0 );
 }
 
-int gcm_init( gcm_context *ctx, const unsigned char *key, unsigned int keysize )
+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) );
 
-    if( ( ret = aes_setkey_enc( &ctx->aes_ctx, key, keysize ) ) != 0 )
+    cipher_info = cipher_info_from_values( cipher, keysize, POLARSSL_MODE_ECB );
+    if( cipher_info == NULL )
+        return( POLARSSL_ERR_GCM_BAD_INPUT );
+
+    if( cipher_info->block_size != 16 )
+        return( POLARSSL_ERR_GCM_BAD_INPUT );
+
+    if( ( ret = cipher_init_ctx( &ctx->cipher_ctx, cipher_info ) ) != 0 )
         return( ret );
 
-    gcm_gen_table( ctx );
+    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 );
 }
@@ -176,10 +196,11 @@
                 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;
+    size_t use_len, olen = 0;
 
     memset( ctx->y, 0x00, sizeof(ctx->y) );
     memset( ctx->buf, 0x00, sizeof(ctx->buf) );
@@ -218,7 +239,11 @@
         gcm_mult( ctx, ctx->y, ctx->y );
     }
 
-    aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->y, ctx->base_ectr );
+    if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr,
+                             &olen ) ) != 0 )
+    {
+        return( ret );
+    }
 
     ctx->add_len = add_len;
     p = add;
@@ -243,11 +268,12 @@
                 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;
+    size_t use_len, olen = 0;
 
     if( output > input && (size_t) ( output - input ) < length )
         return( POLARSSL_ERR_GCM_BAD_INPUT );
@@ -263,7 +289,11 @@
             if( ++ctx->y[i - 1] != 0 )
                 break;
 
-        aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->y, ectr );
+        if( ( ret = cipher_update( &ctx->cipher_ctx, ctx->y, 16, ectr,
+                                   &olen ) ) != 0 )
+        {
+            return( ret );
+        }
 
         for( i = 0; i < use_len; i++ )
         {
@@ -293,11 +323,12 @@
     uint64_t orig_len = ctx->len * 8;
     uint64_t orig_add_len = ctx->add_len * 8;
 
-    memcpy( tag, ctx->base_ectr, tag_len );
-
     if( tag_len > 16 )
         return( POLARSSL_ERR_GCM_BAD_INPUT );
 
+    if( tag_len != 0 )
+        memcpy( tag, ctx->base_ectr, tag_len );
+
     if( orig_len || orig_add_len )
     {
         memset( work_buf, 0x00, 16 );
@@ -357,15 +388,22 @@
                       unsigned char *output )
 {
     unsigned char check_tag[16];
+    size_t i;
+    int diff;
 
     gcm_crypt_and_tag( ctx, GCM_DECRYPT, length, iv, iv_len, add, add_len, input, output, tag_len, check_tag );
 
-    if( memcmp( check_tag, tag, tag_len ) == 0 )
-        return( 0 );
+    /* Check tag in "constant-time" */
+    for( diff = 0, i = 0; i < tag_len; i++ )
+        diff |= tag[i] ^ check_tag[i];
 
-    memset( output, 0, length );
+    if( diff != 0 )
+    {
+        memset( output, 0, length );
+        return( POLARSSL_ERR_GCM_AUTH_FAILED );
+    }
 
-    return( POLARSSL_ERR_GCM_AUTH_FAILED );
+    return( 0 );
 }
 
 #if defined(POLARSSL_SELF_TEST)
@@ -605,6 +643,7 @@
     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++ )
     {
@@ -615,7 +654,7 @@
             if( verbose != 0 )
                 printf( "  AES-GCM-%3d #%d (%s): ", key_len, i, "enc" );
 
-            gcm_init( &ctx, key[key_index[i]], key_len );
+            gcm_init( &ctx, cipher, key[key_index[i]], key_len );
 
             ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT,
                                      pt_len[i],
@@ -639,7 +678,7 @@
             if( verbose != 0 )
                 printf( "  AES-GCM-%3d #%d (%s): ", key_len, i, "dec" );
 
-            gcm_init( &ctx, key[key_index[i]], key_len );
+            gcm_init( &ctx, cipher, key[key_index[i]], key_len );
 
             ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT,
                                      pt_len[i],
@@ -663,7 +702,7 @@
             if( verbose != 0 )
                 printf( "  AES-GCM-%3d #%d split (%s): ", key_len, i, "enc" );
 
-            gcm_init( &ctx, key[key_index[i]], key_len );
+            gcm_init( &ctx, cipher, key[key_index[i]], key_len );
 
             ret = gcm_starts( &ctx, GCM_ENCRYPT,
                               iv[iv_index[i]], iv_len[i],
@@ -726,7 +765,7 @@
             if( verbose != 0 )
                 printf( "  AES-GCM-%3d #%d split (%s): ", key_len, i, "dec" );
 
-            gcm_init( &ctx, key[key_index[i]], key_len );
+            gcm_init( &ctx, cipher, key[key_index[i]], key_len );
 
             ret = gcm_starts( &ctx, GCM_DECRYPT,
                               iv[iv_index[i]], iv_len[i],
diff --git a/library/pkcs12.c b/library/pkcs12.c
index e0d7207..335af7e 100644
--- a/library/pkcs12.c
+++ b/library/pkcs12.c
@@ -184,7 +184,10 @@
     if( ( ret = cipher_setkey( &cipher_ctx, key, keylen, mode ) ) != 0 )
         goto exit;
 
-    if( ( ret = cipher_reset( &cipher_ctx, iv ) ) != 0 )
+    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,
diff --git a/library/pkcs5.c b/library/pkcs5.c
index 9e3ce93..0b9830d 100644
--- a/library/pkcs5.c
+++ b/library/pkcs5.c
@@ -187,7 +187,10 @@
     if( ( ret = cipher_setkey( &cipher_ctx, key, keylen, mode ) ) != 0 )
         goto exit;
 
-    if( ( ret = cipher_reset( &cipher_ctx, iv ) ) != 0 )
+    if( ( ret = cipher_set_iv( &cipher_ctx, iv, enc_scheme_params.len ) ) != 0 )
+        goto exit;
+
+    if( ( ret = cipher_reset( &cipher_ctx ) ) != 0 )
         goto exit;
 
     if( ( ret = cipher_update( &cipher_ctx, data, datalen,
diff --git a/library/rsa.c b/library/rsa.c
index 10fd040..d39a09b 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -253,6 +253,41 @@
     return( 0 );
 }
 
+#if !defined(POLARSSL_RSA_NO_CRT)
+/*
+ * Generate or update blinding values, see section 10 of:
+ *  KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
+ *  DSS, and other systems. In : Advances in Cryptology—CRYPTO’96. Springer
+ *  Berlin Heidelberg, 1996. p. 104-113.
+ */
+static int rsa_prepare_blinding( rsa_context *ctx,
+                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+    int ret;
+
+    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->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 );
+    }
+
+    /* Unblinding value: Vf = random number */
+    MPI_CHK( mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) );
+
+    /* 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 ) );
+
+cleanup:
+    return( ret );
+}
+#endif
+
 /*
  * Do an RSA private key operation
  */
@@ -265,11 +300,8 @@
     int ret;
     size_t olen;
     mpi T, T1, T2;
-    mpi A, X;
-
 
     mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 );
-    mpi_init( &A ); mpi_init( &X );
 
     MPI_CHK( mpi_read_binary( &T, input, ctx->len ) );
     if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
@@ -284,14 +316,12 @@
     if( f_rng != NULL )
     {
         /*
-         * RSA Blinding
-         * A = rnd MPI
-         * T = A^E * T mod N
+         * Blinding
+         * T = T * Vi mod N
          */
-        MPI_CHK( mpi_fill_random( &A, ctx->len - 1, f_rng, p_rng ) );
-        MPI_CHK( mpi_exp_mod( &X, &A, &ctx->E, &ctx->N, NULL ) );
-        MPI_CHK( mpi_mul_mpi( &X, &X, &T ) );
-        MPI_CHK( mpi_mod_mpi( &T, &X, &ctx->N ) );
+        MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) );
+        MPI_CHK( mpi_mul_mpi( &T, &T, &ctx->Vi ) );
+        MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) );
     }
 
     /*
@@ -320,10 +350,9 @@
     {
         /*
          * Unblind
-         * T = T / A mod N
+         * T = T * Vf mod N
          */
-        MPI_CHK( mpi_inv_mod( &A, &A, &ctx->N ) );
-        MPI_CHK( mpi_mul_mpi( &T, &T, &A ) );
+        MPI_CHK( mpi_mul_mpi( &T, &T, &ctx->Vf ) );
         MPI_CHK( mpi_mod_mpi( &T, &T, &ctx->N ) );
     }
 #endif
@@ -334,7 +363,6 @@
 cleanup:
 
     mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 );
-    mpi_free( &A ); mpi_free( &X );
 
     if( ret != 0 )
         return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret );
@@ -1279,6 +1307,9 @@
     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->padding;
 
@@ -1294,6 +1325,7 @@
  */
 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 );
diff --git a/library/ssl_ciphersuites.c b/library/ssl_ciphersuites.c
index 6089ca8..fdd7348 100644
--- a/library/ssl_ciphersuites.c
+++ b/library/ssl_ciphersuites.c
@@ -844,14 +844,12 @@
         size_t i;
         size_t max = sizeof(supported_ciphersuites) / sizeof(int);
 
-        memset( supported_ciphersuites, 0x00, sizeof(supported_ciphersuites) );
-
-        /* Leave room for a final 0 */
         for( i = 0; i < max - 1 && p[i] != 0; i++ )
         {
             if( ssl_ciphersuite_from_id( p[i] ) != NULL )
                 *(q++) = p[i];
         }
+        *q = 0;
 
         supported_init = 1;
     }
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 0fccf34..19f0cb6 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -1711,9 +1711,11 @@
 
         ssl->handshake->pmslen = ssl->handshake->dhm_ctx.len;
 
+        /* No blinding needed for DHE, but will be needed for fixed DH! */
         if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
                                       ssl->handshake->premaster,
-                                     &ssl->handshake->pmslen ) ) != 0 )
+                                     &ssl->handshake->pmslen,
+                                     NULL, NULL ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
             return( ret );
@@ -1748,7 +1750,8 @@
         if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
                                       &ssl->handshake->pmslen,
                                        ssl->handshake->premaster,
-                                       POLARSSL_MPI_MAX_SIZE ) ) != 0 )
+                                       POLARSSL_MPI_MAX_SIZE,
+                                       ssl->f_rng, ssl->p_rng ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "ecdh_calc_secret", ret );
             return( ret );
@@ -1840,8 +1843,9 @@
 
         *(p++) = (unsigned char)( ssl->handshake->dhm_ctx.len >> 8 );
         *(p++) = (unsigned char)( ssl->handshake->dhm_ctx.len      );
+        /* No blinding needed since this is ephemeral DHM */
         if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
-                                      p, &n ) ) != 0 )
+                                      p, &n, NULL, NULL ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
             return( ret );
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 5bedcad..8edc57f 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -134,7 +134,7 @@
         if( p + cert_len > end )
             return( POLARSSL_ERR_SSL_BAD_INPUT_DATA );
 
-        session->peer_cert = polarssl_malloc( cert_len );
+        session->peer_cert = polarssl_malloc( sizeof( x509_cert ) );
 
         if( session->peer_cert == NULL )
             return( POLARSSL_ERR_SSL_MALLOC_FAILED );
@@ -143,8 +143,8 @@
 
         if( ( ret = x509parse_crt( session->peer_cert, p, cert_len ) ) != 0 )
         {
+            x509_free( session->peer_cert );
             polarssl_free( session->peer_cert );
-            free( session->peer_cert );
             session->peer_cert = NULL;
             return( ret );
         }
@@ -2384,9 +2384,11 @@
 
         ssl->handshake->pmslen = ssl->handshake->dhm_ctx.len;
 
+        /* No blinding needed for DHE, but will be needed for fixed DH! */
         if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
                                       ssl->handshake->premaster,
-                                     &ssl->handshake->pmslen ) ) != 0 )
+                                     &ssl->handshake->pmslen,
+                                      NULL, NULL ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
             return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS );
@@ -2410,7 +2412,8 @@
         if( ( ret = ecdh_calc_secret( &ssl->handshake->ecdh_ctx,
                                       &ssl->handshake->pmslen,
                                        ssl->handshake->premaster,
-                                       POLARSSL_MPI_MAX_SIZE ) ) != 0 )
+                                       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 );
@@ -2470,8 +2473,9 @@
 
         n = ssl->handshake->dhm_ctx.len;
 
+        /* No blinding needed since this is ephemeral DHM */
         if( ( ret = dhm_calc_secret( &ssl->handshake->dhm_ctx,
-                                      p, &n ) ) != 0 )
+                                      p, &n, NULL, NULL ) ) != 0 )
         {
             SSL_DEBUG_RET( 1, "dhm_calc_secret", ret );
             return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS );
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index ed95d3e..910205e 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -355,6 +355,7 @@
 
 int ssl_derive_keys( ssl_context *ssl )
 {
+    int ret = 0;
     unsigned char tmp[64];
     unsigned char keyblk[256];
     unsigned char *key1;
@@ -632,58 +633,62 @@
 
     switch( cipher_info->type )
     {
-#if defined(POLARSSL_ARC4_C)
         case POLARSSL_CIPHER_ARC4_128:
-            arc4_setup( (arc4_context *) transform->ctx_enc, key1,
-                        transform->keylen );
-            arc4_setup( (arc4_context *) transform->ctx_dec, key2,
-                        transform->keylen );
-            break;
-#endif
-
-#if defined(POLARSSL_DES_C)
         case POLARSSL_CIPHER_DES_EDE3_CBC:
-             des3_set3key_enc( (des3_context *) transform->ctx_enc, key1 );
-             des3_set3key_dec( (des3_context *) transform->ctx_dec, key2 );
-             break;
-#endif
-
-#if defined(POLARSSL_AES_C)
-        case POLARSSL_CIPHER_AES_128_CBC:
-        case POLARSSL_CIPHER_AES_256_CBC:
-            aes_setkey_enc( (aes_context*) transform->ctx_enc, key1,
-                            cipher_info->key_length );
-            aes_setkey_dec( (aes_context*) transform->ctx_dec, key2,
-                            cipher_info->key_length );
-            break;
-#endif
-
-#if defined(POLARSSL_CAMELLIA_C)
         case POLARSSL_CIPHER_CAMELLIA_128_CBC:
         case POLARSSL_CIPHER_CAMELLIA_256_CBC:
-            camellia_setkey_enc( (camellia_context*) transform->ctx_enc, key1,
-                                 cipher_info->key_length );
-            camellia_setkey_dec( (camellia_context*) transform->ctx_dec, key2,
-                                 cipher_info->key_length );
-            break;
-#endif
-
-#if defined(POLARSSL_DES_C)
+        case POLARSSL_CIPHER_AES_128_CBC:
+        case POLARSSL_CIPHER_AES_256_CBC:
         case POLARSSL_CIPHER_DES_CBC:
-            des_setkey_enc( (des_context *) transform->ctx_enc, key1 );
-            des_setkey_dec( (des_context *) transform->ctx_dec, key2 );
-            break;
-#endif
-
-#if defined(POLARSSL_GCM_C)
         case POLARSSL_CIPHER_AES_128_GCM:
         case POLARSSL_CIPHER_AES_256_GCM:
-            gcm_init( (gcm_context *) transform->ctx_enc, key1,
-                      cipher_info->key_length );
-            gcm_init( (gcm_context *) transform->ctx_dec, key2,
-                      cipher_info->key_length );
+            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( 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 );
+                }
+            }
             break;
-#endif
 
         case POLARSSL_CIPHER_NULL:
             break;
@@ -913,9 +918,11 @@
     }
     else
 #endif /* POLARSSL_CIPHER_NULL_CIPHER */
-#if defined(POLARSSL_ARC4_C)
     if( ssl->transform_out->ciphersuite_info->cipher == POLARSSL_CIPHER_ARC4_128 )
     {
+        int ret;
+        size_t olen = 0;
+
         padlen = 0;
 
         SSL_DEBUG_MSG( 3, ( "before encrypt: msglen = %d, "
@@ -925,17 +932,57 @@
         SSL_DEBUG_BUF( 4, "before encrypt: output payload",
                        ssl->out_msg, ssl->out_msglen );
 
-        arc4_crypt( (arc4_context *) ssl->transform_out->ctx_enc,
-                    ssl->out_msglen, ssl->out_msg,
-                    ssl->out_msg );
+        if( ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_reset", ret );
+            return( ret );
+        }
+
+        if( ( ret = cipher_set_iv( &ssl->transform_out->cipher_ctx_enc,
+                                   ssl->transform_out->iv_enc,
+                                   ssl->transform_out->ivlen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_set_iv", ret );
+            return( ret );
+        }
+
+        if( ( ret = cipher_update( &ssl->transform_out->cipher_ctx_enc,
+                                   ssl->out_msg, ssl->out_msglen, ssl->out_msg,
+                                   &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_update", ret );
+            return( ret );
+        }
+
+        if( ssl->out_msglen != olen )
+        {
+            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d",
+                                ssl->out_msglen, olen ) );
+            // TODO Real error number
+            return( -1 );
+        }
+
+        if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc,
+                                   ssl->out_msg + olen, &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_finish", ret );
+            return( ret );
+        }
+
+        if( 0 != olen )
+        {
+            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d",
+                                0, olen ) );
+            // TODO Real error number
+            return( -1 );
+        }
     }
     else
-#endif /* POLARSSL_ARC4_C */
 #if defined(POLARSSL_GCM_C)
     if( ssl->transform_out->ciphersuite_info->cipher == POLARSSL_CIPHER_AES_128_GCM ||
         ssl->transform_out->ciphersuite_info->cipher == POLARSSL_CIPHER_AES_256_GCM )
     {
-        size_t enc_msglen;
+        size_t enc_msglen, olen, totlen;
         unsigned char *enc_msg;
         unsigned char add_data[13];
         int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
@@ -966,6 +1013,9 @@
                 ssl->transform_out->iv_enc + ssl->transform_out->fixed_ivlen,
                 ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
 
+        SSL_DEBUG_BUF( 4, "IV used", ssl->out_iv,
+                       ssl->transform_out->ivlen - ssl->transform_out->fixed_ivlen );
+
         /*
          * Fix pointer positions and message length with added IV
          */
@@ -982,25 +1032,63 @@
                        ssl->out_msg, ssl->out_msglen );
 
         /*
-         * Adjust for tag
+         * Encrypt
+         */
+        if( ( ret = cipher_set_iv( &ssl->transform_out->cipher_ctx_enc,
+                                    ssl->transform_out->iv_enc,
+                                    ssl->transform_out->ivlen ) ) != 0 ||
+            ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc ) ) != 0 )
+        {
+            return( ret );
+        }
+
+        if( ( ret = cipher_update_ad( &ssl->transform_out->cipher_ctx_enc,
+                                      add_data, 13 ) ) != 0 )
+        {
+            return( ret );
+        }
+
+        if( ( ret = cipher_update( &ssl->transform_out->cipher_ctx_enc,
+                                   enc_msg, enc_msglen,
+                                   enc_msg, &olen ) ) != 0 )
+        {
+            return( ret );
+        }
+        totlen = olen;
+
+        if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc,
+                                   enc_msg + olen, &olen ) ) != 0 )
+        {
+            return( ret );
+        }
+        totlen += olen;
+
+        if( totlen != enc_msglen )
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( -1 );
+        }
+
+        /*
+         * Authenticate
          */
         ssl->out_msglen += 16;
 
-        gcm_crypt_and_tag( (gcm_context *) ssl->transform_out->ctx_enc,
-                GCM_ENCRYPT, enc_msglen,
-                ssl->transform_out->iv_enc, ssl->transform_out->ivlen,
-                add_data, 13,
-                enc_msg, enc_msg,
-                16, enc_msg + enc_msglen );
+        if( ( ret = cipher_write_tag( &ssl->transform_out->cipher_ctx_enc,
+                                      enc_msg + enc_msglen, 16 ) ) != 0 )
+        {
+            return( ret );
+        }
 
-        SSL_DEBUG_BUF( 4, "after encrypt: tag",
-                       enc_msg + enc_msglen, 16 );
+        SSL_DEBUG_BUF( 4, "after encrypt: tag", enc_msg + enc_msglen, 16 );
     }
     else
 #endif /* POLARSSL_GCM_C */
     {
+        int ret;
         unsigned char *enc_msg;
         size_t enc_msglen;
+        size_t olen = 0;
 
         padlen = ssl->transform_out->ivlen - ( ssl->out_msglen + 1 ) %
                  ssl->transform_out->ivlen;
@@ -1049,43 +1137,56 @@
         SSL_DEBUG_BUF( 4, "before encrypt: output payload",
                        ssl->out_iv, ssl->out_msglen );
 
-        switch( ssl->transform_out->ciphersuite_info->cipher )
+        if( ( ret = cipher_reset( &ssl->transform_out->cipher_ctx_enc ) ) != 0 )
         {
-#if defined(POLARSSL_DES_C)
-            case POLARSSL_CIPHER_DES_CBC:
-                des_crypt_cbc( (des_context *) ssl->transform_out->ctx_enc,
-                               DES_ENCRYPT, enc_msglen,
-                               ssl->transform_out->iv_enc, enc_msg, enc_msg );
-                break;
-
-            case POLARSSL_CIPHER_DES_EDE3_CBC:
-                des3_crypt_cbc( (des3_context *) ssl->transform_out->ctx_enc,
-                               DES_ENCRYPT, enc_msglen,
-                               ssl->transform_out->iv_enc, enc_msg, enc_msg );
-                break;
-#endif
-
-#if defined(POLARSSL_AES_C)
-            case POLARSSL_CIPHER_AES_128_CBC:
-            case POLARSSL_CIPHER_AES_256_CBC:
-                aes_crypt_cbc( (aes_context *) ssl->transform_out->ctx_enc,
-                               AES_ENCRYPT, enc_msglen,
-                               ssl->transform_out->iv_enc, enc_msg, enc_msg );
-                break;
-#endif
-
-#if defined(POLARSSL_CAMELLIA_C)
-            case POLARSSL_CIPHER_CAMELLIA_128_CBC:
-            case POLARSSL_CIPHER_CAMELLIA_256_CBC:
-                camellia_crypt_cbc( (camellia_context *) ssl->transform_out->ctx_enc,
-                                    CAMELLIA_ENCRYPT, enc_msglen,
-                                    ssl->transform_out->iv_enc, enc_msg, enc_msg );
-                break;
-#endif
-
-            default:
-                return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+            SSL_DEBUG_RET( 1, "cipher_reset", ret );
+            return( ret );
         }
+
+        if( ( ret = cipher_set_iv( &ssl->transform_out->cipher_ctx_enc,
+                                   ssl->transform_out->iv_enc,
+                                   ssl->transform_out->ivlen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_set_iv", ret );
+            return( ret );
+        }
+
+        if( ( ret = cipher_update( &ssl->transform_out->cipher_ctx_enc,
+                                   enc_msg, enc_msglen, enc_msg,
+                                   &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_update", ret );
+            return( ret );
+        }
+
+        enc_msglen -= olen;
+
+        if( ( ret = cipher_finish( &ssl->transform_out->cipher_ctx_enc,
+                                   enc_msg + olen, &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_finish", ret );
+            return( ret );
+        }
+
+        if( enc_msglen != olen )
+        {
+            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect %d %d",
+                                enc_msglen, olen ) );
+            // TODO Real error number
+            return( -1 );
+        }
+
+#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
     }
 
     for( i = 8; i > 0; i-- )
@@ -1123,11 +1224,53 @@
 #if defined(POLARSSL_ARC4_C)
     if( ssl->transform_in->ciphersuite_info->cipher == POLARSSL_CIPHER_ARC4_128 )
     {
+        int ret;
+        size_t olen = 0;
+
         padlen = 0;
 
-        arc4_crypt( (arc4_context *) ssl->transform_in->ctx_dec,
-                    ssl->in_msglen, ssl->in_msg,
-                    ssl->in_msg );
+        if( ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_reset", ret );
+            return( ret );
+        }
+
+        if( ( ret = cipher_set_iv( &ssl->transform_in->cipher_ctx_dec,
+                                   ssl->transform_in->iv_dec,
+                                   ssl->transform_in->ivlen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_set_iv", ret );
+            return( ret );
+        }
+
+        if( ( ret = cipher_update( &ssl->transform_in->cipher_ctx_dec,
+                                   ssl->in_msg, ssl->in_msglen, ssl->in_msg,
+                                   &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_update", ret );
+            return( ret );
+        }
+
+        if( ssl->in_msglen != olen )
+        {
+            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect" ) );
+            // TODO Real error number
+            return( -1 );
+        }
+
+        if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec,
+                                   ssl->in_msg + olen, &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_finish", ret );
+            return( ret );
+        }
+
+        if( 0 != olen )
+        {
+            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect" ) );
+            // TODO Real error number
+            return( -1 );
+        }
     }
     else
 #endif /* POLARSSL_ARC4_C */
@@ -1137,7 +1280,7 @@
     {
         unsigned char *dec_msg;
         unsigned char *dec_msg_result;
-        size_t dec_msglen;
+        size_t dec_msglen, olen, totlen;
         unsigned char add_data[13];
         int ret = POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE;
 
@@ -1168,21 +1311,54 @@
                                      ssl->transform_in->ivlen );
         SSL_DEBUG_BUF( 4, "TAG used", dec_msg + dec_msglen, 16 );
 
-        ret = gcm_auth_decrypt( (gcm_context *) ssl->transform_in->ctx_dec,
-                                 dec_msglen,
-                                 ssl->transform_in->iv_dec,
-                                 ssl->transform_in->ivlen,
-                                 add_data, 13,
-                                 dec_msg + dec_msglen, 16,
-                                 dec_msg, dec_msg_result );
-
-        if( ret != 0 )
+        /*
+         * Decrypt
+         */
+        if( ( ret = cipher_set_iv( &ssl->transform_in->cipher_ctx_dec,
+                                    ssl->transform_in->iv_dec,
+                                    ssl->transform_in->ivlen ) ) != 0 ||
+            ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec ) ) != 0 )
         {
-            SSL_DEBUG_MSG( 1, ( "AEAD decrypt failed on validation (ret = -0x%02x)",
-                                -ret ) );
+            return( ret );
+        }
 
+        if( ( ret = cipher_update_ad( &ssl->transform_in->cipher_ctx_dec,
+                                      add_data, 13 ) ) != 0 )
+        {
+            return( ret );
+        }
+
+        if( ( ret = cipher_update( &ssl->transform_in->cipher_ctx_dec,
+                                   dec_msg, dec_msglen,
+                                   dec_msg_result, &olen ) ) != 0 )
+        {
+            return( ret );
+        }
+        totlen = olen;
+
+        if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec,
+                                   dec_msg_result + olen, &olen ) ) != 0 )
+        {
+            return( ret );
+        }
+        totlen += olen;
+
+        if( totlen != dec_msglen )
+        {
+            SSL_DEBUG_MSG( 1, ( "should never happen" ) );
+            return( -1 );
+        }
+
+        /*
+         * Authenticate
+         */
+        if( ( ret = cipher_check_tag( &ssl->transform_in->cipher_ctx_dec,
+                                      dec_msg + dec_msglen, 16 ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_check_tag", ret );
             return( POLARSSL_ERR_SSL_INVALID_MAC );
         }
+
     }
     else
 #endif /* POLARSSL_GCM_C */
@@ -1190,10 +1366,12 @@
         /*
          * 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
@@ -1236,44 +1414,55 @@
         }
 #endif /* POLARSSL_SSL_PROTO_TLS1_1 || POLARSSL_SSL_PROTO_TLS1_2 */
 
-        switch( ssl->transform_in->ciphersuite_info->cipher )
+        if( ( ret = cipher_reset( &ssl->transform_in->cipher_ctx_dec ) ) != 0 )
         {
-#if defined(POLARSSL_DES_C)
-            case POLARSSL_CIPHER_DES_CBC:
-                des_crypt_cbc( (des_context *) ssl->transform_in->ctx_dec,
-                               DES_DECRYPT, dec_msglen,
-                               ssl->transform_in->iv_dec, dec_msg, dec_msg_result );
-                break;
-
-            case POLARSSL_CIPHER_DES_EDE3_CBC:
-                des3_crypt_cbc( (des3_context *) ssl->transform_in->ctx_dec,
-                               DES_DECRYPT, dec_msglen,
-                               ssl->transform_in->iv_dec, dec_msg, dec_msg_result );
-                break;
-#endif
-
-#if defined(POLARSSL_AES_C)
-            case POLARSSL_CIPHER_AES_128_CBC:
-            case POLARSSL_CIPHER_AES_256_CBC:
-                aes_crypt_cbc( (aes_context *) ssl->transform_in->ctx_dec,
-                               AES_DECRYPT, dec_msglen,
-                               ssl->transform_in->iv_dec, dec_msg, dec_msg_result );
-                break;
-#endif
-
-#if defined(POLARSSL_CAMELLIA_C)
-            case POLARSSL_CIPHER_CAMELLIA_128_CBC:
-            case POLARSSL_CIPHER_CAMELLIA_256_CBC:
-                camellia_crypt_cbc( (camellia_context *) ssl->transform_in->ctx_dec,
-                                    CAMELLIA_DECRYPT, dec_msglen,
-                                    ssl->transform_in->iv_dec, dec_msg, dec_msg_result );
-                break;
-#endif
-
-            default:
-                return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE );
+            SSL_DEBUG_RET( 1, "cipher_reset", ret );
+            return( ret );
         }
 
+        if( ( ret = cipher_set_iv( &ssl->transform_in->cipher_ctx_dec,
+                                   ssl->transform_in->iv_dec,
+                                   ssl->transform_in->ivlen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_set_iv", ret );
+            return( ret );
+        }
+
+        if( ( ret = cipher_update( &ssl->transform_in->cipher_ctx_dec,
+                                   dec_msg, dec_msglen, dec_msg_result,
+                                   &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_update", ret );
+            return( ret );
+        }
+
+        dec_msglen -= olen;
+        if( ( ret = cipher_finish( &ssl->transform_in->cipher_ctx_dec,
+                                   dec_msg_result + olen, &olen ) ) != 0 )
+        {
+            SSL_DEBUG_RET( 1, "cipher_finish", ret );
+            return( ret );
+        }
+
+        if( dec_msglen != olen )
+        {
+            SSL_DEBUG_MSG( 1, ( "total encrypted length incorrect" ) );
+            // TODO Real error number
+            return( -1 );
+        }
+
+#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 )
@@ -2272,6 +2461,13 @@
         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_free( ssl->session_negotiate->peer_cert );
+        polarssl_free( ssl->session_negotiate->peer_cert );
+    }
+
     if( ( ssl->session_negotiate->peer_cert = (x509_cert *) polarssl_malloc(
                     sizeof( x509_cert ) ) ) == NULL )
     {
diff --git a/library/x509parse.c b/library/x509parse.c
index b3725a7..d606615 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -2266,7 +2266,10 @@
         i = stat( entry_name, &sb );
 
         if( i == -1 )
+        {
+            closedir( dir );
             return( POLARSSL_ERR_X509_FILE_IO_ERROR );
+        }
 
         if( !S_ISREG( sb.st_mode ) )
             continue;
@@ -3737,6 +3740,29 @@
     return flags;
 }
 
+// Equal == 0, inequal == 1
+static int x509_name_cmp( const void *s1, const void *s2, size_t len )
+{
+    size_t i;
+    unsigned char diff;
+    const unsigned char *n1 = s1, *n2 = s2;
+
+    for( i = 0; i < len; i++ )
+    {
+        diff = n1[i] ^ n2[i];
+
+        if( ( n1[i] >= 'a' || n1[i] <= 'z' ) && ( diff == 0 || diff == 32 ) )
+            continue;
+
+        if( ( n1[i] >= 'A' || n1[i] <= 'Z' ) && ( diff == 0 || diff == 32 ) )
+            continue;
+
+        return( 1 );
+    }
+
+    return( 0 );
+}
+
 static int x509_wildcard_verify( const char *cn, x509_buf *name )
 {
     size_t i;
@@ -3758,7 +3784,7 @@
         return( 0 );
 
     if( strlen( cn ) - cn_idx == name->len - 1 &&
-        memcmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
+        x509_name_cmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 )
     {
         return( 1 );
     }
@@ -3937,7 +3963,7 @@
         ret = x509parse_verify_child( parent, grandparent, trust_ca, ca_crl, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
         if( ret != 0 )
             return( ret );
-    } 
+    }
     else
     {
         ret = x509parse_verify_top( parent, trust_ca, ca_crl, path_cnt + 1, &parent_flags, f_vrfy, p_vrfy );
@@ -3986,7 +4012,7 @@
             while( cur != NULL )
             {
                 if( cur->buf.len == cn_len &&
-                    memcmp( cn, cur->buf.p, cn_len ) == 0 )
+                    x509_name_cmp( cn, cur->buf.p, cn_len ) == 0 )
                     break;
 
                 if( cur->buf.len > 2 &&
@@ -4007,7 +4033,7 @@
                 if( OID_CMP( OID_AT_CN, &name->oid ) )
                 {
                     if( name->val.len == cn_len &&
-                        memcmp( name->val.p, cn, cn_len ) == 0 )
+                        x509_name_cmp( name->val.p, cn, cn_len ) == 0 )
                         break;
 
                     if( name->val.len > 2 &&
diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c
index 47b17d5..6caaad8 100644
--- a/programs/aes/crypt_and_hash.c
+++ b/programs/aes/crypt_and_hash.c
@@ -306,7 +306,12 @@
             fprintf( stderr, "cipher_setkey() returned error\n");
             goto exit;
         }
-        if( cipher_reset( &cipher_ctx, IV ) != 0 )
+        if( cipher_set_iv( &cipher_ctx, IV, 16 ) != 0 )
+        {
+            fprintf( stderr, "cipher_set_iv() returned error\n");
+            goto exit;
+        }
+        if( cipher_reset( &cipher_ctx ) != 0 )
         {
             fprintf( stderr, "cipher_reset() returned error\n");
             goto exit;
@@ -424,7 +429,8 @@
 
         cipher_setkey( &cipher_ctx, digest, cipher_info->key_length,
             POLARSSL_DECRYPT );
-        cipher_reset( &cipher_ctx, IV);
+        cipher_set_iv( &cipher_ctx, IV, 16 );
+        cipher_reset( &cipher_ctx );
 
         md_hmac_starts( &md_ctx, digest, 32 );
 
diff --git a/programs/pkey/dh_client.c b/programs/pkey/dh_client.c
index f06b906..c5c6f75 100644
--- a/programs/pkey/dh_client.c
+++ b/programs/pkey/dh_client.c
@@ -239,7 +239,7 @@
     fflush( stdout );
 
     n = dhm.len;
-    if( ( ret = dhm_calc_secret( &dhm, buf, &n ) ) != 0 )
+    if( ( ret = dhm_calc_secret( &dhm, buf, &n, NULL, NULL ) ) != 0 )
     {
         printf( " failed\n  ! dhm_calc_secret returned %d\n\n", ret );
         goto exit;
diff --git a/programs/pkey/dh_server.c b/programs/pkey/dh_server.c
index 1eba806..3382307 100644
--- a/programs/pkey/dh_server.c
+++ b/programs/pkey/dh_server.c
@@ -242,7 +242,7 @@
     printf( "\n  . Shared secret: " );
     fflush( stdout );
 
-    if( ( ret = dhm_calc_secret( &dhm, buf, &n ) ) != 0 )
+    if( ( ret = dhm_calc_secret( &dhm, buf, &n, NULL, NULL ) ) != 0 )
     {
         printf( " failed\n  ! dhm_calc_secret returned %d\n\n", ret );
         goto exit;
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 0650b3a..f9989ff 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -861,8 +861,8 @@
     {
         --opt.reconnect;
 
-        printf( "  ! Press a key to reconnect\n" );
-        (void) getchar();
+        // printf( "  ! Press a key to reconnect\n" );
+        // (void) getchar();
 
         printf( "  . Reconnecting with saved session..." );
         fflush( stdout );
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 8831190..8d2a8b3 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -822,7 +822,10 @@
         printf( " %d bytes read\n\n%s\n", len, (char *) buf );
 
         if( memcmp( buf, "SERVERQUIT", 10 ) == 0 )
+        {
+            ret = 0;
             goto exit;
+        }
 
         if( ret > 0 )
             break;
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index c33f5b5..baf7f4f 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -92,7 +92,7 @@
 #else
 int main( int argc, char *argv[] )
 {
-    int keysize;
+    int ret, keysize;
     unsigned long i, j, tsc;
     unsigned char tmp[64];
 #if defined(POLARSSL_ARC4_C)
@@ -297,7 +297,7 @@
 
         memset( buf, 0, sizeof( buf ) );
         memset( tmp, 0, sizeof( tmp ) );
-        gcm_init( &gcm, tmp, keysize );
+        gcm_init( &gcm, POLARSSL_CIPHER_ID_AES, tmp, keysize );
 
         set_alarm( 1 );
 
@@ -431,25 +431,33 @@
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
         buf[0] = 0;
-        rsa_public( &rsa, buf, buf );
+        ret = rsa_public( &rsa, buf, buf );
     }
 
-    printf( "%9lu  public/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu  public/s\n", i / 3 );
 
     printf( HEADER_FORMAT, "RSA-1024" );
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
         buf[0] = 0;
-        rsa_private( &rsa, buf, buf );
+        ret = rsa_private( &rsa, myrand, NULL, buf, buf );
     }
 
-    printf( "%9lu private/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu private/s\n", i / 3 );
 
     rsa_free( &rsa );
 
@@ -460,25 +468,33 @@
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
         buf[0] = 0;
-        rsa_public( &rsa, buf, buf );
+        ret = rsa_public( &rsa, buf, buf );
     }
 
-    printf( "%9lu  public/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu  public/s\n", i / 3 );
 
     printf( HEADER_FORMAT, "RSA-2048" );
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
         buf[0] = 0;
-        rsa_private( &rsa, buf, buf );
+        ret = rsa_private( &rsa, myrand, NULL, buf, buf );
     }
 
-    printf( "%9lu private/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu private/s\n", i / 3 );
 
     rsa_free( &rsa );
 
@@ -489,25 +505,33 @@
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
         buf[0] = 0;
-        rsa_public( &rsa, buf, buf );
+        ret = rsa_public( &rsa, buf, buf );
     }
 
-    printf( "%9lu  public/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu  public/s\n", i / 3 );
 
     printf( HEADER_FORMAT, "RSA-4096" );
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
         buf[0] = 0;
-        rsa_private( &rsa, buf, buf );
+        ret = rsa_private( &rsa, myrand, NULL, buf, buf );
     }
 
-    printf( "%9lu private/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu private/s\n", i / 3 );
 
     rsa_free( &rsa );
 #endif
@@ -525,13 +549,34 @@
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
-        dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL );
-        dhm_calc_secret( &dhm, buf, &olen );
+        olen = sizeof( buf );
+        ret |= dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL );
+        ret |= dhm_calc_secret( &dhm, buf, &olen, NULL, NULL );
     }
 
-    printf( "%9lu handshake/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu handshake/s\n", i / 3 );
+
+    printf( HEADER_FORMAT, "fixed-DHM-1024" );
+    fflush( stdout );
+    set_alarm( 3 );
+
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
+    {
+        olen = sizeof( buf );
+        ret |= dhm_calc_secret( &dhm, buf, &olen, myrand, NULL );
+    }
+
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu handshake/s\n", i / 3 );
 
     dhm_free( &dhm );
 
@@ -547,16 +592,36 @@
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
-        dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL );
-        dhm_calc_secret( &dhm, buf, &olen );
+        olen = sizeof( buf );
+        ret |= dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL );
+        ret |= dhm_calc_secret( &dhm, buf, &olen, myrand, NULL );
     }
 
-    printf( "%9lu handshake/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu handshake/s\n", i / 3 );
+
+    printf( HEADER_FORMAT, "fixed-DHM-2048" );
+    fflush( stdout );
+    set_alarm( 3 );
+
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
+    {
+        olen = sizeof( buf );
+        ret |= dhm_calc_secret( &dhm, buf, &olen, NULL, NULL );
+    }
+
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu handshake/s\n", i / 3 );
 
     dhm_free( &dhm );
-
     memset( &dhm, 0, sizeof( dhm_context ) );
 
     mpi_read_string( &dhm.P, 16, POLARSSL_DHM_RFC3526_MODP_3072_P );
@@ -569,13 +634,34 @@
     fflush( stdout );
     set_alarm( 3 );
 
-    for( i = 1; ! alarmed; i++ )
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
     {
-        dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL );
-        dhm_calc_secret( &dhm, buf, &olen );
+        olen = sizeof( buf );
+        ret |= dhm_make_public( &dhm, dhm.len, buf, dhm.len, myrand, NULL );
+        ret |= dhm_calc_secret( &dhm, buf, &olen, NULL, NULL );
     }
 
-    printf( "%9lu handshake/s\n", i / 3 );
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu handshake/s\n", i / 3 );
+
+    printf( HEADER_FORMAT, "fixed-DHM-3072" );
+    fflush( stdout );
+    set_alarm( 3 );
+
+    ret = 0;
+    for( i = 1; ! alarmed && ! ret ; i++ )
+    {
+        olen = sizeof( buf );
+        ret |= dhm_calc_secret( &dhm, buf, &olen, myrand, NULL );
+    }
+
+    if( ret != 0 )
+        printf( "FAILED\n" );
+    else
+        printf( "%9lu handshake/s\n", i / 3 );
 
     dhm_free( &dhm );
 #endif
diff --git a/programs/test/ecp-bench.c b/programs/test/ecp-bench.c
index 0a0e015..9231118 100644
--- a/programs/test/ecp-bench.c
+++ b/programs/test/ecp-bench.c
@@ -28,6 +28,29 @@
 
 #else
 
+static int myrand( void *rng_state, unsigned char *output, size_t len )
+{
+    size_t use_len;
+    int rnd;
+
+    if( rng_state != NULL )
+        rng_state  = NULL;
+
+    while( len > 0 )
+    {
+        use_len = len;
+        if( use_len > sizeof(int) )
+            use_len = sizeof(int);
+
+        rnd = rand();
+        memcpy( output, &rnd, use_len );
+        output += use_len;
+        len -= use_len;
+    }
+
+    return( 0 );
+}
+
 static void dhm_bench_case( const char *s, const char *p,
                             const char *g, const char *x )
 {
@@ -161,7 +184,7 @@
     set_alarm( 3 );
 
     for( i = 1; ! alarmed; i++ )
-        ecp_mul( &grp, &R, &M, &grp.G );
+        ecp_mul( &grp, &R, &M, &grp.G, myrand, NULL );
 
     printf( "%9lu mul/s\n", i / 3 );
 
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 2bd41c0..20f3c8d 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -40,9 +40,11 @@
 add_test_suite(blowfish)
 add_test_suite(camellia)
 add_test_suite(cipher cipher.aes)
+add_test_suite(cipher cipher.arc4)
 add_test_suite(cipher cipher.blowfish)
 add_test_suite(cipher cipher.camellia)
 add_test_suite(cipher cipher.des)
+add_test_suite(cipher cipher.gcm)
 add_test_suite(cipher cipher.null)
 add_test_suite(cipher cipher.padding)
 add_test_suite(ctr_drbg)
diff --git a/tests/Makefile b/tests/Makefile
index 4d70858..4d2bcba 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -27,6 +27,7 @@
 		test_suite_arc4									\
 		test_suite_base64		test_suite_blowfish		\
 		test_suite_camellia		test_suite_cipher.aes	\
+		test_suite_cipher.arc4	test_suite_cipher.gcm	\
 		test_suite_cipher.blowfish						\
 		test_suite_cipher.camellia						\
 		test_suite_cipher.des	test_suite_cipher.null	\
@@ -74,6 +75,14 @@
 	echo   "  Generate	$@"
 	scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.aes
 
+test_suite_cipher.arc4.c : suites/test_suite_cipher.function suites/test_suite_cipher.arc4.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
+	echo   "  Generate	$@"
+	scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.arc4
+
+test_suite_cipher.gcm.c : suites/test_suite_cipher.function suites/test_suite_cipher.gcm.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
+	echo   "  Generate	$@"
+	scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.gcm
+
 test_suite_cipher.blowfish.c : suites/test_suite_cipher.function suites/test_suite_cipher.blowfish.data scripts/generate_code.pl suites/helpers.function suites/main_test.function
 	echo   "  Generate	$@"
 	scripts/generate_code.pl suites test_suite_cipher test_suite_cipher.blowfish
@@ -158,6 +167,14 @@
 	echo   "  CC    	$@.c"
 	$(CC) $(CFLAGS) $(OFLAGS) $@.c	$(LDFLAGS) -o $@
 
+test_suite_cipher.arc4: test_suite_cipher.arc4.c ../library/libpolarssl.a
+	echo   "  CC    	$@.c"
+	$(CC) $(CFLAGS) $(OFLAGS) $@.c	$(LDFLAGS) -o $@
+
+test_suite_cipher.gcm: test_suite_cipher.gcm.c ../library/libpolarssl.a
+	echo   "  CC    	$@.c"
+	$(CC) $(CFLAGS) $(OFLAGS) $@.c	$(LDFLAGS) -o $@
+
 test_suite_cipher.blowfish: test_suite_cipher.blowfish.c ../library/libpolarssl.a
 	echo   "  CC    	$@.c"
 	$(CC) $(CFLAGS) $(OFLAGS) $@.c	$(LDFLAGS) -o $@
diff --git a/tests/suites/test_suite_cipher.aes.data b/tests/suites/test_suite_cipher.aes.data
index 2e45ae4..23d4c8c 100644
--- a/tests/suites/test_suite_cipher.aes.data
+++ b/tests/suites/test_suite_cipher.aes.data
@@ -764,3 +764,339 @@
 AES Encrypt and decrypt 32 bytes in multiple parts 1
 depends_on:POLARSSL_AES_C
 enc_dec_buf_multipart:POLARSSL_CIPHER_AES_256_CBC:256:16:16:
+
+AES Decrypt test vector #0
+depends_on:POLARSSL_AES_C:POLARSSL_CIPHER_PADDING_PKCS7
+decrypt_test_vec:POLARSSL_CIPHER_AES_128_CBC:POLARSSL_PADDING_PKCS7:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"23f710842b9bb9c32f26648c786807ca":"00000000000000000000000000000000":"":"":POLARSSL_ERR_CIPHER_INVALID_PADDING:0
+
+AES Decrypt test vector #1
+depends_on:POLARSSL_AES_C
+decrypt_test_vec:POLARSSL_CIPHER_AES_128_CBC:POLARSSL_PADDING_NONE:"ffffffffe00000000000000000000000":"00000000000000000000000000000000":"23f710842b9bb9c32f26648c786807ca":"00000000000000000000000000000000":"":"":0:0
+
+AES Decrypt test vector #2
+depends_on:POLARSSL_AES_C
+decrypt_test_vec:POLARSSL_CIPHER_AES_192_CBC:POLARSSL_PADDING_NONE:"000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"707b1dbb0ffa40ef7d95def421233fae":"fffffffff80000000000000000000000":"":"":0:0
+
+AES Decrypt test vector #3
+depends_on:POLARSSL_AES_C
+decrypt_test_vec:POLARSSL_CIPHER_AES_256_CBC:POLARSSL_PADDING_NONE:"0000000000000000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"49af6b372135acef10132e548f217b17":"ff000000000000000000000000000000":"":"":0:0
+
+AES Decrypt test vector #4
+depends_on:POLARSSL_AES_C:POLARSSL_CIPHER_MODE_CFB
+decrypt_test_vec:POLARSSL_CIPHER_AES_128_CFB128:-1:"fffffffe000000000000000000000000":"00000000000000000000000000000000":"1114bc2028009b923f0b01915ce5e7c4":"00000000000000000000000000000000":"":"":0:0:
+
+AES Decrypt test vector #5
+depends_on:POLARSSL_AES_C:POLARSSL_CIPHER_MODE_CFB
+decrypt_test_vec:POLARSSL_CIPHER_AES_192_CFB128:-1:"ffffffffffffffffffffffffffffffffffffffffffe00000":"00000000000000000000000000000000":"60136703374f64e860b48ce31f930716":"00000000000000000000000000000000":"":"":0:0
+
+AES Decrypt test vector #6
+depends_on:POLARSSL_AES_C:POLARSSL_CIPHER_MODE_CFB
+decrypt_test_vec:POLARSSL_CIPHER_AES_128_CFB128:-1:"ffffffffff800000000000000000000000000000000000000000000000000000":"00000000000000000000000000000000":"be66cfea2fecd6bf0ec7b4352c99bcaa":"00000000000000000000000000000000":"":"":0:0
+
+AES-128-ECB Encrypt NIST KAT #1
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"00000000000000000000000000000000":"f34481ec3cc627bacd5dc3fb08f273e6":"0336763e966d92595a567cc9ce537f5e":0
+
+AES-128-ECB Encrypt NIST KAT #2
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"00000000000000000000000000000000":"9798c4640bad75c7c3227db910174e72":"a9a1631bf4996954ebc093957b234589":0
+
+AES-128-ECB Encrypt NIST KAT #3
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"00000000000000000000000000000000":"96ab5c2ff612d9dfaae8c31f30c42168":"ff4f8391a6a40ca5b25d23bedd44a597":0
+
+AES-128-ECB Encrypt NIST KAT #4
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"e0000000000000000000000000000000":"00000000000000000000000000000000":"72a1da770f5d7ac4c9ef94d822affd97":0
+
+AES-128-ECB Encrypt NIST KAT #5
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"f0000000000000000000000000000000":"00000000000000000000000000000000":"970014d634e2b7650777e8e84d03ccd8":0
+
+AES-128-ECB Encrypt NIST KAT #6
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"f8000000000000000000000000000000":"00000000000000000000000000000000":"f17e79aed0db7e279e955b5f493875a7":0
+
+AES-128-ECB Encrypt NIST KAT #7
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"fffffffffffff0000000000000000000":"00000000000000000000000000000000":"7b90785125505fad59b13c186dd66ce3":0
+
+AES-128-ECB Encrypt NIST KAT #8
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"fffffffffffff8000000000000000000":"00000000000000000000000000000000":"8b527a6aebdaec9eaef8eda2cb7783e5":0
+
+AES-128-ECB Encrypt NIST KAT #9
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"fffffffffffffc000000000000000000":"00000000000000000000000000000000":"43fdaf53ebbc9880c228617d6a9b548b":0
+
+AES-128-ECB Encrypt NIST KAT #10
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"ffffffffffffffffffffffffffffc000":"00000000000000000000000000000000":"70c46bb30692be657f7eaa93ebad9897":0
+
+AES-128-ECB Encrypt NIST KAT #11
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"ffffffffffffffffffffffffffffe000":"00000000000000000000000000000000":"323994cfb9da285a5d9642e1759b224a":0
+
+AES-128-ECB Encrypt NIST KAT #12
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"fffffffffffffffffffffffffffff000":"00000000000000000000000000000000":"1dbf57877b7b17385c85d0b54851e371":0
+
+AES-128-ECB Encrypt NIST KAT #13
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"00000000000000000000000000000000":"ffffffffffffffc00000000000000000":"3a4d354f02bb5a5e47d39666867f246a":0
+
+AES-128-ECB Encrypt NIST KAT #14
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"00000000000000000000000000000000":"ffffffffffffffe00000000000000000":"d451b8d6e1e1a0ebb155fbbf6e7b7dc3":0
+
+AES-128-ECB Encrypt NIST KAT #15
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"00000000000000000000000000000000":"fffffffffffffff00000000000000000":"6898d4f42fa7ba6a10ac05e87b9f2080":0
+
+AES-128-ECB Encrypt NIST KAT #16
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"00000000000000000000000000000000":"ffffffffffffffffffffffffe0000000":"082eb8be35f442fb52668e16a591d1d6":0
+
+AES-128-ECB Encrypt NIST KAT #17
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"00000000000000000000000000000000":"fffffffffffffffffffffffff0000000":"e656f9ecf5fe27ec3e4a73d00c282fb3":0
+
+AES-128-ECB Encrypt NIST KAT #18
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_ENCRYPT:"00000000000000000000000000000000":"fffffffffffffffffffffffff8000000":"2ca8209d63274cd9a29bb74bcd77683a":0
+
+AES-128-ECB Decrypt NIST KAT #1
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_DECRYPT:"00000000000000000000000000000000":"db4f1aa530967d6732ce4715eb0ee24b":"ff000000000000000000000000000000":0
+
+AES-128-ECB Decrypt NIST KAT #2
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_DECRYPT:"00000000000000000000000000000000":"a81738252621dd180a34f3455b4baa2f":"ff800000000000000000000000000000":0
+
+AES-128-ECB Decrypt NIST KAT #3
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_DECRYPT:"00000000000000000000000000000000":"77e2b508db7fd89234caf7939ee5621a":"ffc00000000000000000000000000000":0
+
+AES-128-ECB Decrypt NIST KAT #4
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_DECRYPT:"00000000000000000000000000000000":"dc43be40be0e53712f7e2bf5ca707209":"6a118a874519e64e9963798a503f1d35":0
+
+AES-128-ECB Decrypt NIST KAT #5
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_DECRYPT:"00000000000000000000000000000000":"92beedab1895a94faa69b632e5cc47ce":"cb9fceec81286ca3e989bd979b0cb284":0
+
+AES-128-ECB Decrypt NIST KAT #6
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_DECRYPT:"00000000000000000000000000000000":"459264f4798f6a78bacb89c15ed3d601":"b26aeb1874e47ca8358ff22378f09144":0
+
+AES-128-ECB Decrypt NIST KAT #7
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_DECRYPT:"b69418a85332240dc82492353956ae0c":"a303d940ded8f0baff6f75414cac5243":"00000000000000000000000000000000":0
+
+AES-128-ECB Decrypt NIST KAT #8
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_DECRYPT:"71b5c08a1993e1362e4d0ce9b22b78d5":"c2dabd117f8a3ecabfbb11d12194d9d0":"00000000000000000000000000000000":0
+
+AES-128-ECB Decrypt NIST KAT #9
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_DECRYPT:"e234cdca2606b81f29408d5f6da21206":"fff60a4740086b3b9c56195b98d91a7b":"00000000000000000000000000000000":0
+
+AES-128-ECB Decrypt NIST KAT #10
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_DECRYPT:"ffffffffffffffff0000000000000000":"84be19e053635f09f2665e7bae85b42d":"00000000000000000000000000000000":0
+
+AES-128-ECB Decrypt NIST KAT #11
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_128_ECB:POLARSSL_DECRYPT:"ffffffffffffffff8000000000000000":"32cd652842926aea4aa6137bb2be2b5e":"00000000000000000000000000000000":0
+
+AES-192-ECB Encrypt NIST KAT #1
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_ENCRYPT:"000000000000000000000000000000000000000000000000":"fffffffffffffffffffff80000000000":"156f07767a85a4312321f63968338a01":0
+
+AES-192-ECB Encrypt NIST KAT #2
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_ENCRYPT:"000000000000000000000000000000000000000000000000":"fffffffffffffffffffffc0000000000":"15eec9ebf42b9ca76897d2cd6c5a12e2":0
+
+AES-192-ECB Encrypt NIST KAT #3
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_ENCRYPT:"000000000000000000000000000000000000000000000000":"fffffffffffffffffffffe0000000000":"db0d3a6fdcc13f915e2b302ceeb70fd8":0
+
+AES-192-ECB Encrypt NIST KAT #4
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_ENCRYPT:"000000000000000000000000000000000000000000000000":"51719783d3185a535bd75adc65071ce1":"4f354592ff7c8847d2d0870ca9481b7c":0
+
+AES-192-ECB Encrypt NIST KAT #5
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_ENCRYPT:"000000000000000000000000000000000000000000000000":"26aa49dcfe7629a8901a69a9914e6dfd":"d5e08bf9a182e857cf40b3a36ee248cc":0
+
+AES-192-ECB Encrypt NIST KAT #6
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_ENCRYPT:"000000000000000000000000000000000000000000000000":"941a4773058224e1ef66d10e0a6ee782":"067cd9d3749207791841562507fa9626":0
+
+AES-192-ECB Encrypt NIST KAT #7
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_ENCRYPT:"d2926527e0aa9f37b45e2ec2ade5853ef807576104c7ace3":"00000000000000000000000000000000":"dd619e1cf204446112e0af2b9afa8f8c":0
+
+AES-192-ECB Encrypt NIST KAT #8
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_ENCRYPT:"982215f4e173dfa0fcffe5d3da41c4812c7bcc8ed3540f93":"00000000000000000000000000000000":"d4f0aae13c8fe9339fbf9e69ed0ad74d":0
+
+AES-192-ECB Encrypt NIST KAT #9
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_ENCRYPT:"98c6b8e01e379fbd14e61af6af891596583565f2a27d59e9":"00000000000000000000000000000000":"19c80ec4a6deb7e5ed1033dda933498f":0
+
+AES-192-ECB Encrypt NIST KAT #10
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_ENCRYPT:"fffffffffffffffffffffffffff800000000000000000000":"00000000000000000000000000000000":"8dd274bd0f1b58ae345d9e7233f9b8f3":0
+
+AES-192-ECB Encrypt NIST KAT #11
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_ENCRYPT:"fffffffffffffffffffffffffffc00000000000000000000":"00000000000000000000000000000000":"9d6bdc8f4ce5feb0f3bed2e4b9a9bb0b":0
+
+AES-192-ECB Encrypt NIST KAT #12
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_ENCRYPT:"fffffffffffffffffffffffffffe00000000000000000000":"00000000000000000000000000000000":"fd5548bcf3f42565f7efa94562528d46":0
+
+AES-192-ECB Decrypt NIST KAT #1
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_DECRYPT:"fffffffffffffffffffffffffffffffff000000000000000":"bb2852c891c5947d2ed44032c421b85f":"00000000000000000000000000000000":0
+
+AES-192-ECB Decrypt NIST KAT #2
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_DECRYPT:"fffffffffffffffffffffffffffffffff800000000000000":"1b9f5fbd5e8a4264c0a85b80409afa5e":"00000000000000000000000000000000":0
+
+AES-192-ECB Decrypt NIST KAT #3
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_DECRYPT:"fffffffffffffffffffffffffffffffffc00000000000000":"30dab809f85a917fe924733f424ac589":"00000000000000000000000000000000":0
+
+AES-192-ECB Decrypt NIST KAT #4
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_DECRYPT:"61257134a518a0d57d9d244d45f6498cbc32f2bafc522d79":"cfe4d74002696ccf7d87b14a2f9cafc9":"00000000000000000000000000000000":0
+
+AES-192-ECB Decrypt NIST KAT #5
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_DECRYPT:"b0ab0a6a818baef2d11fa33eac947284fb7d748cfb75e570":"d2eafd86f63b109b91f5dbb3a3fb7e13":"00000000000000000000000000000000":0
+
+AES-192-ECB Decrypt NIST KAT #6
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_DECRYPT:"ee053aa011c8b428cdcc3636313c54d6a03cac01c71579d6":"9b9fdd1c5975655f539998b306a324af":"00000000000000000000000000000000":0
+
+AES-192-ECB Decrypt NIST KAT #7
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_DECRYPT:"000000000000000000000000000000000000000000000000":"275cfc0413d8ccb70513c3859b1d0f72":"1b077a6af4b7f98229de786d7516b639":0
+
+AES-192-ECB Decrypt NIST KAT #8
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_DECRYPT:"000000000000000000000000000000000000000000000000":"c9b8135ff1b5adc413dfd053b21bd96d":"9c2d8842e5f48f57648205d39a239af1":0
+
+AES-192-ECB Decrypt NIST KAT #9
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_DECRYPT:"000000000000000000000000000000000000000000000000":"4a3650c3371ce2eb35e389a171427440":"bff52510095f518ecca60af4205444bb":0
+
+AES-192-ECB Decrypt NIST KAT #10
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_DECRYPT:"000000000000000000000000000000000000000000000000":"b2099795e88cc158fd75ea133d7e7fbe":"ffffffffffffffffffffc00000000000":0
+
+AES-192-ECB Decrypt NIST KAT #11
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_DECRYPT:"000000000000000000000000000000000000000000000000":"a6cae46fb6fadfe7a2c302a34242817b":"ffffffffffffffffffffe00000000000":0
+
+AES-192-ECB Decrypt NIST KAT #12
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_192_ECB:POLARSSL_DECRYPT:"000000000000000000000000000000000000000000000000":"026a7024d6a902e0b3ffccbaa910cc3f":"fffffffffffffffffffff00000000000":0
+
+AES-256-ECB Encrypt NIST KAT #1
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_ENCRYPT:"c1cc358b449909a19436cfbb3f852ef8bcb5ed12ac7058325f56e6099aab1a1c":"00000000000000000000000000000000":"352065272169abf9856843927d0674fd":0
+
+AES-256-ECB Encrypt NIST KAT #2
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_ENCRYPT:"984ca75f4ee8d706f46c2d98c0bf4a45f5b00d791c2dfeb191b5ed8e420fd627":"00000000000000000000000000000000":"4307456a9e67813b452e15fa8fffe398":0
+
+AES-256-ECB Encrypt NIST KAT #3
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_ENCRYPT:"b43d08a447ac8609baadae4ff12918b9f68fc1653f1269222f123981ded7a92f":"00000000000000000000000000000000":"4663446607354989477a5c6f0f007ef4":0
+
+AES-256-ECB Encrypt NIST KAT #4
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_ENCRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"0b24af36193ce4665f2825d7b4749c98":"a9ff75bd7cf6613d3731c77c3b6d0c04":0
+
+AES-256-ECB Encrypt NIST KAT #5
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_ENCRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"761c1fe41a18acf20d241650611d90f1":"623a52fcea5d443e48d9181ab32c7421":0
+
+AES-256-ECB Encrypt NIST KAT #6
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_ENCRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"8a560769d605868ad80d819bdba03771":"38f2c7ae10612415d27ca190d27da8b4":0
+
+AES-256-ECB Encrypt NIST KAT #7
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_ENCRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"ffffff80000000000000000000000000":"36aff0ef7bf3280772cf4cac80a0d2b2":0
+
+AES-256-ECB Encrypt NIST KAT #8
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_ENCRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"ffffffc0000000000000000000000000":"1f8eedea0f62a1406d58cfc3ecea72cf":0
+
+AES-256-ECB Encrypt NIST KAT #9
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_ENCRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"ffffffe0000000000000000000000000":"abf4154a3375a1d3e6b1d454438f95a6":0
+
+AES-256-ECB Encrypt NIST KAT #10
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_ENCRYPT:"ffffffffffffffffffffffffffffffffffff8000000000000000000000000000":"00000000000000000000000000000000":"45d089c36d5c5a4efc689e3b0de10dd5":0
+
+AES-256-ECB Encrypt NIST KAT #11
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_ENCRYPT:"ffffffffffffffffffffffffffffffffffffc000000000000000000000000000":"00000000000000000000000000000000":"b4da5df4becb5462e03a0ed00d295629":0
+
+AES-256-ECB Encrypt NIST KAT #12
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_ENCRYPT:"ffffffffffffffffffffffffffffffffffffe000000000000000000000000000":"00000000000000000000000000000000":"dcf4e129136c1a4b7a0f38935cc34b2b":0
+
+AES-256-ECB Decrypt NIST KAT #1
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_DECRYPT:"fffffffffffffffffffffffffffffffffffffffffffffff00000000000000000":"edf61ae362e882ddc0167474a7a77f3a":"00000000000000000000000000000000":0
+
+AES-256-ECB Decrypt NIST KAT #2
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_DECRYPT:"fffffffffffffffffffffffffffffffffffffffffffffff80000000000000000":"6168b00ba7859e0970ecfd757efecf7c":"00000000000000000000000000000000":0
+
+AES-256-ECB Decrypt NIST KAT #3
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_DECRYPT:"fffffffffffffffffffffffffffffffffffffffffffffffc0000000000000000":"d1415447866230d28bb1ea18a4cdfd02":"00000000000000000000000000000000":0
+
+AES-256-ECB Decrypt NIST KAT #4
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_DECRYPT:"f8be9ba615c5a952cabbca24f68f8593039624d524c816acda2c9183bd917cb9":"a3944b95ca0b52043584ef02151926a8":"00000000000000000000000000000000":0
+
+AES-256-ECB Decrypt NIST KAT #5
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_DECRYPT:"797f8b3d176dac5b7e34a2d539c4ef367a16f8635f6264737591c5c07bf57a3e":"a74289fe73a4c123ca189ea1e1b49ad5":"00000000000000000000000000000000":0
+
+AES-256-ECB Decrypt NIST KAT #6
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_DECRYPT:"6838d40caf927749c13f0329d331f448e202c73ef52c5f73a37ca635d4c47707":"b91d4ea4488644b56cf0812fa7fcf5fc":"00000000000000000000000000000000":0
+
+AES-256-ECB Decrypt NIST KAT #7
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"623a52fcea5d443e48d9181ab32c7421":"761c1fe41a18acf20d241650611d90f1":0
+
+AES-256-ECB Decrypt NIST KAT #8
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"38f2c7ae10612415d27ca190d27da8b4":"8a560769d605868ad80d819bdba03771":0
+
+AES-256-ECB Decrypt NIST KAT #9
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"1bc704f1bce135ceb810341b216d7abe":"91fbef2d15a97816060bee1feaa49afe":0
+
+AES-256-ECB Decrypt NIST KAT #10
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"ddc6bf790c15760d8d9aeb6f9a75fd4e":"80000000000000000000000000000000":0
+
+AES-256-ECB Decrypt NIST KAT #11
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"0a6bdc6d4c1e6280301fd8e97ddbe601":"c0000000000000000000000000000000":0
+
+AES-256-ECB Decrypt NIST KAT #12
+depends_on:POLARSSL_AES_C
+test_vec_ecb:POLARSSL_CIPHER_AES_256_ECB:POLARSSL_DECRYPT:"0000000000000000000000000000000000000000000000000000000000000000":"9b80eefb7ebe2d2b16247aa0efc72f5d":"e0000000000000000000000000000000":0
diff --git a/tests/suites/test_suite_cipher.arc4.data b/tests/suites/test_suite_cipher.arc4.data
new file mode 100644
index 0000000..93d35b3
--- /dev/null
+++ b/tests/suites/test_suite_cipher.arc4.data
@@ -0,0 +1,110 @@
+Cipher Selftest
+depends_on:POLARSSL_SELF_TEST
+cipher_selftest:
+
+Decrypt empty buffer
+dec_empty_buf:
+
+ARC4 Encrypt and decrypt 0 bytes
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:0:-1
+
+ARC4 Encrypt and decrypt 1 byte
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:1:-1
+
+ARC4 Encrypt and decrypt 2 bytes
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:2:-1
+
+ARC4 Encrypt and decrypt 7 bytes
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:7:-1
+
+ARC4 Encrypt and decrypt 8 bytes
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:8:-1
+
+ARC4 Encrypt and decrypt 9 bytes
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:9:-1
+
+ARC4 Encrypt and decrypt 15 bytes
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:15:-1
+
+ARC4 Encrypt and decrypt 16 bytes
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:16:-1
+
+ARC4 Encrypt and decrypt 17 bytes
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:17:-1
+
+ARC4 Encrypt and decrypt 31 bytes
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:31:-1
+
+ARC4 Encrypt and decrypt 32 bytes
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:32:-1
+
+ARC4 Encrypt and decrypt 32 bytes
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:33:-1
+
+ARC4 Encrypt and decrypt 47 bytes
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:47:-1
+
+ARC4 Encrypt and decrypt 48 bytes
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:48:-1
+
+ARC4 Encrypt and decrypt 49 bytes
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf:POLARSSL_CIPHER_ARC4_128:"ARC4-128":128:49:-1
+
+ARC4 Encrypt and decrypt 0 bytes in multiple parts
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:0:0:
+
+ARC4 Encrypt and decrypt 1 bytes in multiple parts 1
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:1:0:
+
+ARC4 Encrypt and decrypt 1 bytes in multiple parts 2
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:0:1:
+
+ARC4 Encrypt and decrypt 16 bytes in multiple parts 1
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:16:0:
+
+ARC4 Encrypt and decrypt 16 bytes in multiple parts 2
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:0:16:
+
+ARC4 Encrypt and decrypt 16 bytes in multiple parts 3
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:1:15:
+
+ARC4 Encrypt and decrypt 16 bytes in multiple parts 4
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:15:1:
+
+ARC4 Encrypt and decrypt 22 bytes in multiple parts 1
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:15:7:
+
+ARC4 Encrypt and decrypt 22 bytes in multiple parts 1
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:16:6:
+
+ARC4 Encrypt and decrypt 22 bytes in multiple parts 1
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:17:6:
+
+ARC4 Encrypt and decrypt 32 bytes in multiple parts 1
+depends_on:POLARSSL_ARC4_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_ARC4_128:128:16:16:
diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function
index 1f7943a..898d98d 100644
--- a/tests/suites/test_suite_cipher.function
+++ b/tests/suites/test_suite_cipher.function
@@ -1,5 +1,9 @@
 /* BEGIN_HEADER */
 #include <polarssl/cipher.h>
+
+#if defined(POLARSSL_GCM_C)
+#include <polarssl/gcm.h>
+#endif
 /* END_HEADER */
 
 /* BEGIN_DEPENDENCIES
@@ -11,30 +15,26 @@
 void enc_dec_buf( int cipher_id, char *cipher_string, int key_len,
                   int length_val, int pad_mode )
 {
-    size_t length = length_val;
+    size_t length = length_val, outlen, total_len, i;
     unsigned char key[32];
     unsigned char iv[16];
+    unsigned char ad[13];
+    unsigned char tag[16];
+    unsigned char inbuf[64];
+    unsigned char encbuf[64];
+    unsigned char decbuf[64];
 
     const cipher_info_t *cipher_info;
     cipher_context_t ctx_dec;
     cipher_context_t ctx_enc;
 
-    unsigned char inbuf[64];
-    unsigned char encbuf[64];
-    unsigned char decbuf[64];
-
-    size_t outlen = 0;
-    size_t total_len = 0;
-
-    memset( key, 0, 32 );
-    memset( iv , 0, 16 );
-    
+    /*
+     * Prepare contexts
+     */
     memset( &ctx_dec, 0, sizeof( ctx_dec ) );
     memset( &ctx_enc, 0, sizeof( ctx_enc ) );
-    
-    memset( inbuf, 5, 64 );
-    memset( encbuf, 0, 64 );
-    memset( decbuf, 0, 64 );
+
+    memset( key, 0x2a, sizeof( key ) );
 
     /* Check and get info structures */
     cipher_info = cipher_info_from_type( cipher_id );
@@ -44,7 +44,7 @@
     /* Initialise enc and dec contexts */
     TEST_ASSERT( 0 == cipher_init_ctx( &ctx_dec, cipher_info ) );
     TEST_ASSERT( 0 == cipher_init_ctx( &ctx_enc, cipher_info ) );
-    
+
     TEST_ASSERT( 0 == cipher_setkey( &ctx_dec, key, key_len, POLARSSL_DECRYPT ) );
     TEST_ASSERT( 0 == cipher_setkey( &ctx_enc, key, key_len, POLARSSL_ENCRYPT ) );
 
@@ -54,8 +54,29 @@
         TEST_ASSERT( 0 == cipher_set_padding_mode( &ctx_enc, pad_mode ) );
     }
 
-    TEST_ASSERT( 0 == cipher_reset( &ctx_dec, iv ) );
-    TEST_ASSERT( 0 == cipher_reset( &ctx_enc, iv ) );
+    /*
+     * Do a few encode/decode cycles
+     */
+    for( i = 0; i < 3; i++ )
+    {
+    memset( iv , 0x00 + i, sizeof( iv ) );
+    memset( ad, 0x10 + i, sizeof( ad ) );
+    memset( inbuf, 0x20 + i, sizeof( inbuf ) );
+
+    memset( encbuf, 0, sizeof( encbuf ) );
+    memset( decbuf, 0, sizeof( decbuf ) );
+    memset( tag, 0, sizeof( tag ) );
+
+    TEST_ASSERT( 0 == cipher_set_iv( &ctx_dec, iv, sizeof( iv ) ) );
+    TEST_ASSERT( 0 == cipher_set_iv( &ctx_enc, iv, sizeof( iv ) ) );
+
+    TEST_ASSERT( 0 == cipher_reset( &ctx_dec ) );
+    TEST_ASSERT( 0 == cipher_reset( &ctx_enc ) );
+
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+    TEST_ASSERT( 0 == cipher_update_ad( &ctx_dec, ad, sizeof( ad ) - i ) );
+    TEST_ASSERT( 0 == cipher_update_ad( &ctx_enc, ad, sizeof( ad ) - i ) );
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
 
     /* encode length number of bytes from inbuf */
     TEST_ASSERT( 0 == cipher_update( &ctx_enc, inbuf, length, encbuf, &outlen ) );
@@ -69,6 +90,10 @@
     TEST_ASSERT( 0 == cipher_finish( &ctx_enc, encbuf + outlen, &outlen ) );
     total_len += outlen;
 
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+    TEST_ASSERT( 0 == cipher_write_tag( &ctx_enc, tag, sizeof( tag ) ) );
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
+
     TEST_ASSERT( total_len == length ||
                  ( total_len % cipher_get_block_size( &ctx_enc ) == 0 &&
                    total_len > length &&
@@ -86,10 +111,18 @@
     TEST_ASSERT( 0 == cipher_finish( &ctx_dec, decbuf + outlen, &outlen ) );
     total_len += outlen;
 
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+    TEST_ASSERT( 0 == cipher_check_tag( &ctx_dec, tag, sizeof( tag ) ) );
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
+
+    /* check result */
     TEST_ASSERT( total_len == length );
-
     TEST_ASSERT( 0 == memcmp(inbuf, decbuf, length) );
+    }
 
+    /*
+     * Done
+     */
     TEST_ASSERT( 0 == cipher_free_ctx( &ctx_dec ) );
     TEST_ASSERT( 0 == cipher_free_ctx( &ctx_enc ) );
 }
@@ -127,7 +160,11 @@
     TEST_ASSERT( 0 == cipher_init_ctx( &ctx, cipher_info ) );
     TEST_ASSERT( 0 == cipher_setkey( &ctx, key, key_len, POLARSSL_ENCRYPT ) );
     TEST_ASSERT( 0 == cipher_set_padding_mode( &ctx, pad_mode ) );
-    TEST_ASSERT( 0 == cipher_reset( &ctx, iv ) );
+    TEST_ASSERT( 0 == cipher_set_iv( &ctx, iv, 16 ) );
+    TEST_ASSERT( 0 == cipher_reset( &ctx ) );
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+    TEST_ASSERT( 0 == cipher_update_ad( &ctx, NULL, 0 ) );
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
 
     /* encode length number of bytes from inbuf */
     TEST_ASSERT( 0 == cipher_update( &ctx, inbuf, length, encbuf, &outlen ) );
@@ -160,7 +197,7 @@
     memset( encbuf, 0, 64 );
     memset( decbuf, 0, 64 );
 
-    /* Initialise enc and dec contexts */
+    /* Initialise context */
     cipher_info = cipher_info_from_type( POLARSSL_CIPHER_AES_128_CBC );
     TEST_ASSERT( NULL != cipher_info);
     
@@ -168,12 +205,19 @@
 
     TEST_ASSERT( 0 == cipher_setkey( &ctx_dec, key, 128, POLARSSL_DECRYPT ) );
 
-    TEST_ASSERT( 0 == cipher_reset( &ctx_dec, iv ) );
+    TEST_ASSERT( 0 == cipher_set_iv( &ctx_dec, iv, 16 ) );
+
+    TEST_ASSERT( 0 == cipher_reset( &ctx_dec ) );
+
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+    TEST_ASSERT( 0 == cipher_update_ad( &ctx_dec, NULL, 0 ) );
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
 
     /* decode 0-byte string */
     TEST_ASSERT( 0 == cipher_update( &ctx_dec, encbuf, 0, decbuf, &outlen ) );
     TEST_ASSERT( 0 == outlen );
-    TEST_ASSERT( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED == cipher_finish( &ctx_dec, decbuf + outlen, &outlen ) );
+    TEST_ASSERT( POLARSSL_ERR_CIPHER_FULL_BLOCK_EXPECTED == cipher_finish(
+                 &ctx_dec, decbuf + outlen, &outlen ) );
     TEST_ASSERT( 0 == outlen );
 
     TEST_ASSERT( 0 == cipher_free_ctx( &ctx_dec ) );
@@ -221,8 +265,16 @@
     TEST_ASSERT( 0 == cipher_setkey( &ctx_dec, key, key_len, POLARSSL_DECRYPT ) );
     TEST_ASSERT( 0 == cipher_setkey( &ctx_enc, key, key_len, POLARSSL_ENCRYPT ) );
 
-    TEST_ASSERT( 0 == cipher_reset( &ctx_dec, iv ) );
-    TEST_ASSERT( 0 == cipher_reset( &ctx_enc, iv ) );
+    TEST_ASSERT( 0 == cipher_set_iv( &ctx_dec, iv, 16 ) );
+    TEST_ASSERT( 0 == cipher_set_iv( &ctx_enc, iv, 16 ) );
+
+    TEST_ASSERT( 0 == cipher_reset( &ctx_dec ) );
+    TEST_ASSERT( 0 == cipher_reset( &ctx_enc ) );
+
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+    TEST_ASSERT( 0 == cipher_update_ad( &ctx_dec, NULL, 0 ) );
+    TEST_ASSERT( 0 == cipher_update_ad( &ctx_enc, NULL, 0 ) );
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
 
     /* encode length number of bytes from inbuf */
     TEST_ASSERT( 0 == cipher_update( &ctx_enc, inbuf, first_length, encbuf, &outlen ) );
@@ -248,7 +300,7 @@
     TEST_ASSERT( totaloutlen == length ||
                  ( totaloutlen % cipher_get_block_size( &ctx_dec ) == 0 &&
                    totaloutlen < length &&
-                   totaloutlen + cipher_get_block_size( &ctx_dec ) > length ) );
+                   totaloutlen + cipher_get_block_size( &ctx_dec ) >= length ) );
 
     TEST_ASSERT( 0 == cipher_finish( &ctx_dec, decbuf + outlen, &outlen ) );
     totaloutlen += outlen;
@@ -263,6 +315,120 @@
 /* END_CASE */
 
 /* BEGIN_CASE */
+void decrypt_test_vec( int cipher_id, int pad_mode,
+                       char *hex_key, char *hex_iv,
+                       char *hex_cipher, char *hex_clear,
+                       char *hex_ad, char *hex_tag,
+                       int finish_result, int tag_result )
+{
+    unsigned char key[50];
+    unsigned char iv[50];
+    unsigned char cipher[200];
+    unsigned char clear[200];
+    unsigned char ad[200];
+    unsigned char tag[20];
+    size_t key_len, iv_len, cipher_len, clear_len, ad_len, tag_len;
+    cipher_context_t ctx;
+    unsigned char output[200];
+    size_t outlen, total_len;
+
+    memset( key, 0x00, sizeof( key ) );
+    memset( iv, 0x00, sizeof( iv ) );
+    memset( cipher, 0x00, sizeof( cipher ) );
+    memset( clear, 0x00, sizeof( clear ) );
+    memset( ad, 0x00, sizeof( ad ) );
+    memset( tag, 0x00, sizeof( tag ) );
+    memset( output, 0x00, sizeof( output ) );
+
+    key_len = unhexify( key, hex_key );
+    iv_len = unhexify( iv, hex_iv );
+    cipher_len = unhexify( cipher, hex_cipher );
+    clear_len = unhexify( clear, hex_clear );
+    ad_len = unhexify( ad, hex_ad );
+    tag_len = unhexify( tag, hex_tag );
+
+    /* Prepare context */
+    TEST_ASSERT( 0 == cipher_init_ctx( &ctx,
+                                       cipher_info_from_type( cipher_id ) ) );
+    TEST_ASSERT( 0 == cipher_setkey( &ctx, key, 8 * key_len, POLARSSL_DECRYPT ) );
+    if( pad_mode != -1 )
+        TEST_ASSERT( 0 == cipher_set_padding_mode( &ctx, pad_mode ) );
+    TEST_ASSERT( 0 == cipher_set_iv( &ctx, iv, iv_len ) );
+    TEST_ASSERT( 0 == cipher_reset( &ctx ) );
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+    TEST_ASSERT( 0 == cipher_update_ad( &ctx, ad, ad_len ) );
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
+
+    /* decode buffer and check tag */
+    total_len = 0;
+    TEST_ASSERT( 0 == cipher_update( &ctx, cipher, cipher_len, output, &outlen ) );
+    total_len += outlen;
+    TEST_ASSERT( finish_result == cipher_finish( &ctx, output + outlen,
+                                                 &outlen ) );
+    total_len += outlen;
+#if defined(POLARSSL_CIPHER_MODE_AEAD)
+    TEST_ASSERT( tag_result == cipher_check_tag( &ctx, tag, tag_len ) );
+#endif /* POLARSSL_CIPHER_MODE_AEAD */
+
+    /* check plaintext only if everything went fine */
+    if( 0 == finish_result && 0 == tag_result )
+    {
+        TEST_ASSERT( total_len == clear_len );
+        TEST_ASSERT( 0 == memcmp( output, clear, clear_len ) );
+    }
+
+    cipher_free_ctx( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
+void test_vec_ecb( int cipher_id, int operation, char *hex_key,
+                   char *hex_input, char *hex_result,
+                   int finish_result )
+{
+    unsigned char key[50];
+    unsigned char input[16];
+    unsigned char result[16];
+    size_t key_len;
+    cipher_context_t ctx;
+    unsigned char output[32];
+    size_t outlen;
+
+    memset( key, 0x00, sizeof( key ) );
+    memset( input, 0x00, sizeof( input ) );
+    memset( result, 0x00, sizeof( result ) );
+    memset( output, 0x00, sizeof( output ) );
+
+    /* Prepare context */
+    TEST_ASSERT( 0 == cipher_init_ctx( &ctx,
+                                       cipher_info_from_type( cipher_id ) ) );
+
+    key_len = unhexify( key, hex_key );
+    TEST_ASSERT( unhexify( input, hex_input ) ==
+                 (int) cipher_get_block_size( &ctx ) );
+    TEST_ASSERT( unhexify( result, hex_result ) ==
+                 (int) cipher_get_block_size( &ctx ) );
+
+    TEST_ASSERT( 0 == cipher_setkey( &ctx, key, 8 * key_len, operation ) );
+
+    TEST_ASSERT( 0 == cipher_update( &ctx, input,
+                                     cipher_get_block_size( &ctx ),
+                                     output, &outlen ) );
+    TEST_ASSERT( outlen == cipher_get_block_size( &ctx ) );
+    TEST_ASSERT( finish_result == cipher_finish( &ctx, output + outlen,
+                                                 &outlen ) );
+    TEST_ASSERT( 0 == outlen );
+
+    /* check plaintext only if everything went fine */
+    if( 0 == finish_result )
+        TEST_ASSERT( 0 == memcmp( output, result,
+                                  cipher_get_block_size( &ctx ) ) );
+
+    cipher_free_ctx( &ctx );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
 void set_padding( int cipher_id, int pad_mode, int ret )
 {
     const cipher_info_t *cipher_info;
diff --git a/tests/suites/test_suite_cipher.gcm.data b/tests/suites/test_suite_cipher.gcm.data
new file mode 100644
index 0000000..7681d18
--- /dev/null
+++ b/tests/suites/test_suite_cipher.gcm.data
@@ -0,0 +1,134 @@
+Cipher Selftest
+depends_on:POLARSSL_SELF_TEST
+cipher_selftest:
+
+Decrypt empty buffer
+dec_empty_buf:
+
+AES-GCM Encrypt and decrypt 0 bytes
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:0:-1
+
+AES 128 GCM Encrypt and decrypt 1 byte
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:1:-1
+
+AES 128 GCM Encrypt and decrypt 2 bytes
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:2:-1
+
+AES 128 GCM Encrypt and decrypt 7 bytes
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:7:-1
+
+AES 128 GCM Encrypt and decrypt 8 bytes
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:8:-1
+
+AES 128 GCM Encrypt and decrypt 9 bytes
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:9:-1
+
+AES 128 GCM Encrypt and decrypt 15 bytes
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:15:-1
+
+AES 128 GCM Encrypt and decrypt 16 bytes
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:16:-1
+
+AES 128 GCM Encrypt and decrypt 17 bytes
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:17:-1
+
+AES 128 GCM Encrypt and decrypt 31 bytes
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:31:-1
+
+AES 128 GCM Encrypt and decrypt 32 bytes
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:32:-1
+
+AES 128 GCM Encrypt and decrypt 32 bytes
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:33:-1
+
+AES 128 GCM Encrypt and decrypt 47 bytes
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:47:-1
+
+AES 128 GCM Encrypt and decrypt 48 bytes
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:48:-1
+
+AES 128 GCM Encrypt and decrypt 49 bytes
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf:POLARSSL_CIPHER_AES_128_GCM:"AES-128-GCM":128:49:-1
+
+AES 128 GCM Encrypt and decrypt 0 bytes in multiple parts
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:0:0
+
+AES 128 GCM Encrypt and decrypt 1 bytes in multiple parts 1
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:1:0
+
+AES 128 GCM Encrypt and decrypt 1 bytes in multiple parts 2
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:0:1
+
+AES 128 GCM Encrypt and decrypt 16 bytes in multiple parts 1
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:16:0
+
+AES 128 GCM Encrypt and decrypt 16 bytes in multiple parts 2
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:0:16
+
+AES 128 GCM Encrypt and decrypt 22 bytes in multiple parts 1
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:16:6
+
+AES 128 GCM Encrypt and decrypt 22 bytes in multiple parts 2
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:0:22
+
+AES 128 GCM Encrypt and decrypt 32 bytes in multiple parts 1
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:16:16
+
+AES 128 GCM Decrypt test vector #1
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"d785dafea3e966731ef6fc6202262584":"d91a46205ee94058b3b8403997592dd2":"":"":"":"3b92a17c1b9c3578a68cffea5a5b6245":0:0
+
+AES 128 GCM Decrypt test vector #2
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"9ab5c8ca905b5fe50461f4a68941144b":"96dd3927a96e16123f2e9d6b367d303f":"":"":"":"6e0c53ef":0:0
+
+AES 128 GCM Decrypt test vector #3
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"b5fc7af605721a9cfe61c1ee6a4b3e22":"6b757d4055823d1035d01077666037d6":"":"":"":"e8c09ddd":0:POLARSSL_ERR_GCM_AUTH_FAILED
+
+AES 128 GCM Decrypt test vector #4
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"03c0b4a6e508a8490db0d086a82c9db7":"ac52f6c1a05030321fa39f87e89fdb5e":"":"":"33316ca79d10a79f4fd038593e8eef09625089dc4e0ffe4bc1f2871554fa6666ab3e7fe7885edef694b410456f3ec0e513bb25f1b48d95e4820c5972c1aabb25c84c08566002dadc36df334c1ce86847964a122016d389ac873bca8c335a7a99bcef91e1b985ae5d488a2d7f78b4bf14e0c2dc715e814f4e24276057cf668172":"756292d8b4653887edef51679b161812":0:POLARSSL_ERR_GCM_AUTH_FAILED
+
+AES 128 GCM Decrypt test vector #5
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"2bc73fba942ff105823b5dccf6befb1c":"902c3e3b69b1ef8395d7281ff74cce38":"":"":"4adec0b4ac00325a860044d9f9519daa4f7c163229a75819b0fd7d8e23319f030e61dfa8eadabff42ea27bc36bdb6cad249e801ca631b656836448b7172c11126bad2781e6a1aa4f62c4eda53409408b008c057e0b81215cc13ddabbb8f1915f4bbab854f8b00763a530ad5055d265778cd3080d0bd35b76a329bdd5b5a2d268":"ebdd7c8e87fe733138a433543542d1":0:0
+
+AES 128 GCM Decrypt test vector #6
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"0dd358bc3f992f26e81e3a2f3aa2d517":"d8c750bb443ee1a169dfe97cfe4d855b":"87cc4fd75788c9d5cc83bae5d764dd249d178ab23224049795d4288b5ed9ea3f317068a39a7574b300c8544226e87b08e008fbe241d094545c211d56ac44437d41491a438272738968c8d371aa7787b5f606c8549a9d868d8a71380e9657d3c0337979feb01de5991fc1470dfc59eb02511efbbff3fcb479a862ba3844a25aaa":"77949b29f085bb3abb71a5386003811233056d3296eb093370f7777dadd306d93d59dcb9754d3857cf2758091ba661f845ef0582f6ae0e134328106f0d5d16b541cd74fdc756dc7b53f4f8a194daeea9369ebb1630c01ccb307b848e9527da20a39898d748fd59206f0b79d0ed946a8958033a45bd9ae673518b32606748eb65":"":"a81d13973baa22a751833d7d3f94b3b1":0:0
+
+AES 128 GCM Decrypt test vector #7
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"9a433c612d7e1bdff881e4d63ba8b141":"8b670cf31f470f79a6c0b79e73863ca1":"ce10758332f423228b5e4ae31efda7677586934a1d8f05d9b7a0dc4e2010ec3eaacb71a527a5fff8e787d75ebd24ad163394c891b33477ed9e2a2d853c364cb1c5d0bc317fcaf4010817dbe5f1fd1037c701b291b3a66b164bc818bf5c00a4c210a1671faa574d74c7f3543f6c09aaf117e12e2eb3dae55edb1cc5b4086b617d":"":"":"8526fd25daf890e79946a205b698f287":0:POLARSSL_ERR_GCM_AUTH_FAILED
+
+AES 128 GCM Decrypt test vector #8
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"69eedf3777e594c30e94e9c5e2bce467":"a3330638a809ba358d6c098e4342b81e":"5114e9983c96fecec3f7304ca42f52aa16cb7c6aadfb62ad537c93a3188835ca0703dad34c73cf96435b668b68a7a1d056931959316e8d3ab956bf64c4e07479c7767f9d488b0c0c351333ccf400b7e0be19a0fd173e3f2a1ae313f27e516952260fd2da9ab9daca478ebb93cd07d0b7503b32364d8e308d904d966c58f226bb":"208e6321238bf5c6e2ef55a4b8f531cbbfb0d77374fe32df6dd663486cf79beeed39bb6910c3c78dd0cc30707a0a12b226b2d06024db25dcd8a4e620f009cafa5242121e864c7f3f4360aaf1e9d4e548d99615156f156008418c1c41ff2bbc007cecf8f209c73203e6df89b32871de637b3d6af2e277d146ae03f3404d387b77":"df4e3f2b47cf0e8590228fcf9913fb8a5eb9751bba318fd2d57be68c7e788e04fabf303699b99f26313d1c4956105cd2817aad21b91c28f3b9251e9c0b354490fa5abfcea0065aa3cc9b96772eb8af06a1a9054bf12d3ae698dfb01a13f989f8b8a4bb61686cf3adf58f05873a24d403a62a092290c2481e4159588fea6b9a09":"5de3068e1e20eed469265000077b1db9":0:0
+
+AES 128 GCM Decrypt test vector #9
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+decrypt_test_vec:POLARSSL_CIPHER_AES_128_GCM:-1:"45cc35311eedf0ba093bf901931a7036":"fed5084de3c348f5a0adf4c2fd4e848a":"5dc8d7525eaad035c19714ae1b1e538cb66a4089027245351e0ad9297410fb3a0c1155407c10a8bb95a9ca624a9c9925dac003ee78926c6e90ff4ccdba10e8a78bda1c4478162a0e302de5ff05fb0f94c89c3c7429fb94828bdcd97d21333c2ee72963ee6f056ce272b8bab007e653a42b01d1d2041ba627f169c8c0d32e6dae":"":"6e210914e4aed188d576f5ad7fc7e4cf7dd8d82f34ea3bcbdb7267cfd9045f806978dbff3460c4e8ff8c4edb6ad2edba405a8d915729d89aab2116b36a70b54f5920a97f5a571977e0329eda6c696749be940eabfc6d8b0bbd6fbdb87657b3a7695da9f5d3a7384257f20e0becd8512d3705cc246ee6ca1e610921cf92603d79":"266a895fc21da5176b44b446d7d1921d":0:POLARSSL_ERR_GCM_AUTH_FAILED
diff --git a/tests/suites/test_suite_cipher.null.data b/tests/suites/test_suite_cipher.null.data
index 96aa36a..dd68277 100644
--- a/tests/suites/test_suite_cipher.null.data
+++ b/tests/suites/test_suite_cipher.null.data
@@ -7,59 +7,59 @@
 
 NULL Encrypt and decrypt 0 bytes
 depends_on:POLARSSL_CIPHER_NULL_CIPHER
-enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:0
+enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:0:-1
 
 NULL Encrypt and decrypt 1 bytes
 depends_on:POLARSSL_CIPHER_NULL_CIPHER
-enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:1
+enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:1:-1
 
 NULL Encrypt and decrypt 2 bytes
 depends_on:POLARSSL_CIPHER_NULL_CIPHER
-enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:2
+enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:2:-1
 
 NULL Encrypt and decrypt 7 bytes
 depends_on:POLARSSL_CIPHER_NULL_CIPHER
-enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:7
+enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:7:-1
 
 NULL Encrypt and decrypt 8 bytes
 depends_on:POLARSSL_CIPHER_NULL_CIPHER
-enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:8
+enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:8:-1
 
 NULL Encrypt and decrypt 9 bytes
 depends_on:POLARSSL_CIPHER_NULL_CIPHER
-enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:9
+enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:9:-1
 
 NULL Encrypt and decrypt 15 bytes
 depends_on:POLARSSL_CIPHER_NULL_CIPHER
-enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:15
+enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:15:-1
 
 NULL Encrypt and decrypt 16 bytes
 depends_on:POLARSSL_CIPHER_NULL_CIPHER
-enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:16
+enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:16:-1
 
 NULL Encrypt and decrypt 31 bytes
 depends_on:POLARSSL_CIPHER_NULL_CIPHER
-enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:31
+enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:31:-1
 
 NULL Encrypt and decrypt 32 bytes
 depends_on:POLARSSL_CIPHER_NULL_CIPHER
-enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:32
+enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:32:-1
 
 NULL Encrypt and decrypt 33 bytes
 depends_on:POLARSSL_CIPHER_NULL_CIPHER
-enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:33
+enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:33:-1
 
 NULL Encrypt and decrypt 47 bytes
 depends_on:POLARSSL_CIPHER_NULL_CIPHER
-enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:47
+enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:47:-1
 
 NULL Encrypt and decrypt 48 bytes
 depends_on:POLARSSL_CIPHER_NULL_CIPHER
-enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:48
+enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:48:-1
 
 NULL Encrypt and decrypt 49 bytes
 depends_on:POLARSSL_CIPHER_NULL_CIPHER
-enc_dec_buf:POLARSSL_CIPHER_NULL:NULL:0:49
+enc_dec_buf:POLARSSL_CIPHER_NULL:"NULL":0:49:-1
 
 NULL Encrypt and decrypt 1 bytes in multiple parts 1
 depends_on:POLARSSL_CIPHER_NULL_CIPHER
diff --git a/tests/suites/test_suite_dhm.data b/tests/suites/test_suite_dhm.data
index 99f4482..168c77c 100644
--- a/tests/suites/test_suite_dhm.data
+++ b/tests/suites/test_suite_dhm.data
@@ -1,8 +1,8 @@
 Diffie-Hellman full exchange #1
-dhm_do_dhm:1024:10:"23":10:"5"
+dhm_do_dhm:10:"23":10:"5"
 
 Diffie-Hellman full exchange #2
-dhm_do_dhm:1024:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
+dhm_do_dhm:10:"93450983094850938450983409623":10:"9345098304850938450983409622"
 
-Diffie-Hellman full exchange #2
-dhm_do_dhm:1024:10:"93450983094850938450983409623982317398171298719873918739182739712938719287391879381271":10:"9345098309485093845098340962223981329819812792137312973297123912791271"
+Diffie-Hellman full exchange #3
+dhm_do_dhm:10:"93450983094850938450983409623982317398171298719873918739182739712938719287391879381271":10:"9345098309485093845098340962223981329819812792137312973297123912791271"
diff --git a/tests/suites/test_suite_dhm.function b/tests/suites/test_suite_dhm.function
index e6524cc..e8d9cea 100644
--- a/tests/suites/test_suite_dhm.function
+++ b/tests/suites/test_suite_dhm.function
@@ -8,7 +8,7 @@
  */
 
 /* BEGIN_CASE */
-void dhm_do_dhm( int NOTUSED, int radix_P, char *input_P,
+void dhm_do_dhm( int radix_P, char *input_P,
                  int radix_G, char *input_G )
 {
     dhm_context ctx_srv;
@@ -25,8 +25,6 @@
     int x_size;
     rnd_pseudo_info rnd_info;
 
-    ((void)NOTUSED);
-
     memset( &ctx_srv, 0x00, sizeof( dhm_context ) );
     memset( &ctx_cli, 0x00, sizeof( dhm_context ) );
     memset( ske, 0x00, 1000 );
@@ -35,22 +33,57 @@
     memset( sec_cli, 0x00, 1000 );
     memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
 
+    /*
+     * Set params
+     */
     TEST_ASSERT( mpi_read_string( &ctx_srv.P, radix_P, input_P ) == 0 );
     TEST_ASSERT( mpi_read_string( &ctx_srv.G, radix_G, input_G ) == 0 );
     x_size = mpi_size( &ctx_srv.P );
+    pub_cli_len = x_size;
+
+    /*
+     * First key exchange
+     */
+    TEST_ASSERT( dhm_make_params( &ctx_srv, x_size, ske, &ske_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
+    ske[ske_len++] = 0;
+    ske[ske_len++] = 0;
+    TEST_ASSERT( dhm_read_params( &ctx_cli, &p, ske + ske_len ) == 0 );
+
+    TEST_ASSERT( dhm_make_public( &ctx_cli, x_size, pub_cli, pub_cli_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
+    TEST_ASSERT( dhm_read_public( &ctx_srv, pub_cli, pub_cli_len ) == 0 );
+
+    TEST_ASSERT( dhm_calc_secret( &ctx_srv, sec_srv, &sec_srv_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
+    TEST_ASSERT( dhm_calc_secret( &ctx_cli, sec_cli, &sec_cli_len, NULL, NULL ) == 0 );
+
+    TEST_ASSERT( sec_srv_len == sec_cli_len );
+    TEST_ASSERT( sec_srv_len != 0 );
+    TEST_ASSERT( memcmp( sec_srv, sec_cli, sec_srv_len ) == 0 );
+
+    /* Re-do calc_secret on server to test update of blinding values */
+    sec_srv_len = 1000;
+    TEST_ASSERT( dhm_calc_secret( &ctx_srv, sec_srv, &sec_srv_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
+
+    TEST_ASSERT( sec_srv_len == sec_cli_len );
+    TEST_ASSERT( sec_srv_len != 0 );
+    TEST_ASSERT( memcmp( sec_srv, sec_cli, sec_srv_len ) == 0 );
+
+    /*
+     * Second key exchange to test change of blinding values on server
+     */
+    sec_cli_len = 1000;
+    sec_srv_len = 1000;
+    p = ske;
 
     TEST_ASSERT( dhm_make_params( &ctx_srv, x_size, ske, &ske_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
     ske[ske_len++] = 0;
     ske[ske_len++] = 0;
     TEST_ASSERT( dhm_read_params( &ctx_cli, &p, ske + ske_len ) == 0 );
 
-    pub_cli_len = x_size;
     TEST_ASSERT( dhm_make_public( &ctx_cli, x_size, pub_cli, pub_cli_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
-
     TEST_ASSERT( dhm_read_public( &ctx_srv, pub_cli, pub_cli_len ) == 0 );
 
-    TEST_ASSERT( dhm_calc_secret( &ctx_srv, sec_srv, &sec_srv_len ) == 0 );
-    TEST_ASSERT( dhm_calc_secret( &ctx_cli, sec_cli, &sec_cli_len ) == 0 );
+    TEST_ASSERT( dhm_calc_secret( &ctx_srv, sec_srv, &sec_srv_len, &rnd_pseudo_rand, &rnd_info ) == 0 );
+    TEST_ASSERT( dhm_calc_secret( &ctx_cli, sec_cli, &sec_cli_len, NULL, NULL ) == 0 );
 
     TEST_ASSERT( sec_srv_len == sec_cli_len );
     TEST_ASSERT( sec_srv_len != 0 );
diff --git a/tests/suites/test_suite_ecdh.function b/tests/suites/test_suite_ecdh.function
index 5bfd63d..ba35c76 100644
--- a/tests/suites/test_suite_ecdh.function
+++ b/tests/suites/test_suite_ecdh.function
@@ -27,8 +27,10 @@
                  == 0 );
     TEST_ASSERT( ecdh_gen_public( &grp, &dB, &qB, &rnd_pseudo_rand, &rnd_info )
                  == 0 );
-    TEST_ASSERT( ecdh_compute_shared( &grp, &zA, &qB, &dA ) == 0 );
-    TEST_ASSERT( ecdh_compute_shared( &grp, &zB, &qA, &dB ) == 0 );
+    TEST_ASSERT( ecdh_compute_shared( &grp, &zA, &qB, &dA,
+                                      &rnd_pseudo_rand, &rnd_info ) == 0 );
+    TEST_ASSERT( ecdh_compute_shared( &grp, &zB, &qA, &dB,
+                                      NULL, NULL ) == 0 );
 
     TEST_ASSERT( mpi_cmp_mpi( &zA, &zB ) == 0 );
 
@@ -70,9 +72,9 @@
     TEST_ASSERT( mpi_cmp_mpi( &qB.Y, &check ) == 0 );
 
     TEST_ASSERT( mpi_read_string( &check, 16, z_str ) == 0 );
-    TEST_ASSERT( ecdh_compute_shared( &grp, &zA, &qB, &dA ) == 0 );
+    TEST_ASSERT( ecdh_compute_shared( &grp, &zA, &qB, &dA, NULL, NULL ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &zA, &check ) == 0 );
-    TEST_ASSERT( ecdh_compute_shared( &grp, &zB, &qA, &dB ) == 0 );
+    TEST_ASSERT( ecdh_compute_shared( &grp, &zB, &qA, &dB, NULL, NULL ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &zB, &check ) == 0 );
 
     ecp_group_free( &grp );
@@ -107,8 +109,9 @@
                                    &rnd_pseudo_rand, &rnd_info ) == 0 );
     TEST_ASSERT( ecdh_read_public( &srv, buf, len ) == 0 );
 
-    TEST_ASSERT( ecdh_calc_secret( &srv, &len, buf, 1000 ) == 0 );
-    TEST_ASSERT( ecdh_calc_secret( &cli, &len, buf, 1000 ) == 0 );
+    TEST_ASSERT( ecdh_calc_secret( &srv, &len, buf, 1000,
+                                   &rnd_pseudo_rand, &rnd_info ) == 0 );
+    TEST_ASSERT( ecdh_calc_secret( &cli, &len, buf, 1000, NULL, NULL ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &srv.z, &cli.z ) == 0 );
 
     ecdh_free( &srv );
diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data
index ce92633..55a3453 100644
--- a/tests/suites/test_suite_ecp.data
+++ b/tests/suites/test_suite_ecp.data
@@ -50,7 +50,7 @@
 ecp_small_sub:0:"14":"11":0:"14":"36":0:27:30
 
 ECP small multiplication negative
-ecp_small_mul:-1:0:0:0:POLARSSL_ERR_ECP_GENERIC
+ecp_small_mul:-1:0:0:0:POLARSSL_ERR_ECP_BAD_INPUT_DATA
 
 ECP small multiplication #0
 ecp_small_mul:0:1:0:0:0
@@ -101,7 +101,7 @@
 ecp_small_mul:2:0:20:01:0
 
 ECP small multiplication too big
-ecp_small_mul:-1:0:0:0:POLARSSL_ERR_ECP_GENERIC
+ecp_small_mul:-1:0:0:0:POLARSSL_ERR_ECP_BAD_INPUT_DATA
 
 ECP small check pubkey #1
 ecp_small_check_pub:1:1:0:POLARSSL_ERR_ECP_GENERIC
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index 62c5de2..5b1ab60 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -101,17 +101,33 @@
     ecp_group grp;
     ecp_point R;
     mpi m;
+    rnd_pseudo_info rnd_info;
 
     ecp_group_init( &grp );
     ecp_point_init( &R );
     mpi_init( &m );
+    memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
 
     TEST_ASSERT( ecp_group_read_string( &grp, 10,
                 "47", "4", "17", "42", "13" ) == 0 );
 
     TEST_ASSERT( mpi_lset( &m, m_str ) == 0 );
 
-    TEST_ASSERT( ecp_mul( &grp, &R, &m, &grp.G ) == ret );
+    TEST_ASSERT( ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) == ret );
+
+    if( r_zero )
+        TEST_ASSERT( mpi_cmp_int( &R.Z, 0 ) == 0 );
+    else
+    {
+        TEST_ASSERT( mpi_cmp_int( &R.X, x_r ) == 0 );
+        TEST_ASSERT( mpi_cmp_int( &R.Y, y_r ) == 0 );
+    }
+
+    /* try again with randomization */
+    ecp_point_free( &R );
+
+    TEST_ASSERT( ecp_mul( &grp, &R, &m, &grp.G,
+                          &rnd_pseudo_rand, &rnd_info ) == ret );
 
     if( r_zero )
         TEST_ASSERT( mpi_cmp_int( &R.Z, 0 ) == 0 );
@@ -158,10 +174,12 @@
     ecp_group grp;
     ecp_point R;
     mpi dA, xA, yA, dB, xB, yB, xZ, yZ;
+    rnd_pseudo_info rnd_info;
 
     ecp_group_init( &grp ); ecp_point_init( &R );
     mpi_init( &dA ); mpi_init( &xA ); mpi_init( &yA ); mpi_init( &dB );
     mpi_init( &xB ); mpi_init( &yB ); mpi_init( &xZ ); mpi_init( &yZ );
+    memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
 
     TEST_ASSERT( ecp_use_known_dp( &grp, id ) == 0 );
 
@@ -176,20 +194,22 @@
     TEST_ASSERT( mpi_read_string( &xZ, 16, xZ_str ) == 0 );
     TEST_ASSERT( mpi_read_string( &yZ, 16, yZ_str ) == 0 );
 
-    TEST_ASSERT( ecp_mul( &grp, &R, &dA, &grp.G ) == 0 );
+    TEST_ASSERT( ecp_mul( &grp, &R, &dA, &grp.G,
+                          &rnd_pseudo_rand, &rnd_info ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &R.X, &xA ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &R.Y, &yA ) == 0 );
     TEST_ASSERT( ecp_check_pubkey( &grp, &R ) == 0 );
-    TEST_ASSERT( ecp_mul( &grp, &R, &dB, &R ) == 0 );
+    TEST_ASSERT( ecp_mul( &grp, &R, &dB, &R, NULL, NULL ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &R.X, &xZ ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &R.Y, &yZ ) == 0 );
     TEST_ASSERT( ecp_check_pubkey( &grp, &R ) == 0 );
 
-    TEST_ASSERT( ecp_mul( &grp, &R, &dB, &grp.G ) == 0 );
+    TEST_ASSERT( ecp_mul( &grp, &R, &dB, &grp.G, NULL, NULL ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &R.X, &xB ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &R.Y, &yB ) == 0 );
     TEST_ASSERT( ecp_check_pubkey( &grp, &R ) == 0 );
-    TEST_ASSERT( ecp_mul( &grp, &R, &dA, &R ) == 0 );
+    TEST_ASSERT( ecp_mul( &grp, &R, &dA, &R,
+                          &rnd_pseudo_rand, &rnd_info ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &R.X, &xZ ) == 0 );
     TEST_ASSERT( mpi_cmp_mpi( &R.Y, &yZ ) == 0 );
     TEST_ASSERT( ecp_check_pubkey( &grp, &R ) == 0 );
diff --git a/tests/suites/test_suite_gcm.function b/tests/suites/test_suite_gcm.function
index c00ec0b..c9cc177 100644
--- a/tests/suites/test_suite_gcm.function
+++ b/tests/suites/test_suite_gcm.function
@@ -39,7 +39,7 @@
     iv_len = unhexify( iv_str, hex_iv_string );
     add_len = unhexify( add_str, hex_add_string );
 
-    TEST_ASSERT( gcm_init( &ctx, key_str, key_len * 8 ) == init_result );
+    TEST_ASSERT( gcm_init( &ctx, POLARSSL_CIPHER_ID_AES, key_str, key_len * 8 ) == init_result );
     if( init_result == 0 )
     {
         TEST_ASSERT( gcm_crypt_and_tag( &ctx, GCM_ENCRYPT, pt_len, iv_str, iv_len, add_str, add_len, src_str, output, tag_len, tag_output ) == 0 );
@@ -84,7 +84,7 @@
     add_len = unhexify( add_str, hex_add_string );
     unhexify( tag_str, hex_tag_string );
 
-    TEST_ASSERT( gcm_init( &ctx, key_str, key_len * 8 ) == init_result );
+    TEST_ASSERT( gcm_init( &ctx, POLARSSL_CIPHER_ID_AES, key_str, key_len * 8 ) == init_result );
     if( init_result == 0 )
     {
         ret = gcm_auth_decrypt( &ctx, pt_len, iv_str, iv_len, add_str, add_len, tag_str, tag_len, src_str, output );
@@ -95,6 +95,7 @@
         }
         else
         {
+            TEST_ASSERT( ret == 0 );
             hexify( dst_str, output, pt_len );
 
             TEST_ASSERT( strcmp( (char *) dst_str, pt_result ) == 0 );
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index f089570..ef7bbd4 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -418,9 +418,9 @@
 depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
 x509_verify:"data_files/server2.crt":"data_files/server1.crt":"data_files/crl_expired.pem":"NULL":0:0:"verify_all"
 
-X509 Certificate verification #21 (domain matching wildcard certificate)
+X509 Certificate verification #21 (domain matching wildcard certificate, case insensitive)
 depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15
-x509_verify:"data_files/cert_example_wildcard.crt":"data_files/test-ca.crt":"data_files/crl.pem":"mail.example.com":0:0:"NULL"
+x509_verify:"data_files/cert_example_wildcard.crt":"data_files/test-ca.crt":"data_files/crl.pem":"mail.ExAmPlE.com":0:0:"NULL"
 
 X509 Certificate verification #22 (domain not matching wildcard certificate)
 depends_on:POLARSSL_PEM_C:POLARSSL_FS_IO:POLARSSL_SHA1_C:POLARSSL_RSA_C:POLARSSL_PKCS1_V15