Moved GCM to use cipher layer instead of AES directly
diff --git a/include/polarssl/gcm.h b/include/polarssl/gcm.h
index dc058dc..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
diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c
index 253fcdc..862328f 100644
--- a/library/cipher_wrap.c
+++ b/library/cipher_wrap.c
@@ -298,9 +298,10 @@
     polarssl_free( ctx );
 }
 
-static int gcm_setkey_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
 {
-    return gcm_init( (gcm_context *) ctx, key, key_length );
+    return gcm_init( (gcm_context *) ctx, POLARSSL_CIPHER_ID_AES,
+                     key, key_length );
 }
 
 const cipher_base_t gcm_aes_info = {
@@ -310,8 +311,8 @@
     NULL,
     NULL,
     NULL,
-    gcm_setkey_wrap,
-    gcm_setkey_wrap,
+    gcm_aes_setkey_wrap,
+    gcm_aes_setkey_wrap,
     gcm_ctx_alloc,
     gcm_ctx_free,
 };
diff --git a/library/gcm.c b/library/gcm.c
index 99036a0..e041647 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,33 @@
             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( ( 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 +193,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 +236,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 +265,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 +286,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++ )
         {
@@ -613,6 +640,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++ )
     {
@@ -623,7 +651,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],
@@ -647,7 +675,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],
@@ -671,7 +699,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],
@@ -734,7 +762,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/tests/suites/test_suite_gcm.function b/tests/suites/test_suite_gcm.function
index 2b870d1..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 );