Prepare for 0.9.8k release.
[oweals/openssl.git] / crypto / aes / aes_ctr.c
index aea3db209272189e4e8fcd6638a3e3ed51048e10..f36982be1e26e2c07b3c2116ab598af4a80442f8 100644 (file)
  *
  */
 
+#ifndef AES_DEBUG
+# ifndef NDEBUG
+#  define NDEBUG
+# endif
+#endif
 #include <assert.h>
+
 #include <openssl/aes.h>
 #include "aes_locl.h"
 
-/* NOTE: CTR mode is big-endian.  The rest of the AES code
+/* NOTE: the IV/counter CTR mode is big-endian.  The rest of the AES code
  * is endian-neutral. */
 
-/* increment counter (128-bit int) by 2^64 */
+/* increment counter (128-bit int) by 1 */
 static void AES_ctr128_inc(unsigned char *counter) {
        unsigned long c;
 
-       /* Grab 3rd dword of counter and increment */
-#ifdef L_ENDIAN
-       c = GETU32(counter + 8);
-       c++;
-       PUTU32(counter + 8, c);
-#else
-       c = GETU32(counter + 4);
-       c++;
-       PUTU32(counter + 4, c);
-#endif
+       /* Grab bottom dword of counter and increment */
+       c = GETU32(counter + 12);
+       c++;    c &= 0xFFFFFFFF;
+       PUTU32(counter + 12, c);
+
+       /* if no overflow, we're done */
+       if (c)
+               return;
+
+       /* Grab 1st dword of counter and increment */
+       c = GETU32(counter +  8);
+       c++;    c &= 0xFFFFFFFF;
+       PUTU32(counter +  8, c);
+
+       /* if no overflow, we're done */
+       if (c)
+               return;
+
+       /* Grab 2nd dword of counter and increment */
+       c = GETU32(counter +  4);
+       c++;    c &= 0xFFFFFFFF;
+       PUTU32(counter +  4, c);
 
        /* if no overflow, we're done */
        if (c)
                return;
 
        /* Grab top dword of counter and increment */
-#ifdef L_ENDIAN
-       c = GETU32(counter + 12);
-       c++;
-       PUTU32(counter + 12, c);
-#else
        c = GETU32(counter +  0);
-       c++;
+       c++;    c &= 0xFFFFFFFF;
        PUTU32(counter +  0, c);
-#endif
-
 }
 
 /* The input encrypted as though 128bit counter mode is being
  * used.  The extra state information to record how much of the
- * 128bit block we have used is contained in *num;
+ * 128bit block we have used is contained in *num, and the
+ * encrypted counter is kept in ecount_buf.  Both *num and
+ * ecount_buf must be initialised with zeros before the first
+ * call to AES_ctr128_encrypt().
+ *
+ * This algorithm assumes that the counter is in the x lower bits
+ * of the IV (ivec), and that the application has full control over
+ * overflow and the rest of the IV.  This implementation takes NO
+ * responsability for checking that the counter doesn't overflow
+ * into the rest of the IV when incremented.
  */
 void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out,
        const unsigned long length, const AES_KEY *key,
-       unsigned char *counter, unsigned int *num) {
+       unsigned char ivec[AES_BLOCK_SIZE],
+       unsigned char ecount_buf[AES_BLOCK_SIZE],
+       unsigned int *num) {
 
        unsigned int n;
        unsigned long l=length;
-       unsigned char tmp[AES_BLOCK_SIZE];
 
        assert(in && out && key && counter && num);
+       assert(*num < AES_BLOCK_SIZE);
 
        n = *num;
 
        while (l--) {
                if (n == 0) {
-                       AES_encrypt(counter, tmp, key);
-                       AES_ctr128_inc(counter);
+                       AES_encrypt(ivec, ecount_buf, key);
+                       AES_ctr128_inc(ivec);
                }
-               *(out++) = *(in++) ^ tmp[n];
+               *(out++) = *(in++) ^ ecount_buf[n];
                n = (n+1) % AES_BLOCK_SIZE;
        }