CCM source cosmetics/tune-ups
- source a bit shorter
- generated code slightly smaller
- preserving performance
diff --git a/library/ccm.c b/library/ccm.c
index fafa238..98987b2 100644
--- a/library/ccm.c
+++ b/library/ccm.c
@@ -84,33 +84,33 @@
memset( ctx, 0, sizeof( ccm_context ) );
}
-#define UPDATE_CBC_MAC( src ) \
-{ \
- size_t olen; \
- \
- for( i = 0; i < 16; i++ ) \
- src[i] ^= y[i]; \
- \
- if( ( ret = cipher_update( &ctx->cipher_ctx, src, 16, \
- y, &olen ) ) != 0 ) \
- { \
- return( ret ); \
- } \
-}
+/*
+ * Macros for common operations.
+ * Results in smaller compiled code than static inline functions.
+ */
-#define CTR_CRYPT_BLOCK( dst, src ) \
-{ \
- size_t olen; \
- \
- if( ( ret = cipher_update( &ctx->cipher_ctx, ctr, 16, \
- dst, &olen ) ) != 0 ) \
- { \
- return( ret ); \
- } \
- \
- for( i = 0; i < 16; i++ ) \
- dst[i] ^= src[i]; \
-}
+/*
+ * Update the CBC-MAC state in y using a block in b
+ * (Always using b as the source helps the compiler optimise a bit better.)
+ */
+#define UPDATE_CBC_MAC \
+ for( i = 0; i < 16; i++ ) \
+ y[i] ^= b[i]; \
+ \
+ if( ( ret = cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \
+ return( ret );
+
+/*
+ * Encrypt or decrypt a partial block with CTR
+ * Warning: using b for temporary storage! src and dst must not be b!
+ * (This avoids allocating one more 16 bytes buffer.)
+ */
+#define CTR_CRYPT( dst, src, len ) \
+ if( ( ret = cipher_update( &ctx->cipher_ctx, ctr, 16, b, &olen ) ) != 0 ) \
+ return( ret ); \
+ \
+ for( i = 0; i < len; i++ ) \
+ dst[i] = src[i] ^ b[i];
/*
* Authenticated encryption or decryption
@@ -124,7 +124,7 @@
int ret;
unsigned char i;
unsigned char q = 16 - 1 - iv_len;
- size_t len_left;
+ size_t len_left, olen;
unsigned char b[16];
unsigned char y[16];
unsigned char ctr[16];
@@ -174,7 +174,7 @@
/* Start CBC-MAC with first block */
memset( y, 0, 16 );
- UPDATE_CBC_MAC( b );
+ UPDATE_CBC_MAC;
/*
* If there is additional data, update CBC-MAC with
@@ -195,28 +195,23 @@
len_left -= use_len;
src += use_len;
- UPDATE_CBC_MAC( b );
+ UPDATE_CBC_MAC;
- while( len_left > 16 )
+ while( len_left > 0 )
{
- memcpy( b, src, 16 );
- UPDATE_CBC_MAC( b );
+ use_len = len_left > 16 ? 16 : len_left;
- len_left -= 16;
- src += 16;
- }
-
- if( len_left > 0 )
- {
memset( b, 0, 16 );
- memcpy( b, src, len_left );
+ memcpy( b, src, use_len );
+ UPDATE_CBC_MAC;
- UPDATE_CBC_MAC( b );
+ len_left -= use_len;
+ src += use_len;
}
}
/*
- * Counter block:
+ * Prepare counter block for encryption:
* 0 .. 0 flags
* 1 .. iv_len nonce (aka iv)
* iv_len+1 .. 15 counter (initially 1)
@@ -230,34 +225,39 @@
memset( ctr + 1 + iv_len, 0, q );
ctr[15] = 1;
+ /*
+ * Authenticate and {en,de}crypt the message.
+ *
+ * The only difference between encryption and decryption is
+ * the respective order of authentication and {en,de}cryption.
+ */
len_left = length;
src = input;
dst = output;
- /*
- * Authenticate and crypt message
- * The only difference between encryption and decryption is
- * the respective order of authentication and {en,de}cryption
- */
- while( len_left > 16 )
+ while( len_left > 0 )
{
+ unsigned char use_len = len_left > 16 ? 16 : len_left;
+
if( mode == CCM_ENCRYPT )
{
- memcpy( b, src, 16 );
- UPDATE_CBC_MAC( b );
+ memset( b, 0, 16 );
+ memcpy( b, src, use_len );
+ UPDATE_CBC_MAC;
}
- CTR_CRYPT_BLOCK( dst, src );
+ CTR_CRYPT( dst, src, use_len );
if( mode == CCM_DECRYPT )
{
- memcpy( b, dst, 16 );
- UPDATE_CBC_MAC( b );
+ memset( b, 0, 16 );
+ memcpy( b, dst, use_len );
+ UPDATE_CBC_MAC;
}
- dst += 16;
- src += 16;
- len_left -= 16;
+ dst += use_len;
+ src += use_len;
+ len_left -= use_len;
/*
* Increment counter.
@@ -268,43 +268,14 @@
break;
}
- if( len_left > 0 )
- {
- unsigned char mask[16];
- size_t olen;
-
- if( mode == CCM_ENCRYPT )
- {
- memset( b, 0, 16 );
- memcpy( b, src, len_left );
- UPDATE_CBC_MAC( b );
- }
-
- if( ( ret = cipher_update( &ctx->cipher_ctx, ctr, 16,
- mask, &olen ) ) != 0 )
- {
- return( ret );
- }
-
- for( i = 0; i < len_left; i++ )
- dst[i] = src[i] ^ mask[i];
-
- if( mode == CCM_DECRYPT )
- {
- memset( b, 0, 16 );
- memcpy( b, dst, len_left );
- UPDATE_CBC_MAC( b );
- }
- }
-
/*
- * Authentication: reset counter and {en,de}crypt internal tag
+ * Authentication: reset counter and crypt/mask internal tag
*/
for( i = 0; i < q; i++ )
ctr[15-i] = 0;
- CTR_CRYPT_BLOCK( b, y );
- memcpy( tag, b, tag_len );
+ CTR_CRYPT( y, y, 16 );
+ memcpy( tag, y, tag_len );
return( 0 );
}