Mercurial > pidgin
changeset 21907:03463c52b9d7
Triple DES cipher support from Elliott Sales de Andrade
committer: Gary Kramlich <grim@reaperworld.com>
author | Elliott Sales de Andrade <qulogic@pidgin.im> |
---|---|
date | Thu, 20 Dec 2007 03:40:56 +0000 |
parents | 47aabef7f802 |
children | f786e478e08b |
files | libpurple/cipher.c libpurple/cipher.h libpurple/tests/test_cipher.c |
diffstat | 3 files changed, 742 insertions(+), 47 deletions(-) [+] |
line wrap: on
line diff
--- a/libpurple/cipher.c Wed Dec 19 15:54:54 2007 +0000 +++ b/libpurple/cipher.c Thu Dec 20 03:40:56 2007 +0000 @@ -340,11 +340,11 @@ NULL, /* get salt size */ NULL, /* set key */ NULL, /* get key size */ + NULL, /* set batch mode */ + NULL, /* get batch mode */ /* padding */ NULL, - NULL, - NULL, NULL }; @@ -595,11 +595,11 @@ NULL, /* get salt size */ NULL, /* set key */ NULL, /* get key size */ + NULL, /* set batch mode */ + NULL, /* get batch mode */ /* padding */ NULL, - NULL, - NULL, NULL }; @@ -986,6 +986,36 @@ return 0; } +static gint +des_decrypt(PurpleCipherContext *context, const guchar data[], + size_t len, guchar output[], size_t *outlen) { + int offset = 0; + int i = 0; + int tmp; + guint8 buf[8] = {0,0,0,0,0,0,0,0}; + while(offset+8<=len) { + des_ecb_crypt(purple_cipher_context_get_data(context), + data+offset, + output+offset, + 1); + offset+=8; + } + *outlen = len; + if(offset<len) { + *outlen += len - offset; + tmp = offset; + while(tmp<len) { + buf[i++] = data[tmp]; + tmp++; + } + des_ecb_crypt(purple_cipher_context_get_data(context), + buf, + output+offset, + 1); + } + return 0; +} + static void des_init(PurpleCipherContext *context, gpointer extra) { struct _des_ctx *mctx; @@ -1005,29 +1035,380 @@ } static PurpleCipherOps DESOps = { - NULL, /* Set option */ - NULL, /* Get option */ - des_init, /* init */ - NULL, /* reset */ - des_uninit, /* uninit */ - NULL, /* set iv */ - NULL, /* append */ - NULL, /* digest */ - des_encrypt, /* encrypt */ - NULL, /* decrypt */ - NULL, /* set salt */ - NULL, /* get salt size */ - des_set_key, /* set key */ - NULL, /* get key size */ + NULL, /* Set option */ + NULL, /* Get option */ + des_init, /* init */ + NULL, /* reset */ + des_uninit, /* uninit */ + NULL, /* set iv */ + NULL, /* append */ + NULL, /* digest */ + des_encrypt, /* encrypt */ + des_decrypt, /* decrypt */ + NULL, /* set salt */ + NULL, /* get salt size */ + des_set_key, /* set key */ + NULL, /* get key size */ + NULL, /* set batch mode */ + NULL, /* get batch mode */ /* padding */ NULL, - NULL, + NULL +}; + +/****************************************************************************** + * Triple-DES + *****************************************************************************/ + +typedef struct _des3_ctx +{ + PurpleCipherBatchMode mode; + guchar iv[8]; + /* First key for encryption */ + struct _des_ctx key1; + /* Second key for decryption */ + struct _des_ctx key2; + /* Third key for encryption */ + struct _des_ctx key3; +} des3_ctx[1]; + +/* + * Fill a DES3 context with subkeys calculated from 3 64bit key. + * Does not check parity bits, but simply ignore them. + * Does not check for weak keys. + **/ +static void +des3_set_key(PurpleCipherContext *context, const guchar * key) +{ + struct _des3_ctx *ctx = purple_cipher_context_get_data(context); + int i; + + des_key_schedule (key + 0, ctx->key1.encrypt_subkeys); + des_key_schedule (key + 8, ctx->key2.encrypt_subkeys); + des_key_schedule (key + 16, ctx->key3.encrypt_subkeys); + + for (i = 0; i < 32; i += 2) + { + ctx->key1.decrypt_subkeys[i] = ctx->key1.encrypt_subkeys[30-i]; + ctx->key1.decrypt_subkeys[i+1] = ctx->key1.encrypt_subkeys[31-i]; + ctx->key2.decrypt_subkeys[i] = ctx->key2.encrypt_subkeys[30-i]; + ctx->key2.decrypt_subkeys[i+1] = ctx->key2.encrypt_subkeys[31-i]; + ctx->key3.decrypt_subkeys[i] = ctx->key3.encrypt_subkeys[30-i]; + ctx->key3.decrypt_subkeys[i+1] = ctx->key3.encrypt_subkeys[31-i]; + } +} + +static gint +des3_ecb_encrypt(struct _des3_ctx *ctx, const guchar data[], + size_t len, guchar output[], size_t *outlen) +{ + int offset = 0; + int i = 0; + int tmp; + guint8 buf[8] = {0,0,0,0,0,0,0,0}; + while (offset + 8 <= len) { + des_ecb_crypt(&ctx->key1, + data+offset, + output+offset, + 0); + des_ecb_crypt(&ctx->key2, + output+offset, + buf, + 1); + des_ecb_crypt(&ctx->key3, + buf, + output+offset, + 0); + offset += 8; + } + *outlen = len; + if (offset < len) { + *outlen += len - offset; + tmp = offset; + memset(buf, 0, 8); + while (tmp < len) { + buf[i++] = data[tmp]; + tmp++; + } + des_ecb_crypt(&ctx->key1, + buf, + output+offset, + 0); + des_ecb_crypt(&ctx->key2, + output+offset, + buf, + 1); + des_ecb_crypt(&ctx->key3, + buf, + output+offset, + 0); + } + return 0; +} + +static gint +des3_cbc_encrypt(struct _des3_ctx *ctx, const guchar data[], + size_t len, guchar output[], size_t *outlen) +{ + int offset = 0; + int i = 0; + int tmp; + guint8 buf[8]; + memcpy(buf, ctx->iv, 8); + while (offset + 8 <= len) { + for (i = 0; i < 8; i++) + buf[i] ^= data[offset + i]; + des_ecb_crypt(&ctx->key1, + buf, + output+offset, + 0); + des_ecb_crypt(&ctx->key2, + output+offset, + buf, + 1); + des_ecb_crypt(&ctx->key3, + buf, + output+offset, + 0); + memcpy(buf, output+offset, 8); + offset += 8; + } + *outlen = len; + if (offset < len) { + *outlen += len - offset; + tmp = offset; + i = 0; + while (tmp < len) { + buf[i++] ^= data[tmp]; + tmp++; + } + des_ecb_crypt(&ctx->key1, + buf, + output+offset, + 0); + des_ecb_crypt(&ctx->key2, + output+offset, + buf, + 1); + des_ecb_crypt(&ctx->key3, + buf, + output+offset, + 0); + } + return 0; +} + +static gint +des3_encrypt(PurpleCipherContext *context, const guchar data[], + size_t len, guchar output[], size_t *outlen) +{ + struct _des3_ctx *ctx = purple_cipher_context_get_data(context); + + if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { + return des3_ecb_encrypt(ctx, data, len, output, outlen); + } else if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { + return des3_cbc_encrypt(ctx, data, len, output, outlen); + } else { + g_return_val_if_reached(0); + } + + return 0; +} + +static gint +des3_ecb_decrypt(struct _des3_ctx *ctx, const guchar data[], + size_t len, guchar output[], size_t *outlen) +{ + int offset = 0; + int i = 0; + int tmp; + guint8 buf[8] = {0,0,0,0,0,0,0,0}; + while (offset + 8 <= len) { + /* NOTE: Apply key in reverse */ + des_ecb_crypt(&ctx->key3, + data+offset, + output+offset, + 1); + des_ecb_crypt(&ctx->key2, + output+offset, + buf, + 0); + des_ecb_crypt(&ctx->key1, + buf, + output+offset, + 1); + offset+=8; + } + *outlen = len; + if (offset < len) { + *outlen += len - offset; + tmp = offset; + memset(buf, 0, 8); + while (tmp < len) { + buf[i++] = data[tmp]; + tmp++; + } + des_ecb_crypt(&ctx->key3, + buf, + output+offset, + 1); + des_ecb_crypt(&ctx->key2, + output+offset, + buf, + 0); + des_ecb_crypt(&ctx->key1, + buf, + output+offset, + 1); + } + return 0; +} + +static gint +des3_cbc_decrypt(struct _des3_ctx *ctx, const guchar data[], + size_t len, guchar output[], size_t *outlen) +{ + int offset = 0; + int i = 0; + int tmp; + guint8 buf[8] = {0,0,0,0,0,0,0,0}; + guint8 link[8]; + memcpy(link, ctx->iv, 8); + while (offset + 8 <= len) { + des_ecb_crypt(&ctx->key3, + data+offset, + output+offset, + 1); + des_ecb_crypt(&ctx->key2, + output+offset, + buf, + 0); + des_ecb_crypt(&ctx->key1, + buf, + output+offset, + 1); + for (i = 0; i < 8; i++) + output[offset + i] ^= link[i]; + memcpy(link, data + offset, 8); + offset+=8; + } + *outlen = len; + if(offset<len) { + *outlen += len - offset; + tmp = offset; + memset(buf, 0, 8); + i = 0; + while(tmp<len) { + buf[i++] = data[tmp]; + tmp++; + } + des_ecb_crypt(&ctx->key3, + buf, + output+offset, + 1); + des_ecb_crypt(&ctx->key2, + output+offset, + buf, + 0); + des_ecb_crypt(&ctx->key1, + buf, + output+offset, + 1); + for (i = 0; i < 8; i++) + output[offset + i] ^= link[i]; + } + return 0; +} + +static gint +des3_decrypt(PurpleCipherContext *context, const guchar data[], + size_t len, guchar output[], size_t *outlen) +{ + struct _des3_ctx *ctx = purple_cipher_context_get_data(context); + + if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_ECB) { + return des3_ecb_decrypt(ctx, data, len, output, outlen); + } else if (ctx->mode == PURPLE_CIPHER_BATCH_MODE_CBC) { + return des3_cbc_decrypt(ctx, data, len, output, outlen); + } else { + g_return_val_if_reached(0); + } + + return 0; +} + +static void +des3_set_batch(PurpleCipherContext *context, PurpleCipherBatchMode mode) +{ + struct _des3_ctx *ctx = purple_cipher_context_get_data(context); + + ctx->mode = mode; +} + +static PurpleCipherBatchMode +des3_get_batch(PurpleCipherContext *context) +{ + struct _des3_ctx *ctx = purple_cipher_context_get_data(context); + + return ctx->mode; +} + +static void +des3_set_iv(PurpleCipherContext *context, guchar *iv, size_t len) +{ + struct _des3_ctx *ctx; + + g_return_if_fail(len == 8); + + ctx = purple_cipher_context_get_data(context); + + memcpy(ctx->iv, iv, len); +} + +static void +des3_init(PurpleCipherContext *context, gpointer extra) +{ + struct _des3_ctx *mctx; + mctx = g_new0(struct _des3_ctx, 1); + purple_cipher_context_set_data(context, mctx); +} + +static void +des3_uninit(PurpleCipherContext *context) +{ + struct _des3_ctx *des3_context; + + des3_context = purple_cipher_context_get_data(context); + memset(des3_context, 0, sizeof(des3_context)); + + g_free(des3_context); + des3_context = NULL; +} + +static PurpleCipherOps DES3Ops = { + NULL, /* Set option */ + NULL, /* Get option */ + des3_init, /* init */ + NULL, /* reset */ + des3_uninit, /* uninit */ + des3_set_iv, /* set iv */ + NULL, /* append */ + NULL, /* digest */ + des3_encrypt, /* encrypt */ + des3_decrypt, /* decrypt */ + NULL, /* set salt */ + NULL, /* get salt size */ + des3_set_key, /* set key */ + NULL, /* get key size */ + des3_set_batch, /* set batch mode */ + des3_get_batch, /* get batch mode */ + + /* padding */ NULL, NULL }; - /******************************************************************************* * SHA-1 ******************************************************************************/ @@ -1266,11 +1647,11 @@ NULL, /* get salt size */ NULL, /* set key */ NULL, /* get key size */ + NULL, /* set batch mode */ + NULL, /* get batch mode */ /* padding */ NULL, - NULL, - NULL, NULL }; @@ -1435,11 +1816,11 @@ NULL, /* get salt size */ rc4_set_key, /* set key */ rc4_get_key_size, /* get key size */ + NULL, /* set batch mode */ + NULL, /* get batch mode */ /* padding */ NULL, - NULL, - NULL, NULL }; @@ -1510,6 +1891,10 @@ caps |= PURPLE_CIPHER_CAPS_SET_KEY; if(ops->get_key_size) caps |= PURPLE_CIPHER_CAPS_GET_KEY_SIZE; + if(ops->set_batch_mode) + caps |= PURPLE_CIPHER_CAPS_SET_BATCH_MODE; + if(ops->get_batch_mode) + caps |= PURPLE_CIPHER_CAPS_GET_BATCH_MODE; return caps; } @@ -1637,6 +2022,7 @@ purple_ciphers_register_cipher("sha1", &SHA1Ops); purple_ciphers_register_cipher("md4", &MD4Ops); purple_ciphers_register_cipher("des", &DESOps); + purple_ciphers_register_cipher("des3", &DES3Ops); purple_ciphers_register_cipher("rc4", &RC4Ops); } @@ -1967,6 +2353,43 @@ } void +purple_cipher_context_set_batch_mode(PurpleCipherContext *context, + PurpleCipherBatchMode mode) +{ + PurpleCipher *cipher = NULL; + + g_return_if_fail(context); + + cipher = context->cipher; + g_return_if_fail(cipher); + + if(cipher->ops && cipher->ops->set_batch_mode) + cipher->ops->set_batch_mode(context, mode); + else + purple_debug_info("cipher", "The %s cipher does not support the " + "set_batch_mode operation\n", cipher->name); +} + +PurpleCipherBatchMode +purple_cipher_context_get_batch_mode(PurpleCipherContext *context) +{ + PurpleCipher *cipher = NULL; + + g_return_val_if_fail(context, -1); + + cipher = context->cipher; + g_return_val_if_fail(cipher, -1); + + if(cipher->ops && cipher->ops->get_batch_mode) + return cipher->ops->get_batch_mode(context); + else { + purple_debug_info("cipher", "The %s cipher does not support the " + "get_batch_mode operation\n", cipher->name); + return -1; + } +} + +void purple_cipher_context_set_data(PurpleCipherContext *context, gpointer data) { g_return_if_fail(context);
--- a/libpurple/cipher.h Wed Dec 19 15:54:54 2007 +0000 +++ b/libpurple/cipher.h Thu Dec 20 03:40:56 2007 +0000 @@ -37,26 +37,35 @@ typedef struct _PurpleCipherOps PurpleCipherOps; /**< Ops for a PurpleCipher */ typedef struct _PurpleCipherContext PurpleCipherContext; /**< A context for a PurpleCipher */ +/** + * Modes for batch encrypters + */ +typedef enum _PurpleCipherBatchMode { + PURPLE_CIPHER_BATCH_MODE_ECB, + PURPLE_CIPHER_BATCH_MODE_CBC +} PurpleCipherBatchMode; /** * The operation flags for a cipher */ typedef enum _PurpleCipherCaps { - PURPLE_CIPHER_CAPS_SET_OPT = 1 << 1, /**< Set option flag */ - PURPLE_CIPHER_CAPS_GET_OPT = 1 << 2, /**< Get option flag */ - PURPLE_CIPHER_CAPS_INIT = 1 << 3, /**< Init flag */ - PURPLE_CIPHER_CAPS_RESET = 1 << 4, /**< Reset flag */ - PURPLE_CIPHER_CAPS_UNINIT = 1 << 5, /**< Uninit flag */ - PURPLE_CIPHER_CAPS_SET_IV = 1 << 6, /**< Set IV flag */ - PURPLE_CIPHER_CAPS_APPEND = 1 << 7, /**< Append flag */ - PURPLE_CIPHER_CAPS_DIGEST = 1 << 8, /**< Digest flag */ - PURPLE_CIPHER_CAPS_ENCRYPT = 1 << 9, /**< Encrypt flag */ - PURPLE_CIPHER_CAPS_DECRYPT = 1 << 10, /**< Decrypt flag */ - PURPLE_CIPHER_CAPS_SET_SALT = 1 << 11, /**< Set salt flag */ - PURPLE_CIPHER_CAPS_GET_SALT_SIZE = 1 << 12, /**< Get salt size flag */ - PURPLE_CIPHER_CAPS_SET_KEY = 1 << 13, /**< Set key flag */ - PURPLE_CIPHER_CAPS_GET_KEY_SIZE = 1 << 14, /**< Get key size flag */ - PURPLE_CIPHER_CAPS_UNKNOWN = 1 << 16 /**< Unknown */ + PURPLE_CIPHER_CAPS_SET_OPT = 1 << 1, /**< Set option flag */ + PURPLE_CIPHER_CAPS_GET_OPT = 1 << 2, /**< Get option flag */ + PURPLE_CIPHER_CAPS_INIT = 1 << 3, /**< Init flag */ + PURPLE_CIPHER_CAPS_RESET = 1 << 4, /**< Reset flag */ + PURPLE_CIPHER_CAPS_UNINIT = 1 << 5, /**< Uninit flag */ + PURPLE_CIPHER_CAPS_SET_IV = 1 << 6, /**< Set IV flag */ + PURPLE_CIPHER_CAPS_APPEND = 1 << 7, /**< Append flag */ + PURPLE_CIPHER_CAPS_DIGEST = 1 << 8, /**< Digest flag */ + PURPLE_CIPHER_CAPS_ENCRYPT = 1 << 9, /**< Encrypt flag */ + PURPLE_CIPHER_CAPS_DECRYPT = 1 << 10, /**< Decrypt flag */ + PURPLE_CIPHER_CAPS_SET_SALT = 1 << 11, /**< Set salt flag */ + PURPLE_CIPHER_CAPS_GET_SALT_SIZE = 1 << 12, /**< Get salt size flag */ + PURPLE_CIPHER_CAPS_SET_KEY = 1 << 13, /**< Set key flag */ + PURPLE_CIPHER_CAPS_GET_KEY_SIZE = 1 << 14, /**< Get key size flag */ + PURPLE_CIPHER_CAPS_SET_BATCH_MODE = 1 << 15, /**< Set batch mode flag */ + PURPLE_CIPHER_CAPS_GET_BATCH_MODE = 1 << 16, /**< Get batch mode flag */ + PURPLE_CIPHER_CAPS_UNKNOWN = 1 << 17 /**< Unknown */ } PurpleCipherCaps; /** @@ -105,10 +114,14 @@ /** The get key size function */ size_t (*get_key_size)(PurpleCipherContext *context); + /** The set batch mode function */ + void (*set_batch_mode)(PurpleCipherContext *context, PurpleCipherBatchMode mode); + + /** The get batch mode function */ + PurpleCipherBatchMode (*get_batch_mode)(PurpleCipherContext *context); + void (*_purple_reserved1)(void); void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); }; #ifdef __cplusplus @@ -345,7 +358,7 @@ /** * Sets the salt on a context * - * @param context The context who's salt to set + * @param context The context whose salt to set * @param salt The salt */ void purple_cipher_context_set_salt(PurpleCipherContext *context, guchar *salt); @@ -353,7 +366,7 @@ /** * Gets the size of the salt if the cipher supports it * - * @param context The context who's salt size to get + * @param context The context whose salt size to get * * @return The size of the salt */ @@ -362,7 +375,7 @@ /** * Sets the key on a context * - * @param context The context who's key to set + * @param context The context whose key to set * @param key The key */ void purple_cipher_context_set_key(PurpleCipherContext *context, const guchar *key); @@ -370,16 +383,34 @@ /** * Gets the key size for a context * - * @param context The context who's key size to get + * @param context The context whose key size to get * * @return The size of the key */ size_t purple_cipher_context_get_key_size(PurpleCipherContext *context); /** + * Sets the batch mode of a context + * + * @param context The context whose batch mode to set + * @param mode The batch mode under which the cipher should operate + * + */ +void purple_cipher_context_set_batch_mode(PurpleCipherContext *context, PurpleCipherBatchMode mode); + +/** + * Gets the batch mode of a context + * + * @param context The context whose batch mode to get + * + * @return The batch mode under which the cipher is operating + */ +PurpleCipherBatchMode purple_cipher_context_get_batch_mode(PurpleCipherContext *context); + +/** * Sets the cipher data for a context * - * @param context The context who's cipher data to set + * @param context The context whose cipher data to set * @param data The cipher data to set */ void purple_cipher_context_set_data(PurpleCipherContext *context, gpointer data); @@ -387,7 +418,7 @@ /** * Gets the cipher data for a context * - * @param context The context who's cipher data to get + * @param context The context whose cipher data to get * * @return The cipher data */
--- a/libpurple/tests/test_cipher.c Wed Dec 19 15:54:54 2007 +0000 +++ b/libpurple/tests/test_cipher.c Thu Dec 20 03:40:56 2007 +0000 @@ -190,6 +190,224 @@ END_TEST /****************************************************************************** + * DES Tests + *****************************************************************************/ +#define DES_TEST(in, keyz, out, len) { \ + PurpleCipher *cipher = NULL; \ + PurpleCipherContext *context = NULL; \ + guchar answer[len+1]; \ + gint ret = 0; \ + guchar decrypt[len+1] = in; \ + guchar key[8+1] = keyz;\ + guchar encrypt[len+1] = out;\ + size_t outlen; \ + \ + cipher = purple_ciphers_find_cipher("des"); \ + context = purple_cipher_context_new(cipher, NULL); \ + purple_cipher_context_set_key(context, key); \ + \ + ret = purple_cipher_context_encrypt(context, decrypt, len, answer, &outlen); \ + fail_unless(ret == 0, NULL); \ + fail_unless(outlen == (len), NULL); \ + fail_unless(memcmp(encrypt, answer, len) == 0, NULL); \ + \ + ret = purple_cipher_context_decrypt(context, encrypt, len, answer, &outlen); \ + fail_unless(ret == 0, NULL); \ + fail_unless(outlen == (len), NULL); \ + fail_unless(memcmp(decrypt, answer, len) == 0, NULL); \ + \ + purple_cipher_context_destroy(context); \ +} + +START_TEST(test_des_12345678) { + DES_TEST("12345678", + "\x3b\x38\x98\x37\x15\x20\xf7\x5e", + "\x06\x22\x05\xac\x6a\x0d\x55\xdd", + 8); +} +END_TEST + +START_TEST(test_des_abcdefgh) { + DES_TEST("abcdefgh", + "\x3b\x38\x98\x37\x15\x20\xf7\x5e", + "\x62\xe0\xc6\x8c\x48\xe4\x75\xed", + 8); +} +END_TEST + +/****************************************************************************** + * DES3 Tests + * See http://csrc.nist.gov/groups/ST/toolkit/examples.html + * and some NULL things I made up + *****************************************************************************/ + +#define DES3_TEST(in, key, iv, out, len, mode) { \ + PurpleCipher *cipher = NULL; \ + PurpleCipherContext *context = NULL; \ + guchar answer[len+1]; \ + guchar decrypt[len+1] = in; \ + guchar encrypt[len+1] = out; \ + size_t outlen; \ + gint ret = 0; \ + \ + cipher = purple_ciphers_find_cipher("des3"); \ + context = purple_cipher_context_new(cipher, NULL); \ + purple_cipher_context_set_key(context, (guchar *)key); \ + purple_cipher_context_set_batch_mode(context, (mode)); \ + purple_cipher_context_set_iv(context, (guchar *)iv, 8); \ + \ + ret = purple_cipher_context_encrypt(context, decrypt, len, answer, &outlen); \ + fail_unless(ret == 0, NULL); \ + fail_unless(outlen == (len), NULL); \ + fail_unless(memcmp(encrypt, answer, len) == 0, NULL); \ + \ + ret = purple_cipher_context_decrypt(context, encrypt, len, answer, &outlen); \ + fail_unless(ret == 0, NULL); \ + fail_unless(outlen == (len), NULL); \ + fail_unless(memcmp(decrypt, answer, len) == 0, NULL); \ + \ + purple_cipher_context_destroy(context); \ +} + +START_TEST(test_des3_ecb_nist1) { + DES3_TEST( + "\x6B\xC1\xBE\xE2\x2E\x40\x9F\x96\xE9\x3D\x7E\x11\x73\x93\x17\x2A" + "\xAE\x2D\x8A\x57\x1E\x03\xAC\x9C\x9E\xB7\x6F\xAC\x45\xAF\x8E\x51", + "\x01\x23\x45\x67\x89\xAB\xCD\xEF" + "\x23\x45\x67\x89\xAB\xCD\xEF\x01" + "\x45\x67\x89\xAB\xCD\xEF\x01\x23", + "00000000", /* ignored */ + "\x71\x47\x72\xF3\x39\x84\x1D\x34\x26\x7F\xCC\x4B\xD2\x94\x9C\xC3" + "\xEE\x11\xC2\x2A\x57\x6A\x30\x38\x76\x18\x3F\x99\xC0\xB6\xDE\x87", + 32, + PURPLE_CIPHER_BATCH_MODE_ECB); +} +END_TEST + +START_TEST(test_des3_ecb_nist2) { + DES3_TEST( + "\x6B\xC1\xBE\xE2\x2E\x40\x9F\x96\xE9\x3D\x7E\x11\x73\x93\x17\x2A" + "\xAE\x2D\x8A\x57\x1E\x03\xAC\x9C\x9E\xB7\x6F\xAC\x45\xAF\x8E\x51", + "\x01\x23\x45\x67\x89\xAB\xCD\xEF" + "\x23\x45\x67\x89\xAB\xCD\xEF\x01" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF", + "00000000", /* ignored */ + "\x06\xED\xE3\xD8\x28\x84\x09\x0A\xFF\x32\x2C\x19\xF0\x51\x84\x86" + "\x73\x05\x76\x97\x2A\x66\x6E\x58\xB6\xC8\x8C\xF1\x07\x34\x0D\x3D", + 32, + PURPLE_CIPHER_BATCH_MODE_ECB); +} +END_TEST + +START_TEST(test_des3_ecb_null_key) { + DES3_TEST( + "\x16\xf4\xb3\x77\xfd\x4b\x9e\xca", + "\x38\x00\x88\x6a\xef\xcb\x00\xad" + "\x5d\xe5\x29\x00\x7d\x98\x64\x4c" + "\x86\x00\x7b\xd3\xc7\x00\x7b\x32", + "00000000", /* ignored */ + "\xc0\x60\x30\xa1\xb7\x25\x42\x44", + 8, + PURPLE_CIPHER_BATCH_MODE_ECB); +} +END_TEST + +START_TEST(test_des3_ecb_null_text) { + DES3_TEST( + "\x65\x73\x34\xc1\x19\x00\x79\x65", + "\x32\x64\xda\x10\x13\x6a\xfe\x1e" + "\x37\x54\xd1\x2c\x41\x04\x10\x40" + "\xaf\x1c\x75\x2b\x51\x3a\x03\xf5", + "00000000", /* ignored */ + "\xe5\x80\xf6\x12\xf8\x4e\xd9\x6c", + 8, + PURPLE_CIPHER_BATCH_MODE_ECB); +} +END_TEST + +START_TEST(test_des3_ecb_null_key_and_text) { + DES3_TEST( + "\xdf\x7f\x00\x92\xe7\xc1\x49\xd2", + "\x0e\x41\x00\xc4\x8b\xf0\x6e\xa1" + "\x66\x49\x42\x63\x22\x00\xf0\x99" + "\x6b\x22\xc1\x37\x9c\x00\xe4\x8f", + "00000000", /* ignored */ + "\x73\xd8\x1f\x1f\x50\x01\xe4\x79", + 8, + PURPLE_CIPHER_BATCH_MODE_ECB); +} +END_TEST + +START_TEST(test_des3_cbc_nist1) { + DES3_TEST( + "\x6B\xC1\xBE\xE2\x2E\x40\x9F\x96\xE9\x3D\x7E\x11\x73\x93\x17\x2A" + "\xAE\x2D\x8A\x57\x1E\x03\xAC\x9C\x9E\xB7\x6F\xAC\x45\xAF\x8E\x51", + "\x01\x23\x45\x67\x89\xAB\xCD\xEF" + "\x23\x45\x67\x89\xAB\xCD\xEF\x01" + "\x45\x67\x89\xAB\xCD\xEF\x01\x23", + "\xF6\x9F\x24\x45\xDF\x4F\x9B\x17", + "\x20\x79\xC3\xD5\x3A\xA7\x63\xE1\x93\xB7\x9E\x25\x69\xAB\x52\x62" + "\x51\x65\x70\x48\x1F\x25\xB5\x0F\x73\xC0\xBD\xA8\x5C\x8E\x0D\xA7", + 32, + PURPLE_CIPHER_BATCH_MODE_CBC); +} +END_TEST + +START_TEST(test_des3_cbc_nist2) { + DES3_TEST( + "\x6B\xC1\xBE\xE2\x2E\x40\x9F\x96\xE9\x3D\x7E\x11\x73\x93\x17\x2A" + "\xAE\x2D\x8A\x57\x1E\x03\xAC\x9C\x9E\xB7\x6F\xAC\x45\xAF\x8E\x51", + "\x01\x23\x45\x67\x89\xAB\xCD\xEF" + "\x23\x45\x67\x89\xAB\xCD\xEF\x01" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF", + "\xF6\x9F\x24\x45\xDF\x4F\x9B\x17", + "\x74\x01\xCE\x1E\xAB\x6D\x00\x3C\xAF\xF8\x4B\xF4\x7B\x36\xCC\x21" + "\x54\xF0\x23\x8F\x9F\xFE\xCD\x8F\x6A\xCF\x11\x83\x92\xB4\x55\x81", + 32, + PURPLE_CIPHER_BATCH_MODE_CBC); +} +END_TEST + +START_TEST(test_des3_cbc_null_key) { + DES3_TEST( + "\x16\xf4\xb3\x77\xfd\x4b\x9e\xca", + "\x38\x00\x88\x6a\xef\xcb\x00\xad" + "\x5d\xe5\x29\x00\x7d\x98\x64\x4c" + "\x86\x00\x7b\xd3\xc7\x00\x7b\x32", + "\x31\x32\x33\x34\x35\x36\x37\x38", + "\x52\xe7\xde\x96\x39\x87\x87\xdb", + 8, + PURPLE_CIPHER_BATCH_MODE_CBC); +} +END_TEST + +START_TEST(test_des3_cbc_null_text) { + DES3_TEST( + "\x65\x73\x34\xc1\x19\x00\x79\x65", + "\x32\x64\xda\x10\x13\x6a\xfe\x1e" + "\x37\x54\xd1\x2c\x41\x04\x10\x40" + "\xaf\x1c\x75\x2b\x51\x3a\x03\xf5", + "\x7C\xAF\x0D\x57\x1E\x57\x10\xDA", + "\x40\x12\x0e\x00\x85\xff\x6c\xc2", + 8, + PURPLE_CIPHER_BATCH_MODE_CBC); +} +END_TEST + +START_TEST(test_des3_cbc_null_key_and_text) { + DES3_TEST( + "\xdf\x7f\x00\x92\xe7\xc1\x49\xd2", + "\x0e\x41\x00\xc4\x8b\xf0\x6e\xa1" + "\x66\x49\x42\x63\x22\x00\xf0\x99" + "\x6b\x22\xc1\x37\x9c\x00\xe4\x8f", + "\x01\x19\x0D\x2c\x40\x67\x89\x67", + "\xa7\xc1\x10\xbe\x9b\xd5\x8a\x67", + 8, + PURPLE_CIPHER_BATCH_MODE_CBC); +} +END_TEST + +/****************************************************************************** * Suite *****************************************************************************/ Suite * @@ -227,6 +445,29 @@ tcase_add_test(tc, test_sha1_1000_as_1000_times); suite_add_tcase(s, tc); + /* des tests */ + tc = tcase_create("DES"); + tcase_add_test(tc, test_des_12345678); + tcase_add_test(tc, test_des_abcdefgh); + suite_add_tcase(s, tc); + + /* des3 ecb tests */ + tc = tcase_create("DES3 ECB"); + tcase_add_test(tc, test_des3_ecb_nist1); + tcase_add_test(tc, test_des3_ecb_nist2); + tcase_add_test(tc, test_des3_ecb_null_key); + tcase_add_test(tc, test_des3_ecb_null_text); + tcase_add_test(tc, test_des3_ecb_null_key_and_text); + suite_add_tcase(s, tc); + /* des3 cbc tests */ + tc = tcase_create("DES3 CBC"); + tcase_add_test(tc, test_des3_cbc_nist1); + tcase_add_test(tc, test_des3_cbc_nist2); + tcase_add_test(tc, test_des3_cbc_null_key); + tcase_add_test(tc, test_des3_cbc_null_text); + tcase_add_test(tc, test_des3_cbc_null_key_and_text); + suite_add_tcase(s, tc); + return s; }