GCM in the cipher layer, step 1
- no support for additional data
- no support for tag
diff --git a/library/cipher.c b/library/cipher.c
index 60e1d91..733f6e5 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -34,6 +34,10 @@
#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)
@@ -285,7 +289,14 @@
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-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 ) )
@@ -392,6 +403,16 @@
ctx->unprocessed_len = 0;
+#if defined(POLARSSL_GCM_C)
+ if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
+ {
+ // TODO: allow other IV length
+ // TODO: allow additional data
+ return gcm_starts( ctx->cipher_ctx, ctx->operation,
+ iv, 12, (unsigned char *) "", 0 );
+ }
+#endif
+
memcpy( ctx->iv, iv, cipher_get_iv_size( ctx ) );
return 0;
@@ -416,7 +437,8 @@
return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
}
- if( ctx->cipher_info->mode == POLARSSL_MODE_CBC )
+ if( ctx->cipher_info->mode == POLARSSL_MODE_CBC ||
+ ctx->cipher_info->mode == POLARSSL_MODE_GCM )
{
/*
* If there is not enough data for a full block, cache it.
@@ -443,6 +465,18 @@
memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input,
copy_len );
+#if defined(POLARSSL_GCM_C)
+ if( ctx->cipher_info->mode == POLARSSL_MODE_GCM )
+ {
+ if( 0 != ( ret = gcm_update( ctx->cipher_ctx,
+ cipher_get_block_size( ctx ),
+ ctx->unprocessed_data, output ) ) )
+ {
+ return ret;
+ }
+ }
+ else
+#endif
if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
ctx->operation, cipher_get_block_size( ctx ), ctx->iv,
ctx->unprocessed_data, output ) ) )
@@ -479,11 +513,23 @@
*/
if( ilen )
{
+#if defined(POLARSSL_GCM_C)
+ if( ctx->cipher_info->mode == POLARSSL_MODE_GCM )
+ {
+ if( 0 != ( ret = gcm_update( ctx->cipher_ctx,
+ ilen, input, output ) ) )
+ {
+ return ret;
+ }
+ }
+ else
+#endif
if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx,
ctx->operation, ilen, ctx->iv, input, output ) ) )
{
return ret;
}
+
*olen += ilen;
}
@@ -712,6 +758,28 @@
return 0;
}
+#if defined(POLARSSL_GCM_C)
+ if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
+ {
+ size_t tag_len = 0; // TODO
+ unsigned char tag[16];
+
+ if( 0 != ( ret = gcm_update( ctx->cipher_ctx,
+ ctx->unprocessed_len, ctx->unprocessed_data,
+ output ) ) )
+ {
+ return( ret );
+ }
+
+ *olen += ctx->unprocessed_len;
+
+ if( 0 != ( ret = gcm_finish( ctx->cipher_ctx, tag, tag_len ) ) )
+ return( ret );
+
+ return( 0 );
+ }
+#endif
+
if( POLARSSL_MODE_CBC == ctx->cipher_info->mode )
{
if( POLARSSL_ENCRYPT == ctx->operation )
diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c
index 562f8b3..c8eee54 100644
--- a/library/cipher_wrap.c
+++ b/library/cipher_wrap.c
@@ -53,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
@@ -235,6 +239,33 @@
#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_setkey_wrap( void *ctx, const unsigned char *key, unsigned int key_length )
+{
+ return gcm_init( (gcm_context *) ctx, key, key_length );
+}
+
+const cipher_base_t gcm_aes_info = {
+ POLARSSL_CIPHER_ID_AES,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ gcm_setkey_wrap,
+ gcm_setkey_wrap,
+ gcm_ctx_alloc,
+ gcm_ctx_free,
+};
+
const cipher_info_t aes_128_gcm_info = {
POLARSSL_CIPHER_AES_128_GCM,
POLARSSL_MODE_GCM,
@@ -242,7 +273,7 @@
"AES-128-GCM",
16,
16,
- &aes_info
+ &gcm_aes_info
};
const cipher_info_t aes_256_gcm_info = {
@@ -252,7 +283,7 @@
"AES-256-GCM",
16,
16,
- &aes_info
+ &gcm_aes_info
};
#endif /* POLARSSL_GCM_C */
diff --git a/library/gcm.c b/library/gcm.c
index 3e9969d..9c079bd 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -293,11 +293,11 @@
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 );
+ memcpy( tag, ctx->base_ectr, tag_len );
+
if( orig_len || orig_add_len )
{
memset( work_buf, 0x00, 16 );
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index cac80a4..20f3c8d 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -44,6 +44,7 @@
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 ad678ea..4d2bcba 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -27,7 +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.arc4 test_suite_cipher.gcm \
test_suite_cipher.blowfish \
test_suite_cipher.camellia \
test_suite_cipher.des test_suite_cipher.null \
@@ -79,6 +79,10 @@
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
@@ -167,6 +171,10 @@
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.function b/tests/suites/test_suite_cipher.function
index 1f7943a4..5377208 100644
--- a/tests/suites/test_suite_cipher.function
+++ b/tests/suites/test_suite_cipher.function
@@ -248,7 +248,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;
diff --git a/tests/suites/test_suite_cipher.gcm.data b/tests/suites/test_suite_cipher.gcm.data
new file mode 100644
index 0000000..aacdca8
--- /dev/null
+++ b/tests/suites/test_suite_cipher.gcm.data
@@ -0,0 +1,110 @@
+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 16 bytes in multiple parts 3
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:1:15
+
+AES 128 GCM Encrypt and decrypt 16 bytes in multiple parts 4
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:15:1
+
+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:15:7
+
+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 1
+depends_on:POLARSSL_AES_C:POLARSSL_GCM_C
+enc_dec_buf_multipart:POLARSSL_CIPHER_AES_128_GCM:128:17:6
+
+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