- Support for DES weak keys and parity bits added

diff --git a/ChangeLog b/ChangeLog
index cfe9855..48ab5ae 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -13,6 +13,7 @@
      verification to allow external blacklisting.
    * Improved X509 certificate parsing to include extended
      certificate fields, including Key Usage.
+   * Detection for DES weak keys and parity bits added
 
 = Version 0.14.0 released on 2010-08-16
 Features
diff --git a/include/polarssl/des.h b/include/polarssl/des.h
index f9778df..0542329 100644
--- a/include/polarssl/des.h
+++ b/include/polarssl/des.h
@@ -32,6 +32,8 @@
 
 #define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH               -0x0C00
 
+#define DES_KEY_SIZE    8
+
 /**
  * \brief          DES context structure
  */
@@ -57,6 +59,34 @@
 #endif
 
 /**
+ * \brief          Set key parity on the given key to odd.
+ *
+ *                 DES keys are 56 bits long, but each byte is padded with
+ *                 a parity bit to allow verification.
+ *
+ * \param key      8-byte secret key
+ */
+void des_key_set_parity( unsigned char key[DES_KEY_SIZE] );
+
+/**
+ * \brief          Check that key parity on the given key is odd.
+ *
+ *                 DES keys are 56 bits long, but each byte is padded with
+ *                 a parity bit to allow verification.
+ *
+ * \param key      8-byte secret key
+ */
+int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] );
+
+
+/**
+ * \brief          Check that key is not a weak or semi-weak DES key
+ *
+ * \param key      8-byte secret key
+ */
+int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] );
+
+/**
  * \brief          DES key schedule (56-bit, encryption)
  *
  * \param ctx      DES context to be initialized
@@ -64,7 +94,7 @@
  *
  * \return         0
  */
-int des_setkey_enc( des_context *ctx, const unsigned char key[8] );
+int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] );
 
 /**
  * \brief          DES key schedule (56-bit, decryption)
@@ -74,7 +104,7 @@
  *
  * \return         0
  */
-int des_setkey_dec( des_context *ctx, const unsigned char key[8] );
+int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] );
 
 /**
  * \brief          Triple-DES key schedule (112-bit, encryption)
@@ -84,7 +114,7 @@
  *
  * \return         0
  */
-int des3_set2key_enc( des3_context *ctx, const unsigned char key[16] );
+int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] );
 
 /**
  * \brief          Triple-DES key schedule (112-bit, decryption)
@@ -94,7 +124,7 @@
  *
  * \return         0
  */
-int des3_set2key_dec( des3_context *ctx, const unsigned char key[16] );
+int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] );
 
 /**
  * \brief          Triple-DES key schedule (168-bit, encryption)
@@ -104,7 +134,7 @@
  *
  * \return         0
  */
-int des3_set3key_enc( des3_context *ctx, const unsigned char key[24] );
+int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] );
 
 /**
  * \brief          Triple-DES key schedule (168-bit, decryption)
@@ -114,7 +144,7 @@
  *
  * \return         0
  */
