rijndael: refactor to reduce number of #ifdefs and branches
[libgcrypt.git] / cipher / cipher-ccm.c
index ebcbf1e..3d5f220 100644 (file)
@@ -1,5 +1,5 @@
 /* cipher-ccm.c - CTR mode with CBC-MAC mode implementation
- * Copyright © 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ * Copyright (C) 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi>
  *
  * This file is part of Libgcrypt.
  *
 
 #include "g10lib.h"
 #include "cipher.h"
-#include "ath.h"
 #include "bufhelp.h"
 #include "./cipher-internal.h"
 
+/* We need a 64 bit type for this code.  */
+#ifdef HAVE_U64_TYPEDEF
+
 
 #define set_burn(burn, nburn) do { \
   unsigned int __nburn = (nburn); \
@@ -149,14 +151,14 @@ _gcry_cipher_ccm_set_nonce (gcry_cipher_hd_t c, const unsigned char *nonce,
 
 
 gcry_err_code_t
-_gcry_cipher_ccm_set_lengths (gcry_cipher_hd_t c, size_t encryptlen,
-                              size_t aadlen, size_t taglen)
+_gcry_cipher_ccm_set_lengths (gcry_cipher_hd_t c, u64 encryptlen, u64 aadlen,
+                              u64 taglen)
 {
   unsigned int burn = 0;
   unsigned char b0[16];
   size_t noncelen = 15 - (c->u_iv.iv[0] + 1);
-  size_t M = taglen;
-  size_t M_;
+  u64 M = taglen;
+  u64 M_;
   int i;
 
   M_ = (M - 2) / 2;
@@ -164,7 +166,7 @@ _gcry_cipher_ccm_set_lengths (gcry_cipher_hd_t c, size_t encryptlen,
   /* Authentication field must be 4, 6, 8, 10, 12, 14 or 16. */
   if ((M_ * 2 + 2) != M || M < 4 || M > 16)
     return GPG_ERR_INV_LENGTH;
-  if (!c->u_mode.ccm.nonce || c->u_mode.ccm.tag)
+  if (!c->u_mode.ccm.nonce || c->marks.tag)
     return GPG_ERR_INV_STATE;
   if (c->u_mode.ccm.lengths)
     return GPG_ERR_INV_STATE;
@@ -203,7 +205,6 @@ _gcry_cipher_ccm_set_lengths (gcry_cipher_hd_t c, size_t encryptlen,
       buf_put_be32(&b0[2], aadlen);
       set_burn (burn, do_cbc_mac (c, b0, 6, 0));
     }
-#ifdef HAVE_U64_TYPEDEF
   else if (aadlen > (unsigned int)0xffffffff)
     {
       b0[0] = 0xff;
@@ -211,7 +212,6 @@ _gcry_cipher_ccm_set_lengths (gcry_cipher_hd_t c, size_t encryptlen,
       buf_put_be64(&b0[2], aadlen);
       set_burn (burn, do_cbc_mac (c, b0, 10, 0));
     }
-#endif
 
   /* Generate S_0 and increase counter.  */
   set_burn (burn, c->spec->encrypt ( &c->context.c, c->u_mode.ccm.s0,
@@ -235,7 +235,7 @@ _gcry_cipher_ccm_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf,
 
   if (abuflen > 0 && !abuf)
     return GPG_ERR_INV_ARG;
-  if (!c->u_mode.ccm.nonce || !c->u_mode.ccm.lengths || c->u_mode.ccm.tag)
+  if (!c->u_mode.ccm.nonce || !c->u_mode.ccm.lengths || c->marks.tag)
     return GPG_ERR_INV_STATE;
   if (abuflen > c->u_mode.ccm.aadlen)
     return GPG_ERR_INV_LENGTH;
@@ -267,7 +267,7 @@ _gcry_cipher_ccm_tag (gcry_cipher_hd_t c, unsigned char *outbuf,
   if (c->u_mode.ccm.encryptlen > 0)
     return GPG_ERR_UNFINISHED;
 
-  if (!c->u_mode.ccm.tag)
+  if (!c->marks.tag)
     {
       burn = do_cbc_mac (c, NULL, 0, 1); /* Perform final padding.  */
 
@@ -280,6 +280,8 @@ _gcry_cipher_ccm_tag (gcry_cipher_hd_t c, unsigned char *outbuf,
 
       if (burn)
         _gcry_burn_stack (burn + sizeof(void *) * 5);
+
+      c->marks.tag = 1;
     }
 
   if (!check)
@@ -289,13 +291,8 @@ _gcry_cipher_ccm_tag (gcry_cipher_hd_t c, unsigned char *outbuf,
     }
   else
     {
-      int diff, i;
-
-      /* Constant-time compare. */
-      for (i = 0, diff = 0; i < outbuflen; i++)
-        diff -= !!(outbuf[i] - c->u_iv.iv[i]);
-
-      return !diff ? GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM;
+      return buf_eq_const(outbuf, c->u_iv.iv, outbuflen) ?
+             GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM;
     }
 }
 
@@ -304,7 +301,7 @@ gcry_err_code_t
 _gcry_cipher_ccm_get_tag (gcry_cipher_hd_t c, unsigned char *outtag,
                          size_t taglen)
 {
-       return _gcry_cipher_ccm_tag (c, outtag, taglen, 0);
+  return _gcry_cipher_ccm_tag (c, outtag, taglen, 0);
 }
 
 
@@ -312,20 +309,20 @@ gcry_err_code_t
 _gcry_cipher_ccm_check_tag (gcry_cipher_hd_t c, const unsigned char *intag,
                            size_t taglen)
 {
-       return _gcry_cipher_ccm_tag (c, (unsigned char *)intag, taglen, 1);
+  return _gcry_cipher_ccm_tag (c, (unsigned char *)intag, taglen, 1);
 }
 
 
 gcry_err_code_t
 _gcry_cipher_ccm_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
-                          unsigned int outbuflen, const unsigned char *inbuf,
-                          unsigned int inbuflen)
+                          size_t outbuflen, const unsigned char *inbuf,
+                          size_t inbuflen)
 {
   unsigned int burn;
 
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
-  if (!c->u_mode.ccm.nonce || c->u_mode.ccm.tag || !c->u_mode.ccm.lengths ||
+  if (!c->u_mode.ccm.nonce || c->marks.tag || !c->u_mode.ccm.lengths ||
       c->u_mode.ccm.aadlen > 0)
     return GPG_ERR_INV_STATE;
   if (inbuflen > c->u_mode.ccm.encryptlen)
@@ -342,15 +339,15 @@ _gcry_cipher_ccm_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
 
 gcry_err_code_t
 _gcry_cipher_ccm_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
-                          unsigned int outbuflen, const unsigned char *inbuf,
-                          unsigned int inbuflen)
+                          size_t outbuflen, const unsigned char *inbuf,
+                          size_t inbuflen)
 {
   gcry_err_code_t err;
   unsigned int burn;
 
   if (outbuflen < inbuflen)
     return GPG_ERR_BUFFER_TOO_SHORT;
-  if (!c->u_mode.ccm.nonce || c->u_mode.ccm.tag || !c->u_mode.ccm.lengths ||
+  if (!c->u_mode.ccm.nonce || c->marks.tag || !c->u_mode.ccm.lengths ||
       c->u_mode.ccm.aadlen > 0)
     return GPG_ERR_INV_STATE;
   if (inbuflen > c->u_mode.ccm.encryptlen)
@@ -367,3 +364,78 @@ _gcry_cipher_ccm_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf,
 
   return err;
 }
+
+#else
+
+/*
+ * Provide dummy functions so that we avoid adding too much #ifdefs in
+ * cipher.c.
+ */
+
+gcry_err_code_t
+_gcry_cipher_ccm_encrypt(gcry_cipher_hd_t c, unsigned char *outbuf,
+                        size_t outbuflen, const unsigned char *inbuf,
+                        size_t inbuflen)
+{
+  (void)c;
+  (void)outbuf;
+  (void)outbuflen;
+  (void)inbuf;
+  (void)inbuflen;
+  return GPG_ERR_NOT_SUPPORTED;
+}
+
+gcry_err_code_t
+_gcry_cipher_ccm_decrypt(gcry_cipher_hd_t c, unsigned char *outbuf,
+                        size_t outbuflen, const unsigned char *inbuf,
+                        size_t inbuflen)
+{
+  (void)c;
+  (void)outbuf;
+  (void)outbuflen;
+  (void)inbuf;
+  (void)inbuflen;
+  return GPG_ERR_NOT_SUPPORTED;
+}
+
+gcry_err_code_t
+_gcry_cipher_ccm_set_nonce(gcry_cipher_hd_t c, const unsigned char *nonce,
+                          size_t noncelen)
+{
+  (void)c;
+  (void)nonce;
+  (void)noncelen;
+  return GPG_ERR_NOT_SUPPORTED;
+}
+
+gcry_err_code_t
+_gcry_cipher_ccm_authenticate(gcry_cipher_hd_t c, const unsigned char *abuf,
+                             size_t abuflen)
+{
+  (void)c;
+  (void)abuf;
+  (void)abuflen;
+  return GPG_ERR_NOT_SUPPORTED;
+}
+
+gcry_err_code_t
+_gcry_cipher_ccm_get_tag(gcry_cipher_hd_t c, unsigned char *outtag,
+                        size_t taglen)
+{
+  (void)c;
+  (void)outtag;
+  (void)taglen;
+  return GPG_ERR_NOT_SUPPORTED;
+}
+
+gcry_err_code_t
+_gcry_cipher_ccm_check_tag(gcry_cipher_hd_t c, const unsigned char *intag,
+                          size_t taglen)
+{
+  (void)c;
+  (void)intag;
+  (void)taglen;
+  return GPG_ERR_NOT_SUPPORTED;
+}
+
+#endif /*HAVE_U64_TYPEDEF*/