Fix alignment problem in serpent.c.
authorVladimir Serbinenko <phcoder@gmail.com>
Thu, 18 Apr 2013 11:22:34 +0000 (13:22 +0200)
committerWerner Koch <wk@gnupg.org>
Thu, 18 Apr 2013 12:48:30 +0000 (14:48 +0200)
* cipher/serpent.c (serpent_key_prepare): Fix misaligned access.
(serpent_setkey): Likewise.
(serpent_encrypt_internal): Likewise.
(serpent_decrypt_internal): Likewise.
(serpent_encrypt): Don't put an alignment-increasing cast.
(serpent_decrypt): Likewise.
(serpent_test): Likewise.
--

This is a port of the fix for the Libgcrypt code in GRUB:
  http://bzr.savannah.gnu.org/lh/grub/trunk/grub/revision/3685
GRUB is FSF copyrighted and thus we can use this code without a DCO.

Note that the above fix was not correct and failed the selftests, thus
I fixed this fix.

GnuPG-bug-id: 1384
Signed-off-by: Werner Koch <wk@gnupg.org>
(cherry picked from commit 8eab66ad6852ec985bfb1e7fec35981d5e31148a)

AUTHORS
cipher/serpent.c

diff --git a/AUTHORS b/AUTHORS
index 5c75b3c..a7a8f3f 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -103,6 +103,11 @@ Assigns Past and Future Changes
 ulm@gentoo.org
 (Changes to cipher/idea.c and related files)
 
+LIBGCRYPT       Vladimir Serbinenko  2012-04-26
+Assigns Past and Future Changes
+phcoder@gmail.com
+(cipher/serpent.c)
+
 
 Authors with a DCO
 ==================
