diff --git a/ChangeLog b/ChangeLog index cfe985526..48ab5aefa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,7 @@ Note: Most of these features have been donated by Fox-IT 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 f9778df8d..05423294d 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 */ @@ -56,6 +58,34 @@ des3_context; extern "C" { #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) * @@ -64,7 +94,7 @@ extern "C" { * * \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 @@ int des_setkey_enc( des_context *ctx, const unsigned char key[8] ); * * \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 @@ int des_setkey_dec( des_context *ctx, const unsigned char key[8] ); * * \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 @@ int des3_set2key_enc( des3_context *ctx, const unsigned char key[16] ); * * \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 @@ int des3_set2key_dec( des3_context *ctx, const unsigned char key[16] ); * * \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 @@ int des3_set3key_enc( des3_context *ctx, const unsigned char key[24] ); * * \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 f470220d7..39ff216dc 100644 --- a/library/des.c +++ b/library/des.c @@ -290,7 +290,95 @@ static const unsigned long RHs[16] = #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 @@ static void des_setkey( unsigned long SK[32], const unsigned char key[8] ) /* * 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 @@ int des_setkey_enc( des_context *ctx, const unsigned char key[8] ) /* * 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 @@ int des_setkey_dec( des_context *ctx, const unsigned char key[8] ) 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 @@ static void des3_set2key( unsigned long esk[96], /* * 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 @@ int des3_set2key_enc( des3_context *ctx, const unsigned char key[16] ) /* * 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 @@ static void des3_set3key( unsigned long esk[96], /* * 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 @@ int des3_set3key_enc( des3_context *ctx, const unsigned char key[24] ) /* * 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 a317bae49..729164905 100644 --- a/tests/suites/test_suite_des.data +++ b/tests/suites/test_suite_des.data @@ -232,5 +232,8 @@ des_encrypt_cbc:"0123456789abcdef":"fedcba9876543210":"37363534333231204E6F77206 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 59458b86e..ab957a6d9 100644 --- a/tests/suites/test_suite_des.function +++ b/tests/suites/test_suite_des.function @@ -254,6 +254,49 @@ des3_decrypt_cbc:key_count:hex_key_string:hex_iv_string:hex_src_string:hex_dst_s } 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: {