Split up GCM into a start/update/finish cycle
diff --git a/ChangeLog b/ChangeLog
index ee3d865..6ea2dea6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -16,6 +16,7 @@
      dynamically set (Better support for hardware acceleration)
    * Moved all OID functionality to a separate module. RSA function
      prototypes for the RSA sign and verify functions changed as a result
+   * Split up the GCM module into a starts/update/finish cycle
 
 Bugfix
    * Fix for MPI assembly for ARM
diff --git a/include/polarssl/gcm.h b/include/polarssl/gcm.h
index 77baa17..c703f3b 100644
--- a/include/polarssl/gcm.h
+++ b/include/polarssl/gcm.h
@@ -49,6 +49,12 @@
     aes_context aes_ctx;        /*!< AES context used */
     uint64_t HL[16];            /*!< Precalculated HTable */
     uint64_t HH[16];            /*!< Precalculated HTable */
+    uint64_t len;               /*!< Total data length */
+    uint64_t add_len;           /*!< Total add length */
+    unsigned char base_ectr[16];/*!< First ECTR for tag */
+    unsigned char y[16];        /*!< Y working value */
+    unsigned char buf[16];      /*!< buf working value */
+    int mode;                   /*!< Encrypt or Decrypt */
 }
 gcm_context;
 
@@ -115,7 +121,7 @@
  * \param add       additional data
  * \param add_len   length of additional data
  * \param tag       buffer holding the tag
- * \param tag_len   length of the tag 
+ * \param tag_len   length of the tag
  * \param input     buffer holding the input data
  * \param output    buffer for holding the output data
  *
@@ -128,12 +134,68 @@
                       size_t iv_len,
                       const unsigned char *add,
                       size_t add_len,