index a78e018..ea14c7e 100644 (file)
@@ -585,15 +585,14 @@ serpent_key_prepare (const byte *key, unsigned int key_length,
   int i;
 
   /* Copy key.  */
-  for (i = 0; i < key_length / 4; i++)
-    {
+  memcpy (key_prepared, key, key_length);
+  key_length /= 4;
 #ifdef WORDS_BIGENDIAN
-      key_prepared[i] = byte_swap_32 (((u32 *) key)[i]);
+  for (i = 0; i < key_length; i++)
+    key_prepared[i] = byte_swap_32 (key_prepared[i]);
 #else
-      key_prepared[i] = ((u32 *) key)[i];
+  i = key_length;
 #endif
-    }
-
   if (i < 8)
     {
       /* Key must be padded according to the Serpent
@@ -707,21 +706,17 @@ serpent_setkey (void *ctx,
 
 static void
 serpent_encrypt_internal (serpent_context_t *context,
-                         const serpent_block_t input, serpent_block_t output)
+                         const byte *input, byte *output)
 {
   serpent_block_t b, b_next;
   int round = 0;
 
+  memcpy (b, input, sizeof (b));
 #ifdef WORDS_BIGENDIAN
-  b[0] = byte_swap_32 (input[0]);
-  b[1] = byte_swap_32 (input[1]);
-  b[2] = byte_swap_32 (input[2]);
-  b[3] = byte_swap_32 (input[3]);
-#else
-  b[0] = input[0];
-  b[1] = input[1];
-  b[2] = input[2];
-  b[3] = input[3];
+  b[0] = byte_swap_32 (b[0]);
+  b[1] = byte_swap_32 (b[1]);
+  b[2] = byte_swap_32 (b[2]);
+  b[3] = byte_swap_32 (b[3]);
 #endif
 
   ROUND (0, context->keys, b, b_next);
@@ -759,35 +754,27 @@ serpent_encrypt_internal (serpent_context_t *context,
   ROUND_LAST (7, context->keys, b, b_next);
 
 #ifdef WORDS_BIGENDIAN
-  output[0] = byte_swap_32 (b_next[0]);
-  output[1] = byte_swap_32 (b_next[1]);
-  output[2] = byte_swap_32 (b_next[2]);
-  output[3] = byte_swap_32 (b_next[3]);
-#else
-  output[0] = b_next[0];
-  output[1] = b_next[1];
-  output[2] = b_next[2];
-  output[3] = b_next[3];
+  b_next[0] = byte_swap_32 (b_next[0]);
+  b_next[1] = byte_swap_32 (b_next[1]);
+  b_next[2] = byte_swap_32 (b_next[2]);
+  b_next[3] = byte_swap_32 (b_next[3]);
 #endif
+  memcpy (output, b_next, sizeof (b_next));
 }
 
 static void
 serpent_decrypt_internal (serpent_context_t *context,
-                         const serpent_block_t input, serpent_block_t output)
+                         const byte *input, byte *output)
 {
   serpent_block_t b, b_next;
   int round = ROUNDS;
 
+  memcpy (b_next, input, sizeof (b));
 #ifdef WORDS_BIGENDIAN
-  b_next[0] = byte_swap_32 (input[0]);
-  b_next[1] = byte_swap_32 (input[1]);
-  b_next[2] = byte_swap_32 (input[2]);
-  b_next[3] = byte_swap_32 (input[3]);
-#else
-  b_next[0] = input[0];
-  b_next[1] = input[1];
-  b_next[2] = input[2];
-  b_next[3] = input[3];
+  b_next[0] = byte_swap_32 (b_next[0]);
+  b_next[1] = byte_swap_32 (b_next[1]);
+  b_next[2] = byte_swap_32 (b_next[2]);
+  b_next[3] = byte_swap_32 (b_next[3]);
 #endif
 
   ROUND_FIRST_INVERSE (7, context->keys, b_next, b);
@@ -824,18 +811,13 @@ serpent_decrypt_internal (serpent_context_t *context,
   ROUND_INVERSE (1, context->keys, b, b_next);
   ROUND_INVERSE (0, context->keys, b, b_next);
 
-
 #ifdef WORDS_BIGENDIAN
-  output[0] = byte_swap_32 (b_next[0]);
-  output[1] = byte_swap_32 (b_next[1]);
-  output[2] = byte_swap_32 (b_next[2]);
-  output[3] = byte_swap_32 (b_next[3]);
-#else
-  output[0] = b_next[0];
-  output[1] = b_next[1];
-  output[2] = b_next[2];
-  output[3] = b_next[3];
+  b_next[0] = byte_swap_32 (b_next[0]);
+  b_next[1] = byte_swap_32 (b_next[1]);
+  b_next[2] = byte_swap_32 (b_next[2]);
+  b_next[3] = byte_swap_32 (b_next[3]);
 #endif
+  memcpy (output, b_next, sizeof (b_next));
 }
 
 static void
@@ -843,8 +825,7 @@ serpent_encrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
 {
   serpent_context_t *context = ctx;
 
-  serpent_encrypt_internal (context,
-                           (const u32 *) buffer_in, (u32 *) buffer_out);
+  serpent_encrypt_internal (context, buffer_in, buffer_out);
   _gcry_burn_stack (2 * sizeof (serpent_block_t));
 }
 
@@ -853,9 +834,7 @@ serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
 {
   serpent_context_t *context = ctx;
 
-  serpent_decrypt_internal (context,
-                           (const u32 *) buffer_in,
-                           (u32 *) buffer_out);
+  serpent_decrypt_internal (context, buffer_in, buffer_out);
   _gcry_burn_stack (2 * sizeof (serpent_block_t));
 }
 
@@ -914,9 +893,7 @@ serpent_test (void)
     {
       serpent_setkey_internal (&context, test_data[i].key,
                                test_data[i].key_length);
-      serpent_encrypt_internal (&context,
-                               (const u32 *) test_data[i].text_plain,
-                               (u32 *) scratch);
+      serpent_encrypt_internal (&context, test_data[i].text_plain, scratch);
 
       if (memcmp (scratch, test_data[i].text_cipher, sizeof (serpent_block_t)))
        switch (test_data[i].key_length)
@@ -929,9 +906,7 @@ serpent_test (void)
            return "Serpent-256 test encryption failed.";
          }
 
-    serpent_decrypt_internal (&context,
-                             (const u32 *) test_data[i].text_cipher,
-                             (u32 *) scratch);
+    serpent_decrypt_internal (&context, test_data[i].text_cipher, scratch);
     if (memcmp (scratch, test_data[i].text_plain, sizeof (serpent_block_t)))
       switch (test_data[i].key_length)
        {