Change cipher prototypes for GCM
diff --git a/library/cipher.c b/library/cipher.c
index 733f6e5..d7cac05 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -396,7 +396,9 @@
return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
}
-int cipher_reset( cipher_context_t *ctx, const unsigned char *iv )
+int cipher_reset( cipher_context_t *ctx,
+ const unsigned char *iv, size_t iv_len,
+ const unsigned char *ad, size_t ad_len )
{
if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv )
return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA;
@@ -406,11 +408,13 @@
#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 );
+ iv, iv_len, ad, ad_len );
}
+#else
+ ((void) ad);
+ ((void) ad_len);
+ ((void) iv_len);
#endif
memcpy( ctx->iv, iv, cipher_get_iv_size( ctx ) );
@@ -742,7 +746,9 @@
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,
+ unsigned char *tag, size_t tag_len )
{
int ret = 0;
@@ -761,8 +767,9 @@
#if defined(POLARSSL_GCM_C)
if( POLARSSL_MODE_GCM == ctx->cipher_info->mode )
{
- size_t tag_len = 0; // TODO
- unsigned char tag[16];
+ unsigned char check_tag[16];
+ size_t i;
+ int diff;
if( 0 != ( ret = gcm_update( ctx->cipher_ctx,
ctx->unprocessed_len, ctx->unprocessed_data,
@@ -773,11 +780,29 @@
*olen += ctx->unprocessed_len;
- if( 0 != ( ret = gcm_finish( ctx->cipher_ctx, tag, tag_len ) ) )
+ if( 0 != ( ret = gcm_finish( ctx->cipher_ctx, check_tag, tag_len ) ) )
return( ret );
+ /* On encryption, write the tag */
+ if( POLARSSL_ENCRYPT == ctx->operation )
+ {
+ if( tag_len != 0 )
+ memcpy( tag, check_tag, tag_len );
+ return( 0 );
+ }
+
+ /* On decryption, 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 );
}
+#else
+ ((void) tag);
+ ((void) tag_len);
#endif
if( POLARSSL_MODE_CBC == ctx->cipher_info->mode )
diff --git a/library/cipher_wrap.c b/library/cipher_wrap.c
index c8eee54..5c98100 100644
--- a/library/cipher_wrap.c
+++ b/library/cipher_wrap.c
@@ -271,7 +271,7 @@
POLARSSL_MODE_GCM,
128,
"AES-128-GCM",
- 16,
+ 0,
16,
&gcm_aes_info
};
@@ -281,7 +281,7 @@
POLARSSL_MODE_GCM,
256,
"AES-256-GCM",
- 16,
+ 0,
16,
&gcm_aes_info
};
diff --git a/library/gcm.c b/library/gcm.c
index 104fda3..99036a0 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -296,7 +296,8 @@
if( tag_len > 16 )
return( POLARSSL_ERR_GCM_BAD_INPUT );
- memcpy( tag, ctx->base_ectr, tag_len );
+ if( tag_len != 0 )
+ memcpy( tag, ctx->base_ectr, tag_len );
if( orig_len || orig_add_len )
{
diff --git a/library/pkcs12.c b/library/pkcs12.c
index e0d7207..9ccb60a 100644
--- a/library/pkcs12.c
+++ b/library/pkcs12.c
@@ -184,7 +184,7 @@
if( ( ret = cipher_setkey( &cipher_ctx, key, keylen, mode ) ) != 0 )
goto exit;
- if( ( ret = cipher_reset( &cipher_ctx, iv ) ) != 0 )
+ if( ( ret = cipher_reset( &cipher_ctx, iv, 0, NULL, 0 ) ) != 0 )
goto exit;
if( ( ret = cipher_update( &cipher_ctx, data, len,
@@ -193,8 +193,11 @@
goto exit;
}
- if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 )
+ if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen, NULL, 0 ) )
+ != 0 )
+ {
ret = POLARSSL_ERR_PKCS12_PASSWORD_MISMATCH;
+ }
exit:
cipher_free_ctx( &cipher_ctx );
diff --git a/library/pkcs5.c b/library/pkcs5.c
index 9e3ce93..2b6a75a 100644
--- a/library/pkcs5.c
+++ b/library/pkcs5.c
@@ -187,7 +187,7 @@
if( ( ret = cipher_setkey( &cipher_ctx, key, keylen, mode ) ) != 0 )
goto exit;
- if( ( ret = cipher_reset( &cipher_ctx, iv ) ) != 0 )
+ if( ( ret = cipher_reset( &cipher_ctx, iv, 0, NULL, 0 ) ) != 0 )
goto exit;
if( ( ret = cipher_update( &cipher_ctx, data, datalen,
@@ -196,8 +196,11 @@
goto exit;
}
- if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 )
+ if( ( ret = cipher_finish( &cipher_ctx, output + olen, &olen, NULL, 0 ) )
+ != 0 )
+ {
ret = POLARSSL_ERR_PKCS5_PASSWORD_MISMATCH;
+ }
exit:
md_free_ctx( &md_ctx );