im.pidgin.pidgin: 6e4b6167ad006d6cf4c643ae912ae9f9488784de
quantum.analyst at gmail.com
quantum.analyst at gmail.com
Wed Dec 19 23:00:52 EST 2007
-----------------------------------------------------------------
Revision: 6e4b6167ad006d6cf4c643ae912ae9f9488784de
Ancestor: 0db720d53baa44f5f1e82557a4953940ca8f52c8
Author: quantum.analyst at gmail.com
Date: 2007-12-20T03:40:56
Branch: im.pidgin.pidgin
Modified files:
libpurple/cipher.c libpurple/cipher.h
libpurple/tests/test_cipher.c
ChangeLog:
Triple DES cipher support from Elliott Sales de Andrade
-------------- next part --------------
============================================================
--- libpurple/cipher.c 6c67b38d1ceeb53ffc244d2bed4048f82c047bc4
+++ libpurple/cipher.c 486f42416341df92d4bb136cec3f65e82dd2687e
@@ -340,11 +340,11 @@ static PurpleCipherOps MD5Ops = {
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 @@ static PurpleCipherOps MD4Ops = {
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 @@ des_encrypt(PurpleCipherContext *context
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 = {
}
static PurpleCipherOps DESOps = {
- NULL, /* Set option */
- NULL, /* Get option */
- des_init, /* init */
+ 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
+};
+
+/******************************************************************************
+ * 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 */
- 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 */
+ 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,
- NULL,
NULL
};
-
/*******************************************************************************
* SHA-1
******************************************************************************/
@@ -1266,11 +1647,11 @@ static PurpleCipherOps SHA1Ops = {
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 @@ static PurpleCipherOps RC4Ops = {
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 @@ purple_cipher_get_capabilities(PurpleCip
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_init() {
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
}
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);
============================================================
--- libpurple/cipher.h 094bcb2f742e04e09e5025ef2cd14ce960dc0694
+++ libpurple/cipher.h 5aba8da46a9696c7c6b5ce0e9146cd76adc99204
@@ -37,26 +37,35 @@ typedef struct _PurpleCipherContext Purp
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 @@ struct _PurpleCipherOps {
/** 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 @@ gint purple_cipher_context_decrypt(Purpl
/**
* 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 @@ void purple_cipher_context_set_salt(Purp
/**
* 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 @@ size_t purple_cipher_context_get_salt_si
/**
* 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 @@ void purple_cipher_context_set_key(Purpl
/**
* 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 @@ void purple_cipher_context_set_data(Purp
/**
* 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
*/
============================================================
--- libpurple/tests/test_cipher.c b5796e5699d8d7a6c2320513435b00fd15d04782
+++ libpurple/tests/test_cipher.c 3fea5ff141fef6f0e67bb87367424887b930323c
@@ -190,6 +190,224 @@ END_TEST
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 @@ cipher_suite(void) {
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;
}
More information about the Commits
mailing list