Mercurial > pidgin
changeset 21908:f786e478e08b
HMAC digest 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:44:01 +0000 |
parents | 03463c52b9d7 |
children | 6648cfa72842 |
files | libpurple/cipher.c libpurple/cipher.h libpurple/tests/test_cipher.c |
diffstat | 3 files changed, 608 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- a/libpurple/cipher.c Thu Dec 20 03:40:56 2007 +0000 +++ b/libpurple/cipher.c Thu Dec 20 03:44:01 2007 +0000 @@ -64,6 +64,8 @@ /******************************************************************************* * MD5 ******************************************************************************/ +#define MD5_HMAC_BLOCK_SIZE 64 + struct MD5Context { guint32 total[2]; guint32 state[4]; @@ -325,6 +327,13 @@ return TRUE; } +static size_t +md5_get_block_size(PurpleCipherContext *context) +{ + /* This does not change (in this case) */ + return MD5_HMAC_BLOCK_SIZE; +} + static PurpleCipherOps MD5Ops = { NULL, /* Set option */ NULL, /* Get option */ @@ -342,10 +351,8 @@ NULL, /* get key size */ NULL, /* set batch mode */ NULL, /* get batch mode */ - - /* padding */ - NULL, - NULL + md5_get_block_size, /* get block size */ + NULL /* set key with len */ }; /******************************************************************************* @@ -580,6 +587,13 @@ md4_context = NULL; } +static size_t +md4_get_block_size(PurpleCipherContext *context) +{ + /* This does not change (in this case) */ + return MD4_HMAC_BLOCK_SIZE; +} + static PurpleCipherOps MD4Ops = { NULL, /* Set option */ NULL, /* Get option */ @@ -597,10 +611,200 @@ NULL, /* get key size */ NULL, /* set batch mode */ NULL, /* get batch mode */ - - /* padding */ - NULL, - NULL + md4_get_block_size, /* get block size */ + NULL /* set key with len */ +}; + +/******************************************************************************* + * HMAC + ******************************************************************************/ + +struct HMAC_Context { + PurpleCipherContext *hash; + char *name; + int blocksize; + guchar *opad; +}; + +static void +hmac_init(PurpleCipherContext *context, gpointer extra) +{ + struct HMAC_Context *hctx; + hctx = g_new0(struct HMAC_Context, 1); + purple_cipher_context_set_data(context, hctx); + purple_cipher_context_reset(context, extra); +} + +static void +hmac_reset(PurpleCipherContext *context, gpointer extra) +{ + struct HMAC_Context *hctx; + + hctx = purple_cipher_context_get_data(context); + + g_free(hctx->name); + hctx->name = NULL; + if (hctx->hash) + purple_cipher_context_destroy(hctx->hash); + hctx->hash = NULL; + hctx->blocksize = 0; + g_free(hctx->opad); + hctx->opad = NULL; +} + +static void +hmac_set_opt(PurpleCipherContext *context, const gchar *name, void *value) +{ + struct HMAC_Context *hctx; + + hctx = purple_cipher_context_get_data(context); + + if (!strcmp(name, "hash")) { + g_free(hctx->name); + if (hctx->hash) + purple_cipher_context_destroy(hctx->hash); + hctx->name = g_strdup((char*)value); + hctx->hash = purple_cipher_context_new_by_name((char *)value, NULL); + hctx->blocksize = purple_cipher_context_get_block_size(hctx->hash); + } +} + +static void * +hmac_get_opt(PurpleCipherContext *context, const gchar *name) +{ + struct HMAC_Context *hctx; + + hctx = purple_cipher_context_get_data(context); + + if (!strcmp(name, "hash")) { + return hctx->name; + } + + return NULL; +} + +static void +hmac_append(PurpleCipherContext *context, const guchar *data, size_t len) +{ + struct HMAC_Context *hctx = purple_cipher_context_get_data(context); + + g_return_if_fail(hctx->hash != NULL); + + purple_cipher_context_append(hctx->hash, data, len); +} + +static gboolean +hmac_digest(PurpleCipherContext *context, size_t in_len, guchar *out, size_t *out_len) +{ + struct HMAC_Context *hctx = purple_cipher_context_get_data(context); + PurpleCipherContext *hash = hctx->hash; + guchar *inner_hash; + size_t hash_len; + gboolean result; + + g_return_val_if_fail(hash != NULL, FALSE); + + inner_hash = g_malloc(100); /* TODO: Should be enough for now... */ + result = purple_cipher_context_digest(hash, 100, inner_hash, &hash_len); + + purple_cipher_context_reset(hash, NULL); + + purple_cipher_context_append(hash, hctx->opad, hctx->blocksize); + purple_cipher_context_append(hash, inner_hash, hash_len); + + g_free(inner_hash); + + result = result && purple_cipher_context_digest(hash, in_len, out, out_len); + + return result; +} + +static void +hmac_uninit(PurpleCipherContext *context) +{ + struct HMAC_Context *hctx; + + purple_cipher_context_reset(context, NULL); + + hctx = purple_cipher_context_get_data(context); + + g_free(hctx); +} + +static void +hmac_set_key_with_len(PurpleCipherContext *context, const guchar * key, size_t key_len) +{ + struct HMAC_Context *hctx = purple_cipher_context_get_data(context); + int blocksize, i; + guchar *ipad; + guchar *full_key; + + g_return_if_fail(hctx->hash != NULL); + + g_free(hctx->opad); + + blocksize = hctx->blocksize; + ipad = g_malloc(blocksize); + hctx->opad = g_malloc(blocksize); + + if (key_len > blocksize) { + purple_cipher_context_reset(hctx->hash, NULL); + purple_cipher_context_append(hctx->hash, key, key_len); + full_key = g_malloc(100); /* TODO: Should be enough for now... */ + purple_cipher_context_digest(hctx->hash, 100, full_key, &key_len); + } else + full_key = g_memdup(key, key_len); + + if (key_len < blocksize) { + full_key = g_realloc(full_key, blocksize); + memset(full_key + key_len, 0, blocksize - key_len); + } + + for(i = 0; i < blocksize; i++) { + ipad[i] = 0x36 ^ full_key[i]; + hctx->opad[i] = 0x5c ^ full_key[i]; + } + + g_free(full_key); + + purple_cipher_context_reset(hctx->hash, NULL); + purple_cipher_context_append(hctx->hash, ipad, blocksize); + g_free(ipad); +} + +static void +hmac_set_key(PurpleCipherContext *context, const guchar * key) +{ + hmac_set_key_with_len(context, key, strlen(key)); +} + +static size_t +hmac_get_block_size(PurpleCipherContext *context) +{ + struct HMAC_Context *hctx = purple_cipher_context_get_data(context); + + return hctx->blocksize; +} + +static PurpleCipherOps HMACOps = { + hmac_set_opt, /* Set option */ + hmac_get_opt, /* Get option */ + hmac_init, /* init */ + hmac_reset, /* reset */ + hmac_uninit, /* uninit */ + NULL, /* set iv */ + hmac_append, /* append */ + hmac_digest, /* digest */ + NULL, /* encrypt */ + NULL, /* decrypt */ + NULL, /* set salt */ + NULL, /* get salt size */ + hmac_set_key, /* set key */ + NULL, /* get key size */ + NULL, /* set batch mode */ + NULL, /* get batch mode */ + hmac_get_block_size, /* get block size */ + hmac_set_key_with_len /* set key with len */ }; /****************************************************************************** @@ -1051,10 +1255,8 @@ NULL, /* get key size */ NULL, /* set batch mode */ NULL, /* get batch mode */ - - /* padding */ - NULL, - NULL + NULL, /* get block size */ + NULL /* set key with len */ }; /****************************************************************************** @@ -1403,15 +1605,14 @@ NULL, /* get key size */ des3_set_batch, /* set batch mode */ des3_get_batch, /* get batch mode */ - - /* padding */ - NULL, - NULL + NULL, /* get block size */ + NULL /* set key with len */ }; /******************************************************************************* * SHA-1 ******************************************************************************/ +#define SHA1_HMAC_BLOCK_SIZE 64 #define SHA1_ROTL(X,n) ((((X) << (n)) | ((X) >> (32-(n)))) & 0xFFFFFFFF) struct SHA1Context { @@ -1632,6 +1833,13 @@ return TRUE; } +static size_t +sha1_get_block_size(PurpleCipherContext *context) +{ + /* This does not change (in this case) */ + return SHA1_HMAC_BLOCK_SIZE; +} + static PurpleCipherOps SHA1Ops = { sha1_set_opt, /* Set Option */ sha1_get_opt, /* Get Option */ @@ -1649,10 +1857,8 @@ NULL, /* get key size */ NULL, /* set batch mode */ NULL, /* get batch mode */ - - /* padding */ - NULL, - NULL + sha1_get_block_size, /* get block size */ + NULL /* set key with len */ }; /******************************************************************************* @@ -1818,10 +2024,8 @@ rc4_get_key_size, /* get key size */ NULL, /* set batch mode */ NULL, /* get batch mode */ - - /* padding */ - NULL, - NULL + NULL, /* get block size */ + NULL /* set key with len */ }; /******************************************************************************* @@ -1895,6 +2099,10 @@ caps |= PURPLE_CIPHER_CAPS_SET_BATCH_MODE; if(ops->get_batch_mode) caps |= PURPLE_CIPHER_CAPS_GET_BATCH_MODE; + if(ops->get_block_size) + caps |= PURPLE_CIPHER_CAPS_GET_BLOCK_SIZE; + if(ops->set_key_with_len) + caps |= PURPLE_CIPHER_CAPS_SET_KEY_WITH_LEN; return caps; } @@ -2021,6 +2229,7 @@ purple_ciphers_register_cipher("md5", &MD5Ops); purple_ciphers_register_cipher("sha1", &SHA1Ops); purple_ciphers_register_cipher("md4", &MD4Ops); + purple_ciphers_register_cipher("hmac", &HMACOps); purple_ciphers_register_cipher("des", &DESOps); purple_ciphers_register_cipher("des3", &DES3Ops); purple_ciphers_register_cipher("rc4", &RC4Ops); @@ -2389,6 +2598,43 @@ } } +size_t +purple_cipher_context_get_block_size(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_block_size) + return cipher->ops->get_block_size(context); + else { + purple_debug_info("cipher", "The %s cipher does not support the " + "get_block_size operation\n", cipher->name); + return -1; + } +} + +void +purple_cipher_context_set_key_with_len(PurpleCipherContext *context, + const guchar *key, size_t len) +{ + PurpleCipher *cipher = NULL; + + g_return_if_fail(context); + + cipher = context->cipher; + g_return_if_fail(cipher); + + if(cipher->ops && cipher->ops->set_key_with_len) + cipher->ops->set_key_with_len(context, key, len); + else + purple_debug_info("cipher", "The %s cipher does not support the " + "set_key_with_len operation\n", cipher->name); +} + void purple_cipher_context_set_data(PurpleCipherContext *context, gpointer data) { g_return_if_fail(context);
--- a/libpurple/cipher.h Thu Dec 20 03:40:56 2007 +0000 +++ b/libpurple/cipher.h Thu Dec 20 03:44:01 2007 +0000 @@ -65,7 +65,9 @@ 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 */ + PURPLE_CIPHER_CAPS_GET_BLOCK_SIZE = 1 << 17, /**< The get block size flag */ + PURPLE_CIPHER_CAPS_SET_KEY_WITH_LEN = 1 << 18, /**< The set key with length flag */ + PURPLE_CIPHER_CAPS_UNKNOWN = 1 << 19 /**< Unknown */ } PurpleCipherCaps; /** @@ -120,8 +122,11 @@ /** The get batch mode function */ PurpleCipherBatchMode (*get_batch_mode)(PurpleCipherContext *context); - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); + /** The get block size function */ + size_t (*get_block_size)(PurpleCipherContext *context); + + /** The set key with length function */ + void (*set_key_with_len)(PurpleCipherContext *context, const guchar *key, size_t len); }; #ifdef __cplusplus @@ -408,6 +413,25 @@ PurpleCipherBatchMode purple_cipher_context_get_batch_mode(PurpleCipherContext *context); /** + * Gets the block size of a context + * + * @param context The context whose block size to get + * + * @return The block size of the context + */ +size_t purple_cipher_context_get_block_size(PurpleCipherContext *context); + +/** + * Sets the key with a given length on a context + * + * @param context The context whose key to set + * @param key The key + * @param len The length of the key + * + */ +void purple_cipher_context_set_key_with_len(PurpleCipherContext *context, const guchar *key, size_t len); + +/** * Sets the cipher data for a context * * @param context The context whose cipher data to set
--- a/libpurple/tests/test_cipher.c Thu Dec 20 03:40:56 2007 +0000 +++ b/libpurple/tests/test_cipher.c Thu Dec 20 03:44:01 2007 +0000 @@ -408,6 +408,293 @@ END_TEST /****************************************************************************** + * HMAC Tests + * See RFC2202 and some other NULL tests I made up + *****************************************************************************/ + +#define HMAC_TEST(data, data_len, key, key_len, type, digest) { \ + PurpleCipher *cipher = NULL; \ + PurpleCipherContext *context = NULL; \ + gchar cdigest[41]; \ + gboolean ret = FALSE; \ + \ + cipher = purple_ciphers_find_cipher("hmac"); \ + context = purple_cipher_context_new(cipher, NULL); \ + purple_cipher_context_set_option(context, "hash", type); \ + purple_cipher_context_set_key_with_len(context, (guchar *)key, (key_len)); \ + \ + purple_cipher_context_append(context, (guchar *)(data), (data_len)); \ + ret = purple_cipher_context_digest_to_str(context, sizeof(cdigest), cdigest, \ + NULL); \ + \ + fail_unless(ret == TRUE, NULL); \ + fail_unless(strcmp((digest), cdigest) == 0, NULL); \ + \ + purple_cipher_context_destroy(context); \ +} + +/* HMAC MD5 */ + +START_TEST(test_hmac_md5_Hi) { + HMAC_TEST("Hi There", + 8, + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + 16, + "md5", + "9294727a3638bb1c13f48ef8158bfc9d"); +} +END_TEST + +START_TEST(test_hmac_md5_what) { + HMAC_TEST("what do ya want for nothing?", + 28, + "Jefe", + 4, + "md5", + "750c783e6ab0b503eaa86e310a5db738"); +} +END_TEST + +START_TEST(test_hmac_md5_dd) { + HMAC_TEST("\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", + 50, + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + 16, + "md5", + "56be34521d144c88dbb8c733f0e8b3f6"); +} +END_TEST + +START_TEST(test_hmac_md5_cd) { + HMAC_TEST("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", + 50, + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" + "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19", + 25, + "md5", + "697eaf0aca3a3aea3a75164746ffaa79"); +} +END_TEST + +START_TEST(test_hmac_md5_truncation) { + HMAC_TEST("Test With Truncation", + 20, + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", + 16, + "md5", + "56461ef2342edc00f9bab995690efd4c"); +} +END_TEST + +START_TEST(test_hmac_md5_large_key) { + HMAC_TEST("Test Using Larger Than Block-Size Key - Hash Key First", + 54, + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + 80, + "md5", + "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd"); +} +END_TEST + +START_TEST(test_hmac_md5_large_key_and_data) { + HMAC_TEST("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", + 73, + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + 80, + "md5", + "6f630fad67cda0ee1fb1f562db3aa53e"); +} +END_TEST + +START_TEST(test_hmac_md5_null_key) { + HMAC_TEST("Hi There", + 8, + "\x0a\x0b\x00\x0d\x0e\x0f\x1a\x2f\x0b\x0b" + "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b", + 20, + "md5", + "597bfd644b797a985561eeb03a169e59"); +} +END_TEST + +START_TEST(test_hmac_md5_null_text) { + HMAC_TEST("Hi\x00There", + 8, + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + 20, + "md5", + "70be8e1b7b50dfcc335d6cd7992c564f"); +} +END_TEST + +START_TEST(test_hmac_md5_null_key_and_text) { + HMAC_TEST("Hi\x00Th\x00re", + 8, + "\x0c\x0d\x00\x0f\x10\x1a\x3a\x3a\xe6\x34" + "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b", + 20, + "md5", + "b31bcbba35a33a067cbba9131cba4889"); +} +END_TEST + +/* HMAC SHA1 */ + +START_TEST(test_hmac_sha1_Hi) { + HMAC_TEST("Hi There", + 8, + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + 20, + "sha1", + "b617318655057264e28bc0b6fb378c8ef146be00"); +} +END_TEST + +START_TEST(test_hmac_sha1_what) { + HMAC_TEST("what do ya want for nothing?", + 28, + "Jefe", + 4, + "sha1", + "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79"); +} +END_TEST + +START_TEST(test_hmac_sha1_dd) { + HMAC_TEST("\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", + 50, + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + 20, + "sha1", + "125d7342b9ac11cd91a39af48aa17b4f63f175d3"); +} +END_TEST + +START_TEST(test_hmac_sha1_cd) { + HMAC_TEST("\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", + 50, + "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" + "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" + "\x15\x16\x17\x18\x19", + 25, + "sha1", + "4c9007f4026250c6bc8414f9bf50c86c2d7235da"); +} +END_TEST + +START_TEST(test_hmac_sha1_truncation) { + HMAC_TEST("Test With Truncation", + 20, + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", + 20, + "sha1", + "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04"); +} +END_TEST + +START_TEST(test_hmac_sha1_large_key) { + HMAC_TEST("Test Using Larger Than Block-Size Key - Hash Key First", + 54, + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + 80, + "sha1", + "aa4ae5e15272d00e95705637ce8a3b55ed402112"); +} +END_TEST + +START_TEST(test_hmac_sha1_large_key_and_data) { + HMAC_TEST("Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", + 73, + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", + 80, + "sha1", + "e8e99d0f45237d786d6bbaa7965c7808bbff1a91"); +} +END_TEST + +START_TEST(test_hmac_sha1_null_key) { + HMAC_TEST("Hi There", + 8, + "\x0a\x0b\x00\x0d\x0e\x0f\x1a\x2f\x0b\x0b" + "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b", + 20, + "sha1", + "eb62a2e0e33d300be669c52aab3f591bc960aac5"); +} +END_TEST + +START_TEST(test_hmac_sha1_null_text) { + HMAC_TEST("Hi\x00There", + 8, + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + 20, + "sha1", + "31ca58d849e971e418e3439de2c6f83144b6abb7"); +} +END_TEST + +START_TEST(test_hmac_sha1_null_key_and_text) { + HMAC_TEST("Hi\x00Th\x00re", + 8, + "\x0c\x0d\x00\x0f\x10\x1a\x3a\x3a\xe6\x34" + "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b", + 20, + "sha1", + "e6b8e2fede87aa09dcb13e554df1435e056eae36"); +} +END_TEST + +/****************************************************************************** * Suite *****************************************************************************/ Suite * @@ -468,6 +755,30 @@ tcase_add_test(tc, test_des3_cbc_null_key_and_text); suite_add_tcase(s, tc); + /* hmac tests */ + tc = tcase_create("HMAC"); + tcase_add_test(tc, test_hmac_md5_Hi); + tcase_add_test(tc, test_hmac_md5_what); + tcase_add_test(tc, test_hmac_md5_dd); + tcase_add_test(tc, test_hmac_md5_cd); + tcase_add_test(tc, test_hmac_md5_truncation); + tcase_add_test(tc, test_hmac_md5_large_key); + tcase_add_test(tc, test_hmac_md5_large_key_and_data); + tcase_add_test(tc, test_hmac_md5_null_key); + tcase_add_test(tc, test_hmac_md5_null_text); + tcase_add_test(tc, test_hmac_md5_null_key_and_text); + tcase_add_test(tc, test_hmac_sha1_Hi); + tcase_add_test(tc, test_hmac_sha1_what); + tcase_add_test(tc, test_hmac_sha1_dd); + tcase_add_test(tc, test_hmac_sha1_cd); + tcase_add_test(tc, test_hmac_sha1_truncation); + tcase_add_test(tc, test_hmac_sha1_large_key); + tcase_add_test(tc, test_hmac_sha1_large_key_and_data); + tcase_add_test(tc, test_hmac_sha1_null_key); + tcase_add_test(tc, test_hmac_sha1_null_text); + tcase_add_test(tc, test_hmac_sha1_null_key_and_text); + suite_add_tcase(s, tc); + return s; }