Merged blinding additions for EC, RSA and DHM into development
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..72d55ee 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -40,11 +40,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/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/cipher.h b/include/polarssl/cipher.h
index 0ab2b56..b7c03cb 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,49 @@
 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 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
- * \param iv            IV to use or NONCE_COUNTER in the case of a CTR-mode cipher
  *
  * \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 +528,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 +545,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 +560,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 +570,37 @@
  *                      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 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 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/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/ssl.h b/include/polarssl/ssl.h
index 354c6c2..eaebd6a 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.
  */
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/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/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_srv.c b/library/ssl_srv.c
index 21ceaf1..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 );
         }
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 c175df4..55cc9e3 100644
--- a/library/x509parse.c
+++ b/library/x509parse.c
@@ -2053,7 +2053,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;
@@ -3457,6 +3460,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;
@@ -3478,7 +3504,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 );
     }
@@ -3657,7 +3683,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 );
@@ -3706,7 +3732,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 &&
@@ -3727,7 +3753,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/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/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 1f7943a4..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_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