Split cipher_set_iv() out of cipher_reset()
diff --git a/include/polarssl/cipher.h b/include/polarssl/cipher.h
index ef037be..e540c92 100644
--- a/include/polarssl/cipher.h
+++ b/include/polarssl/cipher.h
@@ -185,7 +185,8 @@
     /** Name of the cipher */
     const char * name;
 
-    /** IV size, in bytes */
+    /** IV/NONCE size, in bytes, for ciphers with fixed-length IVs), or
+     * 0 for ciphers with variable-length IVs or not using IVs */
     unsigned int iv_size;
 
     /** block size, in bytes */
@@ -222,6 +223,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;
@@ -315,18 +319,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 or accepts IV of various sizes.
+ * \return              If IV has not been set yet: desired size for ciphers
+ *                      with fixed-size IVs, 0 for other ciphers.
+ *                      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;
 }
 
@@ -428,12 +436,24 @@
 int cipher_set_padding_mode( cipher_context_t *ctx, cipher_padding_t mode );
 
 /**
+ * \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               Reset the given context, setting the IV to iv
  *
  * \param ctx           generic cipher context
- * \param iv            IV to use or NONCE_COUNTER in the case of a CTR-mode cipher
- * \param iv_len        IV length for ciphers with variable-size IV,
- *                      Discared by ciphers with fixed-size IV.
  * \param ad            Additional data for AEAD ciphers, or discarded.
  *                      May be NULL only if ad_len is 0.
  * \param ad_len        Length of ad for AEAD ciphers, or discarded.
@@ -442,7 +462,6 @@
  *                      if parameter verification fails.
  */
 int cipher_reset( cipher_context_t *ctx,
-                  const unsigned char *iv, size_t iv_len,
                   const unsigned char *ad, size_t ad_len );
 
 /**
diff --git a/library/cipher.c b/library/cipher.c
index d7cac05..d90abe1 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -396,29 +396,42 @@
     return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
 }
 
-int cipher_reset( cipher_context_t *ctx,
-                  const unsigned char *iv, size_t iv_len,
-                  const unsigned char *ad, size_t ad_len )
+int cipher_set_iv( cipher_context_t *ctx,
+                   const unsigned char *iv, size_t iv_len )
 {
+    size_t fixed_iv_size;
+
     if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
         return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
 
+    fixed_iv_size = cipher_get_iv_size( ctx );
+
+    /* 0 means variable size (or no IV): use given len */
+    if( fixed_iv_size == 0 )
+        fixed_iv_size = iv_len;
+
+    memcpy( ctx->iv, iv, fixed_iv_size );
+    ctx->iv_size = fixed_iv_size;
+
+    return 0;
+}
+
+int cipher_reset( cipher_context_t *ctx,
+                  const unsigned char *ad, size_t ad_len )
+{
     ctx->unprocessed_len = 0;
 
 #if defined(POLARSSL_GCM_C)
     if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
     {
         return gcm_starts( ctx->cipher_ctx, ctx->operation,
-                           iv, iv_len, ad, ad_len );
+                           ctx->iv, ctx->iv_size, ad, ad_len );
     }
 #else
     ((void) ad);
     ((void) ad_len);
-    ((void) iv_len);
 #endif
 
-    memcpy( ctx->iv, iv, cipher_get_iv_size( ctx ) );
-
     return 0;
 }
 
diff --git a/library/pkcs12.c b/library/pkcs12.c
index 9ccb60a..3634ce1 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, NULL, 0 ) ) != 0 )
+    if( ( ret = cipher_set_iv( &cipher_ctx, iv, 0 ) ) != 0 )
+        goto exit;
+
+    if( ( ret = cipher_reset( &cipher_ctx, iv, 0 ) ) != 0 )
         goto exit;
 
     if( ( ret = cipher_update( &cipher_ctx, data, len,
diff --git a/library/pkcs5.c b/library/pkcs5.c
index 2b6a75a..6582fd0 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, NULL, 0 ) ) != 0 )
+    if( ( ret = cipher_set_iv( &cipher_ctx, iv, 0 ) ) != 0 )
+        goto exit;
+
+    if( ( ret = cipher_reset( &cipher_ctx, NULL, 0 ) ) != 0 )
         goto exit;
 
     if( ( ret = cipher_update( &cipher_ctx, data, datalen,
diff --git a/programs/aes/crypt_and_hash.c b/programs/aes/crypt_and_hash.c
index a9b862e..8ffdb9f 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, 16, NULL, 0 ) != 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, NULL, 0 ) != 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, 16, NULL, 0 );
+        cipher_set_iv( &cipher_ctx, IV, 16 );
+        cipher_reset( &cipher_ctx, NULL, 0 );
 
         md_hmac_starts( &md_ctx, digest, 32 );
 
diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function
index b1814fa..d247bab 100644
--- a/tests/suites/test_suite_cipher.function
+++ b/tests/suites/test_suite_cipher.function
@@ -58,8 +58,11 @@
         TEST_ASSERT( 0 == cipher_set_padding_mode( &ctx_enc, pad_mode ) );
     }
 
-    TEST_ASSERT( 0 == cipher_reset( &ctx_dec, iv, 16, ad, 13 ) );
-    TEST_ASSERT( 0 == cipher_reset( &ctx_enc, iv, 16, ad, 13 ) );
+    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, ad, 13 ) );
+    TEST_ASSERT( 0 == cipher_reset( &ctx_enc, ad, 13 ) );
 
     /* encode length number of bytes from inbuf */
     TEST_ASSERT( 0 == cipher_update( &ctx_enc, inbuf, length, encbuf, &outlen ) );
@@ -133,7 +136,8 @@
     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, 16, NULL, 0 ) );
+    TEST_ASSERT( 0 == cipher_set_iv( &ctx, iv, 16 ) );
+    TEST_ASSERT( 0 == cipher_reset( &ctx, NULL, 0 ) );
 
     /* encode length number of bytes from inbuf */
     TEST_ASSERT( 0 == cipher_update( &ctx, inbuf, length, encbuf, &outlen ) );
@@ -166,7 +170,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);
     
@@ -174,7 +178,9 @@
 
     TEST_ASSERT( 0 == cipher_setkey( &ctx_dec, key, 128, POLARSSL_DECRYPT ) );
 
-    TEST_ASSERT( 0 == cipher_reset( &ctx_dec, iv, 16, NULL, 0 ) );
+    TEST_ASSERT( 0 == cipher_set_iv( &ctx_dec, iv, 16 ) );
+
+    TEST_ASSERT( 0 == cipher_reset( &ctx_dec, NULL, 0 ) );
 
     /* decode 0-byte string */
     TEST_ASSERT( 0 == cipher_update( &ctx_dec, encbuf, 0, decbuf, &outlen ) );
@@ -228,8 +234,11 @@
     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, 16, NULL, 0 ) );
-    TEST_ASSERT( 0 == cipher_reset( &ctx_enc, iv, 16, NULL, 0 ) );
+    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, NULL, 0 ) );
+    TEST_ASSERT( 0 == cipher_reset( &ctx_enc, NULL, 0 ) );
 
     /* encode length number of bytes from inbuf */
     TEST_ASSERT( 0 == cipher_update( &ctx_enc, inbuf, first_length, encbuf, &outlen ) );