-int des3_set3key_dec( des3_context *ctx, const unsigned char key[24] );
+int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] );
 
 /**
  * \brief          DES-ECB block encryption/decryption
diff --git a/library/des.c b/library/des.c
index f470220..39ff216 100644
--- a/library/des.c
+++ b/library/des.c
@@ -290,7 +290,95 @@
 
 #define SWAP(a,b) { unsigned long t = a; a = b; b = t; t = 0; }
 
-static void des_setkey( unsigned long SK[32], const unsigned char key[8] )
+static const unsigned char odd_parity_table[128] = { 1,  2,  4,  7,  8,
+        11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44,
+        47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81,
+        82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112,
+        115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140,
+        143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168,
+        171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196,
+        199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224,
+        227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253,
+        254 };
+
+void des_key_set_parity( unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+
+    for( i = 0; i < DES_KEY_SIZE; i++ )
+        key[i] = odd_parity_table[key[i] / 2];
+}
+
+/*
+ * Check the given key's parity, returns 1 on failure, 0 on SUCCESS
+ */
+int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+
+    for( i = 0; i < DES_KEY_SIZE; i++ )
+        if ( key[i] != odd_parity_table[key[i] / 2] )
+            return( 1 );
+
+    return( 0 );
+}
+
+/*
+ * Table of weak and semi-weak keys
+ *
+ * Source: http://en.wikipedia.org/wiki/Weak_key
+ *
+ * Weak:
+ * Alternating ones + zeros (0x0101010101010101)
+ * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE)
+ * '0xE0E0E0E0F1F1F1F1'
+ * '0x1F1F1F1F0E0E0E0E'
+ *
+ * Semi-weak:
+ * 0x011F011F010E010E and 0x1F011F010E010E01
+ * 0x01E001E001F101F1 and 0xE001E001F101F101
+ * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01
+ * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E
+ * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E
+ * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1
+ *
+ */
+
+#define WEAK_KEY_COUNT 16
+
+static const unsigned char weak_key_table[WEAK_KEY_COUNT][DES_KEY_SIZE] =
+{
+    { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
+    { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE },
+    { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E },
+    { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 },
+
+    { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E },
+    { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 },
+    { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 },
+    { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 },
+    { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE },
+    { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 },
+    { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 },
+    { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E },
+    { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE },
+    { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E },
+    { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE },
+    { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 }
+};
+
+int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] )
+{
+    int i;
+
+    for( i = 0; i < WEAK_KEY_COUNT; i++ )
+        if( memcmp( weak_key_table[i], key, DES_KEY_SIZE) == 0)
+            return( 0 );
+
+    return( 1 );
+}
+
+static void des_setkey( unsigned long SK[32], const unsigned char key[DES_KEY_SIZE] )
 {
     int i;
     unsigned long X, Y, T;
@@ -362,7 +450,7 @@
 /*
  * DES key schedule (56-bit, encryption)
  */
-int des_setkey_enc( des_context *ctx, const unsigned char key[8] )
+int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] )
 {
     des_setkey( ctx->sk, key );
 
@@ -372,7 +460,7 @@
 /*
  * DES key schedule (56-bit, decryption)
  */
-int des_setkey_dec( des_context *ctx, const unsigned char key[8] )
+int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] )
 {
     int i;
 
@@ -389,7 +477,7 @@
 
 static void des3_set2key( unsigned long esk[96],
                           unsigned long dsk[96],
-                          const unsigned char key[16] )
+                          const unsigned char key[DES_KEY_SIZE*2] )
 {
     int i;
 
@@ -415,7 +503,7 @@
 /*
  * Triple-DES key schedule (112-bit, encryption)
  */
-int des3_set2key_enc( des3_context *ctx, const unsigned char key[16] )
+int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] )
 {
     unsigned long sk[96];
 
@@ -428,7 +516,7 @@
 /*
  * Triple-DES key schedule (112-bit, decryption)
  */
-int des3_set2key_dec( des3_context *ctx, const unsigned char key[16] )
+int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] )
 {
     unsigned long sk[96];
 
@@ -464,7 +552,7 @@
 /*
  * Triple-DES key schedule (168-bit, encryption)
  */
-int des3_set3key_enc( des3_context *ctx, const unsigned char key[24] )
+int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] )
 {
     unsigned long sk[96];
 
@@ -477,7 +565,7 @@
 /*
  * Triple-DES key schedule (168-bit, decryption)
  */
-int des3_set3key_dec( des3_context *ctx, const unsigned char key[24] )
+int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] )
 {
     unsigned long sk[96];
 
diff --git a/tests/suites/test_suite_des.data b/tests/suites/test_suite_des.data
index a317bae..7291649 100644
--- a/tests/suites/test_suite_des.data
+++ b/tests/suites/test_suite_des.data
@@ -232,5 +232,8 @@
 3DES-CBC 3Key Encrypt (Invalid input length)
 des3_encrypt_cbc:3:"0123456789abcdeff1e0d3c2b5a49786fedcba9876543210":"fedcba9876543210":"37363534333231204E6F77206973207468652074696D65":"":POLARSSL_ERR_DES_INVALID_INPUT_LENGTH
 
+Run through parity bit tests
+des_key_parity_run:
+
 DES Selftest
 des_selftest:
diff --git a/tests/suites/test_suite_des.function b/tests/suites/test_suite_des.function
index 59458b8..ab957a6 100644
--- a/tests/suites/test_suite_des.function
+++ b/tests/suites/test_suite_des.function
@@ -255,6 +255,49 @@
 END_CASE
 
 BEGIN_CASE
+des_key_parity_run:
+{
+    int i, j, cnt;
+    unsigned char key[DES_KEY_SIZE];
+    unsigned int parity;
+
+    memset( key, 0, DES_KEY_SIZE );
+    cnt = 0;
+
+    // Iterate through all possible byte values
+    //
+    for( i = 0; i < 32; i++ )
+    {
+        for( j = 0; j < 8; j++ )
+            key[j] = cnt++;
+
+        // Set the key parity according to the table
+        //
+        des_key_set_parity( key );
+
+        // Check the parity with a function
+        //
+        for( j = 0; j < 8; j++ )
+        {
+            parity = key[j] ^ ( key[j] >> 4 );
+            parity = parity ^
+                    ( parity >> 1 ) ^
+                    ( parity >> 2 ) ^
+                    ( parity >> 3 );
+            parity &= 1;
+
+            if( parity != 1 )
+                TEST_ASSERT( 0 );
+        }
+
+        // Check the parity with the table
+        //
+        TEST_ASSERT( des_key_check_key_parity( key ) == 0 );
+    }
+}
+END_CASE
+
+BEGIN_CASE
 des_selftest:
 {
     TEST_ASSERT( des_self_test( 0 ) == 0 );