-                      const unsigned char *tag, 
+                      const unsigned char *tag,
                       size_t tag_len,
                       const unsigned char *input,
                       unsigned char *output );
 
 /**
+ * \brief           Generic GCM stream start function
+ *
+ * \param ctx       GCM context
+ * \param mode      GCM_ENCRYPT or GCM_DECRYPT
+ * \param iv        initialization vector
+ * \param iv_len    length of IV
+ * \param add       additional data
+ * \param add_len   length of additional data
+ *
+ * \return         0 if successful
+ */
+int gcm_starts( gcm_context *ctx,
+                int mode,
+                const unsigned char *iv,
+                size_t iv_len,
+                const unsigned char *add,
+                size_t add_len );
+
+/**
+ * \brief           Generic GCM update function. Encrypts/decrypts using the
+ *                  given GCM context. Expects input to be a multiple of 16
+ *                  bytes! Only the last call before gcm_finish() can be less
+ *                  than 16 bytes!
+ *
+ * \note On decryption, the output buffer cannot be the same as input buffer.
+ *       If buffers overlap, the output buffer must trail at least 8 bytes
+ *       behind the input buffer.
+ *
+ * \param ctx       GCM context
+ * \param length    length of the input data
+ * \param input     buffer holding the input data
+ * \param output    buffer for holding the output data
+ *
+ * \return         0 if successful or POLARSSL_ERR_GCM_BAD_INPUT
+ */
+int gcm_update( gcm_context *ctx,
+                size_t length,
+                const unsigned char *input,
+                unsigned char *output );
+
+/**
+ * \brief           Generic GCM finalisation function. Wraps up the GCM stream
+ *                  and generated 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_len   length of the tag to generate
+ *
+ * \return         0 if successful or POLARSSL_ERR_GCM_BAD_INPUT
+ */
+int gcm_finish( gcm_context *ctx,
+                unsigned char *tag,
+                size_t tag_len );
+
+/**
  * \brief          Checkup routine
  *
  * \return         0 if successful, or 1 if the test failed
diff --git a/library/gcm.c b/library/gcm.c
index f1daaff..f0bacc6 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -169,41 +169,24 @@
     PUT_UINT32_BE( zl, output, 12 );
 }
 
-int gcm_crypt_and_tag( gcm_context *ctx,
-                       int mode,
-                       size_t length,
-                       const unsigned char *iv,
-                       size_t iv_len,
-                       const unsigned char *add,
-                       size_t add_len,
-                       const unsigned char *input,
-                       unsigned char *output,
-                       size_t tag_len,
-                       unsigned char *tag )
+int gcm_starts( gcm_context *ctx,
+                int mode,
+                const unsigned char *iv,
+                size_t iv_len,
+                const unsigned char *add,
+                size_t add_len )
 {
-    unsigned char y[16];
-    unsigned char ectr[16];
-    unsigned char buf[16];
     unsigned char work_buf[16];
     size_t i;
     const unsigned char *p;
-    unsigned char *out_p = output;
     size_t use_len;
-    uint64_t orig_len = length * 8;
-    uint64_t orig_add_len = add_len * 8;
 
-    memset( y, 0x00, 16 );
-    memset( work_buf, 0x00, 16 );
-    memset( tag, 0x00, tag_len );
-    memset( buf, 0x00, 16 );
-
-    if( output > input && (size_t) ( output - input ) < length )
-        return( POLARSSL_ERR_GCM_BAD_INPUT );
+    ctx->mode = mode;
 
     if( iv_len == 12 )
     {
-        memcpy( y, iv, iv_len );
-        y[15] = 1;
+        memcpy( ctx->y, iv, iv_len );
+        ctx->y[15] = 1;
     }
     else
     {
@@ -216,64 +199,100 @@
             use_len = ( iv_len < 16 ) ? iv_len : 16;
 
             for( i = 0; i < use_len; i++ )
-                y[i] ^= p[i];
+                ctx->y[i] ^= p[i];
 
-            gcm_mult( ctx, y, y );
+            gcm_mult( ctx, ctx->y, ctx->y );
 
             iv_len -= use_len;
             p += use_len;
         }
 
         for( i = 0; i < 16; i++ )
-            y[i] ^= work_buf[i];
+            ctx->y[i] ^= work_buf[i];
 
-        gcm_mult( ctx, y, y );
+        gcm_mult( ctx, ctx->y, ctx->y );
     }
 
-    aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, y, ectr );
-    memcpy( tag, ectr, tag_len );
+    aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->y, ctx->base_ectr );
 
+    ctx->add_len = add_len;
     p = add;
     while( add_len > 0 )
     {
         use_len = ( add_len < 16 ) ? add_len : 16;
 
         for( i = 0; i < use_len; i++ )
-            buf[i] ^= p[i];
+            ctx->buf[i] ^= p[i];
 
-        gcm_mult( ctx, buf, buf );
+        gcm_mult( ctx, ctx->buf, ctx->buf );
 
         add_len -= use_len;
         p += use_len;
     }
 
+    return( 0 );
+}
+
+int gcm_update( gcm_context *ctx,
+                size_t length,
+                const unsigned char *input,
+                unsigned char *output )
+{
+    unsigned char ectr[16];
+    size_t i;
+    const unsigned char *p;
+    unsigned char *out_p = output;
+    size_t use_len;
+
+    if( output > input && (size_t) ( output - input ) < length )
+        return( POLARSSL_ERR_GCM_BAD_INPUT );
+
+    ctx->len += length;
+
     p = input;
     while( length > 0 )
     {
         use_len = ( length < 16 ) ? length : 16;
 
         for( i = 16; i > 12; i-- )
-            if( ++y[i - 1] != 0 )
+            if( ++ctx->y[i - 1] != 0 )
                 break;
 
-        aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, y, ectr );
+        aes_crypt_ecb( &ctx->aes_ctx, AES_ENCRYPT, ctx->y, ectr );
 
         for( i = 0; i < use_len; i++ )
         {
-            if( mode == GCM_DECRYPT )
-                buf[i] ^= p[i];
+            if( ctx->mode == GCM_DECRYPT )
+                ctx->buf[i] ^= p[i];
             out_p[i] = ectr[i] ^ p[i];
-            if( mode == GCM_ENCRYPT )
-                buf[i] ^= out_p[i];
+            if( ctx->mode == GCM_ENCRYPT )
+                ctx->buf[i] ^= out_p[i];
         }
 
-        gcm_mult( ctx, buf, buf );
+        gcm_mult( ctx, ctx->buf, ctx->buf );
 
         length -= use_len;
         p += use_len;
         out_p += use_len;
     }
 
+    return( 0 );
+}
+
+int gcm_finish( gcm_context *ctx,
+                unsigned char *tag,
+                size_t tag_len )
+{
+    unsigned char work_buf[16];
+    size_t i;
+    uint64_t orig_len = ctx->len * 8;
+    uint64_t orig_add_len = ctx->add_len * 8;
+
+    memcpy( tag, ctx->base_ectr, tag_len );
+
+    if( tag_len > 16 )
+        return( POLARSSL_ERR_GCM_BAD_INPUT );
+
     if( orig_len || orig_add_len )
     {
         memset( work_buf, 0x00, 16 );
@@ -284,17 +303,43 @@
         PUT_UINT32_BE( ( orig_len           ), work_buf, 12 );
 
         for( i = 0; i < 16; i++ )
-            buf[i] ^= work_buf[i];
+            ctx->buf[i] ^= work_buf[i];
 
-        gcm_mult( ctx, buf, buf );
+        gcm_mult( ctx, ctx->buf, ctx->buf );
 
         for( i = 0; i < tag_len; i++ )
-            tag[i] ^= buf[i];
+            tag[i] ^= ctx->buf[i];
     }
 
     return( 0 );
 }
 
+int gcm_crypt_and_tag( gcm_context *ctx,
+                       int mode,
+                       size_t length,
+                       const unsigned char *iv,
+                       size_t iv_len,
+                       const unsigned char *add,
+                       size_t add_len,
+                       const unsigned char *input,
+                       unsigned char *output,
+                       size_t tag_len,
+                       unsigned char *tag )
+{
+    int ret;
+
+    if( ( ret = gcm_starts( ctx, mode, iv, iv_len, add, add_len ) ) != 0 )
+        return( ret );
+
+    if( ( ret = gcm_update( ctx, length, input, output ) ) != 0 )
+        return( ret );
+
+    if( ( ret = gcm_finish( ctx, tag, tag_len ) ) != 0 )
+        return( ret );
+
+    return( 0 );
+}
+
 int gcm_auth_decrypt( gcm_context *ctx,
                       size_t length,
                       const unsigned char *iv,
@@ -562,7 +607,9 @@
 
         for( i = 0; i < MAX_TESTS; i++ )
         {
-            printf( "  AES-GCM-%3d #%d (%s): ", key_len, i, "enc" );
+            if( verbose != 0 )
+                printf( "  AES-GCM-%3d #%d (%s): ", key_len, i, "enc" );
+
             gcm_init( &ctx, key[key_index[i]], key_len );
 
             ret = gcm_crypt_and_tag( &ctx, GCM_ENCRYPT,
@@ -584,7 +631,9 @@
             if( verbose != 0 )
                 printf( "passed\n" );
 
-            printf( "  AES-GCM-%3d #%d (%s): ", key_len, i, "dec" );
+            if( verbose != 0 )
+                printf( "  AES-GCM-%3d #%d (%s): ", key_len, i, "dec" );
+
             gcm_init( &ctx, key[key_index[i]], key_len );
 
             ret = gcm_crypt_and_tag( &ctx, GCM_DECRYPT,
@@ -605,10 +654,138 @@
 
             if( verbose != 0 )
                 printf( "passed\n" );
+
+            if( verbose != 0 )
+                printf( "  AES-GCM-%3d #%d split (%s): ", key_len, i, "enc" );
+
+            gcm_init( &ctx, key[key_index[i]], key_len );
+
+            ret = gcm_starts( &ctx, GCM_ENCRYPT,
+                              iv[iv_index[i]], iv_len[i],
+                              additional[add_index[i]], add_len[i] );
+            if( ret != 0 )
+            {
+                if( verbose != 0 )
+                    printf( "failed\n" );
+
+                return( 1 );
+            }
+
+            if( pt_len[i] > 32 )
+            {
+                size_t rest_len = pt_len[i] - 32;
+                ret = gcm_update( &ctx, 32, pt[pt_index[i]], buf );
+                if( ret != 0 )
+                {
+                    if( verbose != 0 )
+                        printf( "failed\n" );
+
+                    return( 1 );
+                }
+
+                ret = gcm_update( &ctx, rest_len, pt[pt_index[i]] + 32, buf + 32 );
+                if( ret != 0 )
+                {
+                    if( verbose != 0 )
+                        printf( "failed\n" );
+
+                    return( 1 );
+                }
+            }
+            else
+            {
+                ret = gcm_update( &ctx, pt_len[i], pt[pt_index[i]], buf );
+                if( ret != 0 )
+                {
+                    if( verbose != 0 )
+                        printf( "failed\n" );
+
+                    return( 1 );
+                }
+            }
+
+            ret = gcm_finish( &ctx, tag_buf, 16 );
+            if( ret != 0 ||
+                memcmp( buf, ct[j * 6 + i], pt_len[i] ) != 0 ||
+                memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+            {
+                if( verbose != 0 )
+                    printf( "failed\n" );
+
+                return( 1 );
+            }
+
+            if( verbose != 0 )
+                printf( "passed\n" );
+
+            if( verbose != 0 )
+                printf( "  AES-GCM-%3d #%d split (%s): ", key_len, i, "dec" );
+
+            gcm_init( &ctx, key[key_index[i]], key_len );
+
+            ret = gcm_starts( &ctx, GCM_DECRYPT,
+                              iv[iv_index[i]], iv_len[i],
+                              additional[add_index[i]], add_len[i] );
+            if( ret != 0 )
+            {
+                if( verbose != 0 )
+                    printf( "failed\n" );
+
+                return( 1 );
+            }
+
+            if( pt_len[i] > 32 )
+            {
+                size_t rest_len = pt_len[i] - 32;
+                ret = gcm_update( &ctx, 32, ct[j * 6 + i], buf );
+                if( ret != 0 )
+                {
+                    if( verbose != 0 )
+                        printf( "failed\n" );
+
+                    return( 1 );
+                }
+
+                ret = gcm_update( &ctx, rest_len, ct[j * 6 + i] + 32, buf + 32 );
+                if( ret != 0 )
+                {
+                    if( verbose != 0 )
+                        printf( "failed\n" );
+
+                    return( 1 );
+                }
+            }
+            else
+            {
+                ret = gcm_update( &ctx, pt_len[i], ct[j * 6 + i], buf );
+                if( ret != 0 )
+                {
+                    if( verbose != 0 )
+                        printf( "failed\n" );
+
+                    return( 1 );
+                }
+            }
+
+            ret = gcm_finish( &ctx, tag_buf, 16 );
+            if( ret != 0 ||
+                memcmp( buf, pt[pt_index[i]], pt_len[i] ) != 0 ||
+                memcmp( tag_buf, tag[j * 6 + i], 16 ) != 0 )
+            {
+                if( verbose != 0 )
+                    printf( "failed\n" );
+
+                return( 1 );
+            }
+
+            if( verbose != 0 )
+                printf( "passed\n" );
+
         }
     }
 
-    printf( "\n" );
+    if( verbose != 0 )
+        printf( "\n" );
 
     return( 0 );
 }
diff --git a/tests/scripts/gen_gcm_decrypt.pl b/tests/scripts/gen_gcm_decrypt.pl
index 2fb76c6..6decac2 100755
--- a/tests/scripts/gen_gcm_decrypt.pl
+++ b/tests/scripts/gen_gcm_decrypt.pl
@@ -91,4 +91,8 @@
         print("\n\n");
     }
 }
+
+print("GCM Selftest\n");
+print("gcm_selftest:\n\n");
+
 close(TEST_DATA);
diff --git a/tests/scripts/gen_gcm_encrypt.pl b/tests/scripts/gen_gcm_encrypt.pl
index de179a9..8adbbce 100755
--- a/tests/scripts/gen_gcm_encrypt.pl
+++ b/tests/scripts/gen_gcm_encrypt.pl
@@ -74,4 +74,8 @@
         print("\n\n");
     }
 }
+
+print("GCM Selftest\n");
+print("gcm_selftest:\n\n");
+
 close(TEST_DATA);
diff --git a/tests/suites/test_suite_gcm.decrypt_128.data b/tests/suites/test_suite_gcm.decrypt_128.data
index 0b714ab..8e12296 100644
--- a/tests/suites/test_suite_gcm.decrypt_128.data
+++ b/tests/suites/test_suite_gcm.decrypt_128.data
@@ -502,3 +502,5 @@
 GCM NIST Validation (AES-128,128,1024,1024,32) #2
 gcm_decrypt_and_verify:"659b9e729d12f68b73fdc2f7260ab114":"fd0732a38224c3f16f58de3a7f333da2ecdb6eec92b469544a891966dd4f8fb64a711a793f1ef6a90e49765eacaccdd8cc438c2b57c51902d27a82ee4f24925a864a9513a74e734ddbf77204a99a3c0060fcfbaccae48fe509bc95c3d6e1b1592889c489801265715e6e4355a45357ce467c1caa2f1c3071bd3a9168a7d223e3":"459df18e2dfbd66d6ad04978432a6d97":"ee0b0b52a729c45b899cc924f46eb1908e55aaaeeaa0c4cdaacf57948a7993a6debd7b6cd7aa426dc3b3b6f56522ba3d5700a820b1697b8170bad9ca7caf1050f13d54fb1ddeb111086cb650e1c5f4a14b6a927205a83bf49f357576fd0f884a83b068154352076a6e36a5369436d2c8351f3e6bfec65b4816e3eb3f144ed7f9":32:"8e5a6a79":"FAIL":0
 
+GCM Selftest
+gcm_selftest:
diff --git a/tests/suites/test_suite_gcm.decrypt_192.data b/tests/suites/test_suite_gcm.decrypt_192.data
index cb57add..476f8ed 100644
--- a/tests/suites/test_suite_gcm.decrypt_192.data
+++ b/tests/suites/test_suite_gcm.decrypt_192.data
@@ -501,3 +501,6 @@
 
 GCM NIST Validation (AES-192,128,1024,1024,32) #2
 gcm_decrypt_and_verify:"b10979797fb8f418a126120d45106e1779b4538751a19bf6":"e3dc64e3c02731fe6e6ec0e899183018da347bf8bd476aa7746d7a7729d83a95f64bb732ba987468d0cede154e28169f7bafa36559200795037ee38279e0e4ca40f9cfa85aa0c8035df9649345c8fdffd1c31528b485dfe443c1923180cc8fae5196d16f822be4ad07e3f1234e1d218e7c8fb37a0e4480dc6717c9c09ff5c45f":"ca362e615024a1fe11286668646cc1de":"237d95d86a5ad46035870f576a1757eded636c7234d5ed0f8039f6f59f1333cc31cb893170d1baa98bd4e79576de920120ead0fdecfb343edbc2fcc556540a91607388a05d43bdb8b55f1327552feed3b620614dfcccb2b342083896cbc81dc9670b761add998913ca813163708a45974e6d7b56dfd0511a72eb879f239d6a6d":32:"28d730ea":"dafde27aa8b3076bfa16ab1d89207d339c4997f8a756cc3eb62c0b023976de808ab640ba4467f2b2ea83d238861229c73387594cd43770386512ea595a70888b4c38863472279e06b923e7cf32438199b3e054ac4bc21baa8df39ddaa207ebb17fa4cad6e83ea58c3a92ec74e6e01b0a8979af145dd31d5df29750bb91b42d45":0
+
+GCM Selftest
+gcm_selftest:
diff --git a/tests/suites/test_suite_gcm.decrypt_256.data b/tests/suites/test_suite_gcm.decrypt_256.data
index 3542aaf..24702b8 100644
--- a/tests/suites/test_suite_gcm.decrypt_256.data
+++ b/tests/suites/test_suite_gcm.decrypt_256.data
@@ -502,3 +502,5 @@
 GCM NIST Validation (AES-256,128,1024,1024,32) #2
 gcm_decrypt_and_verify:"ca264e7caecad56ee31c8bf8dde9592f753a6299e76c60ac1e93cff3b3de8ce9":"8d03cf6fac31182ad3e6f32e4c823e3b421aef786d5651afafbf70ef14c00524ab814bc421b1d4181b4d3d82d6ae4e8032e43a6c4e0691184425b37320798f865c88b9b306466311d79e3e42076837474c37c9f6336ed777f05f70b0c7d72bd4348a4cd754d0f0c3e4587f9a18313ea2d2bace502a24ea417d3041b709a0471f":"4763a4e37b806a5f4510f69fd8c63571":"07daeba37a66ebe15f3d6451d1176f3a7107a302da6966680c425377e621fd71610d1fc9c95122da5bf85f83b24c4b783b1dcd6b508d41e22c09b5c43693d072869601fc7e3f5a51dbd3bc6508e8d095b9130fb6a7f2a043f3a432e7ce68b7de06c1379e6bab5a1a48823b76762051b4e707ddc3201eb36456e3862425cb011a":32:"3105dddb":"FAIL":0
 
+GCM Selftest
+gcm_selftest:
diff --git a/tests/suites/test_suite_gcm.encrypt_128.data b/tests/suites/test_suite_gcm.encrypt_128.data
index d617c42..31cd37f 100644
--- a/tests/suites/test_suite_gcm.encrypt_128.data
+++ b/tests/suites/test_suite_gcm.encrypt_128.data
@@ -501,3 +501,6 @@
 
 GCM NIST Validation (AES-128,128,1024,1024,32) #2
 gcm_encrypt_and_tag:"fe481476fce76efcfc78ed144b0756f1":"246e1f2babab8da98b17cc928bd49504d7d87ea2cc174f9ffb7dbafe5969ff824a0bcb52f35441d22f3edcd10fab0ec04c0bde5abd3624ca25cbb4541b5d62a3deb52c00b75d68aaf0504d51f95b8dcbebdd8433f4966c584ac7f8c19407ca927a79fa4ead2688c4a7baafb4c31ef83c05e8848ec2b4f657aab84c109c91c277":"1a2c18c6bf13b3b2785610c71ccd98ca":"b0ab3cb5256575774b8242b89badfbe0dfdfd04f5dd75a8e5f218b28d3f6bc085a013defa5f5b15dfb46132db58ed7a9ddb812d28ee2f962796ad988561a381c02d1cf37dca5fd33e081d61cc7b3ab0b477947524a4ca4cb48c36f48b302c440be6f5777518a60585a8a16cea510dbfc5580b0daac49a2b1242ff55e91a8eae8":"5587620bbb77f70afdf3cdb7ae390edd0473286d86d3f862ad70902d90ff1d315947c959f016257a8fe1f52cc22a54f21de8cb60b74808ac7b22ea7a15945371e18b77c9571aad631aa080c60c1e472019fa85625fc80ed32a51d05e397a8987c8fece197a566689d24d05361b6f3a75616c89db6123bf5902960b21a18bc03a":32:"bd4265a8":0
+
+GCM Selftest
+gcm_selftest:
diff --git a/tests/suites/test_suite_gcm.encrypt_192.data b/tests/suites/test_suite_gcm.encrypt_192.data
index 6ef7fc6..e2690ae 100644
--- a/tests/suites/test_suite_gcm.encrypt_192.data
+++ b/tests/suites/test_suite_gcm.encrypt_192.data
@@ -501,3 +501,6 @@
 
 GCM NIST Validation (AES-192,128,1024,1024,32) #2
 gcm_encrypt_and_tag:"713358e746dd84ab27b8adb3b17ea59cd75fa6cb0c13d1a8":"35b8b655efdf2d09f5ed0233c9eeb0b6f85e513834848cd594dba3c6e64f78e7af4a7a6d53bba7b43764334d6373360ae3b73b1e765978dffa7dbd805fda7825b8e317e8d3f1314aa97f877be815439c5da845028d1686283735aefac79cdb9e02ec3590091cb507089b9174cd9a6111f446feead91f19b80fd222fc6299fd1c":"26ed909f5851961dd57fa950b437e17c":"c9469ad408764cb7d417f800d3d84f03080cee9bbd53f652763accde5fba13a53a12d990094d587345da2cdc99357b9afd63945ca07b760a2c2d4948dbadb1312670ccde87655a6a68edb5982d2fcf733bb4101d38cdb1a4942a5d410f4c45f5ddf00889bc1fe5ec69b40ae8aaee60ee97bea096eeef0ea71736efdb0d8a5ec9":"cc3f9983e1d673ec2c86ae4c1e1b04e30f9f395f67c36838e15ce825b05d37e9cd40041470224da345aa2da5dfb3e0c561dd05ba7984a1332541d58e8f9160e7e8457e717bab203de3161a72b7aedfa53616b16ca77fd28d566fbf7431be559caa1a129b2f29b9c5bbf3eaba594d6650c62907eb28e176f27c3be7a3aa24cef6":32:"5be7611b":0
+
+GCM Selftest
+gcm_selftest:
diff --git a/tests/suites/test_suite_gcm.encrypt_256.data b/tests/suites/test_suite_gcm.encrypt_256.data
index 68802c2..5d265ff 100644
--- a/tests/suites/test_suite_gcm.encrypt_256.data
+++ b/tests/suites/test_suite_gcm.encrypt_256.data
@@ -502,3 +502,5 @@
 GCM NIST Validation (AES-256,128,1024,1024,32) #2
 gcm_encrypt_and_tag:"1477e189fb3546efac5cc144f25e132ffd0081be76e912e25cbce7ad63f1c2c4":"7bd3ea956f4b938ebe83ef9a75ddbda16717e924dd4e45202560bf5f0cffbffcdd23be3ae08ff30503d698ed08568ff6b3f6b9fdc9ea79c8e53a838cc8566a8b52ce7c21b2b067e778925a066c970a6c37b8a6cfc53145f24bf698c352078a7f0409b53196e00c619237454c190b970842bb6629c0def7f166d19565127cbce0":"c109f35893aff139db8ed51c85fee237":"8f7f9f71a4b2bb0aaf55fced4eb43c57415526162070919b5f8c08904942181820d5847dfd54d9ba707c5e893a888d5a38d0130f7f52c1f638b0119cf7bc5f2b68f51ff5168802e561dff2cf9c5310011c809eba002b2fa348718e8a5cb732056273cc7d01cce5f5837ab0b09b6c4c5321a7f30a3a3cd21f29da79fce3f3728b":"7841e3d78746f07e5614233df7175931e3c257e09ebd7b78545fae484d835ffe3db3825d3aa1e5cc1541fe6cac90769dc5aaeded0c148b5b4f397990eb34b39ee7881804e5a66ccc8d4afe907948780c4e646cc26479e1da874394cb3537a8f303e0aa13bd3cc36f6cc40438bcd41ef8b6a1cdee425175dcd17ee62611d09b02":32:"cb13ce59":0
 
+GCM Selftest
+gcm_selftest: