From 42e69fbdadda32684495c7917ec5332e0aea859a Mon Sep 17 00:00:00 2001 From: Jan Hutter Date: Mon, 28 Nov 2005 12:42:43 +0000 Subject: [PATCH] - AUTH_HMAC_MD5_96 and AUTH_HMAC_SHA1_96 implemented and tested... --- Source/charon/testcases/Makefile.testcases | 4 + Source/charon/testcases/aes_cbc_crypter_test.c | 10 +- Source/charon/testcases/hmac_signer_test.c | 214 ++++++++++++++++++++++ Source/charon/testcases/hmac_signer_test.h | 42 +++++ Source/charon/testcases/testcases.c | 19 +- Source/charon/transforms/crypters/crypter.c | 2 + Source/charon/transforms/signers/Makefile.signers | 4 + Source/charon/transforms/signers/hmac_signer.c | 184 +++++++++++++++++++ Source/charon/transforms/signers/hmac_signer.h | 59 ++++++ Source/charon/transforms/signers/signer.c | 19 ++ 10 files changed, 548 insertions(+), 9 deletions(-) create mode 100644 Source/charon/testcases/hmac_signer_test.c create mode 100644 Source/charon/testcases/hmac_signer_test.h create mode 100644 Source/charon/transforms/signers/hmac_signer.c create mode 100644 Source/charon/transforms/signers/hmac_signer.h diff --git a/Source/charon/testcases/Makefile.testcases b/Source/charon/testcases/Makefile.testcases index a1087d4..bc1a537 100644 --- a/Source/charon/testcases/Makefile.testcases +++ b/Source/charon/testcases/Makefile.testcases @@ -59,6 +59,10 @@ $(BUILD_DIR)linked_list_test.o : $(TESTCASES_DIR)linked_list_test.c $(TESTCASES_ TEST_OBJS+= $(BUILD_DIR)hmac_test.o $(BUILD_DIR)hmac_test.o : $(TESTCASES_DIR)hmac_test.c $(TESTCASES_DIR)hmac_test.h $(CC) $(CFLAGS) -c -o $@ $< + +TEST_OBJS+= $(BUILD_DIR)hmac_signer_test.o +$(BUILD_DIR)hmac_signer_test.o : $(TESTCASES_DIR)hmac_signer_test.c $(TESTCASES_DIR)hmac_signer_test.h + $(CC) $(CFLAGS) -c -o $@ $< TEST_OBJS+= $(BUILD_DIR)scheduler_test.o $(BUILD_DIR)scheduler_test.o : $(TESTCASES_DIR)scheduler_test.c $(TESTCASES_DIR)scheduler_test.h diff --git a/Source/charon/testcases/aes_cbc_crypter_test.c b/Source/charon/testcases/aes_cbc_crypter_test.c index bbb8928..7b6e844 100644 --- a/Source/charon/testcases/aes_cbc_crypter_test.c +++ b/Source/charon/testcases/aes_cbc_crypter_test.c @@ -109,7 +109,8 @@ void test_aes_cbc_crypter(tester_t *tester) chunk_t data2 = {ptr: plaintext2, len : 32}; chunk_t encrypted2; chunk_t decrypted2; - + + crypter = (crypter_t *) aes_cbc_crypter_create(16); tester->assert_true(tester, (crypter != NULL), "create call test"); @@ -131,7 +132,8 @@ void test_aes_cbc_crypter(tester_t *tester) logger->log_chunk(logger,RAW,"decrypted :", &decrypted2); allocator_free_chunk(&decrypted2); - + + tester->assert_true(tester, (crypter->destroy(crypter) == SUCCESS), "destroy call test"); /* * Test 3 of RFC3603 @@ -173,7 +175,7 @@ void test_aes_cbc_crypter(tester_t *tester) chunk_t data3 = {ptr: plaintext3, len : 64}; chunk_t encrypted3; chunk_t decrypted3; - + crypter = (crypter_t *) aes_cbc_crypter_create(16); tester->assert_true(tester, (crypter != NULL), "create call test"); @@ -198,10 +200,8 @@ void test_aes_cbc_crypter(tester_t *tester) tester->assert_true(tester, (crypter->destroy(crypter) == SUCCESS), "destroy call test"); - - global_logger_manager->destroy_logger(global_logger_manager,logger); } diff --git a/Source/charon/testcases/hmac_signer_test.c b/Source/charon/testcases/hmac_signer_test.c new file mode 100644 index 0000000..f11107d --- /dev/null +++ b/Source/charon/testcases/hmac_signer_test.c @@ -0,0 +1,214 @@ +/** + * @file hmac_signer_test.c + * + * @brief Tests the hmac SHA1 and MD5 signer class hmac_signer_t + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + + +#include + +#include "hmac_signer_test.h" + +#include +#include +#include + + +/* + * Described in header. + */ +void test_hmac_md5_signer(tester_t *tester) +{ + /* Test cases from RFC2202 + * + * test_case = 5 + * key = 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c + * key_len = 16 + * data = "Test With Truncation" + * data_len = 20 + * digest = 0x56461ef2342edc00f9bab995690efd4c + * digest-96 0x56461ef2342edc00f9bab995 + * + * currently only this test 5 gets performed! + */ + chunk_t keys[4]; + chunk_t data[4]; + chunk_t signature[4]; + chunk_t reference[4]; + chunk_t wrong_reference[4]; + int i; + logger_t *logger; + bool valid; + + logger = global_logger_manager->create_logger(global_logger_manager,TESTER,"HMAC MD5 96"); + + signer_t *signer = (signer_t *) signer_create(AUTH_HMAC_MD5_96); + tester->assert_true(tester, (signer != NULL), "signer create call check"); + + + /* + * values for test 5 + */ + u_int8_t key1[] = { + 0x0c,0x0c,0x0c,0x0c, + 0x0c,0x0c,0x0c,0x0c, + 0x0c,0x0c,0x0c,0x0c, + 0x0c,0x0c,0x0c,0x0c, + }; + keys[0].ptr = key1; + keys[0].len = sizeof(key1); + data[0].ptr = "Test With Truncation"; + data[0].len = 20; + u_int8_t reference1[] = { + 0x56,0x46,0x1e,0xf2,0x34,0x2e, + 0xdc,0x00,0xf9,0xba,0xb9,0x95 + }; + reference[0].ptr = reference1; + reference[0].len = sizeof(reference1); + + u_int8_t wrong_reference1[] = { + 0x56,0x46,0x1e,0xa2,0x34,0x2e, + 0xdc,0x00,0xf9,0xba,0xb9,0x95 + }; + + wrong_reference[0].ptr = wrong_reference1; + wrong_reference[0].len = sizeof(wrong_reference1); + + for (i=0; i<1; i++) + { + signer->set_key(signer, keys[i]); + signer->allocate_signature(signer, data[i], &signature[i]); + tester->assert_true(tester, signature[i].len == 12, "chunk len"); + tester->assert_true(tester, (memcmp(signature[i].ptr, reference[i].ptr, 12) == 0), "hmac value"); + logger->log_chunk(logger,RAW,"expected signature:",&reference[i]); + logger->log_chunk(logger,RAW,"signature:",&signature[i]); + allocator_free(signature[i].ptr); + signer->verify_signature(signer, data[i],reference[i], &valid); + tester->assert_true(tester, (valid == TRUE), "Signature valid check"); + + signer->verify_signature(signer, data[i],wrong_reference[i], &valid); + tester->assert_true(tester, (valid == FALSE), "Signature not valid check"); + } + + + + tester->assert_true(tester, (signer->destroy(signer) == SUCCESS), "signer destroy call check"); + + global_logger_manager->destroy_logger(global_logger_manager,logger); +} + + +/* + * Described in header. + */ +void test_hmac_sha1_signer(tester_t *tester) +{ + /* + * test_case = 7 + * key = 0xaa repeated 80 times + * key_len = 80 + * data = "Test Using Larger Than Block-Size Key and Larger + * Than One Block-Size Data" + * data_len = 73 + * digest = 0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04 + * digest-96 = 0x4c1a03424b55e07fe7f27be1 + */ + + chunk_t keys[4]; + chunk_t data[4]; + chunk_t signature[4]; + chunk_t reference[4]; + chunk_t wrong_reference[4]; + int i; + logger_t *logger; + bool valid; + + logger = global_logger_manager->create_logger(global_logger_manager,TESTER,"HMAC SHA1 96"); + + signer_t *signer = (signer_t *) signer_create(AUTH_HMAC_SHA1_96); + tester->assert_true(tester, (signer != NULL), "signer create call check"); + + + /* + * values for test 5 + */ + u_int8_t key1[] = { + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + 0xaa,0xaa,0xaa,0xaa, + }; + keys[0].ptr = key1; + keys[0].len = sizeof(key1); + data[0].ptr = "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"; + data[0].len = 73; + u_int8_t reference1[] = { + 0xe8,0xe9,0x9d,0x0f,0x45,0x23, + 0x7d,0x78,0x6d,0x6b,0xba,0xa7 + }; + reference[0].ptr = reference1; + reference[0].len = sizeof(reference1); + + u_int8_t wrong_reference1[] = { + 0xe8,0xe9,0x9d,0x0f,0x46,0x23, + 0x7d,0x71,0x6d,0x6b,0xba,0xa7 + }; + + wrong_reference[0].ptr = wrong_reference1; + wrong_reference[0].len = sizeof(wrong_reference1); + + for (i=0; i<1; i++) + { + signer->set_key(signer, keys[i]); + signer->allocate_signature(signer, data[i], &signature[i]); + tester->assert_true(tester, signature[i].len == 12, "chunk len"); + tester->assert_true(tester, (memcmp(signature[i].ptr, reference[i].ptr, 12) == 0), "hmac value"); + logger->log_chunk(logger,RAW,"expected signature:",&reference[i]); + logger->log_chunk(logger,RAW,"signature:",&signature[i]); + allocator_free(signature[i].ptr); + signer->verify_signature(signer, data[i],reference[i], &valid); + tester->assert_true(tester, (valid == TRUE), "Signature valid check"); + + signer->verify_signature(signer, data[i],wrong_reference[i], &valid); + tester->assert_true(tester, (valid == FALSE), "Signature not valid check"); + } + + + + tester->assert_true(tester, (signer->destroy(signer) == SUCCESS), "signer destroy call check"); + + global_logger_manager->destroy_logger(global_logger_manager,logger); + +} diff --git a/Source/charon/testcases/hmac_signer_test.h b/Source/charon/testcases/hmac_signer_test.h new file mode 100644 index 0000000..cefb636 --- /dev/null +++ b/Source/charon/testcases/hmac_signer_test.h @@ -0,0 +1,42 @@ +/** + * @file hmac_signer_test.h + * + * @brief Tests the hmac SHA1 and MD5 signer class hmac_signer_t + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef _HMAC_SIGNER_TEST_H_ +#define _HMAC_SIGNER_TEST_H_ + +#include + +/** + * @brief Test function used to test the hmac sign functionality using MD5. + * + * @param tester associated tester object + */ +void test_hmac_md5_signer(tester_t *tester); + +/** + * @brief Test function used to test the hmac sign functionality using SHA1. + * + * @param tester associated tester object + */ +void test_hmac_sha1_signer(tester_t *tester); + +#endif //_HMAC_SIGNER_TEST_H_ diff --git a/Source/charon/testcases/testcases.c b/Source/charon/testcases/testcases.c index 3577f26..ac69b28 100644 --- a/Source/charon/testcases/testcases.c +++ b/Source/charon/testcases/testcases.c @@ -52,6 +52,7 @@ #include #include #include +#include /* output for test messages */ extern FILE * stderr; @@ -201,7 +202,15 @@ test_t prf_plus_test = {test_prf_plus, "prf+"}; */ test_t aes_cbc_crypter_test = {test_aes_cbc_crypter, "AES CBC"}; +/** + * Test for hmac signer with MD5 + */ +test_t hmac_signer_test1 = {test_hmac_md5_signer, "HMAC MD5 signer test"}; +/** + * Test for hmac signer with SHA1 + */ +test_t hmac_signer_test2 = {test_hmac_sha1_signer, "HMAC SHA1 signer test"}; /** @@ -280,9 +289,11 @@ logger_manager_t *global_logger_manager; &hmac_test2, &prf_plus_test, &aes_cbc_crypter_test, + &hmac_signer_test1, + &hmac_signer_test2, NULL }; - global_logger_manager = logger_manager_create(FULL); + global_logger_manager = logger_manager_create(0); global_socket = socket_create(4600); @@ -293,13 +304,13 @@ logger_manager_t *global_logger_manager; global_ike_sa_manager = ike_sa_manager_create(); global_logger_manager->disable_logger_level(global_logger_manager,TESTER,FULL); -// global_logger_manager->enable_logger_level(global_logger_manager,TESTER,RAW); + //global_logger_manager->enable_logger_level(global_logger_manager,TESTER,RAW); tester_t *tester = tester_create(test_output, FALSE); -// tester->perform_tests(tester,all_tests); - tester->perform_test(tester,&aes_cbc_crypter_test); + tester->perform_tests(tester,all_tests); +// tester->perform_test(tester,&hmac_signer_test2); diff --git a/Source/charon/transforms/crypters/crypter.c b/Source/charon/transforms/crypters/crypter.c index 79a02cf..8a9f590 100644 --- a/Source/charon/transforms/crypters/crypter.c +++ b/Source/charon/transforms/crypters/crypter.c @@ -23,6 +23,8 @@ #include "crypter.h" +#include + /** * string mappings for encryption_algorithm_t diff --git a/Source/charon/transforms/signers/Makefile.signers b/Source/charon/transforms/signers/Makefile.signers index 823f828..861125c 100644 --- a/Source/charon/transforms/signers/Makefile.signers +++ b/Source/charon/transforms/signers/Makefile.signers @@ -17,3 +17,7 @@ SIGNERS_DIR= $(TRANSFORMS_DIR)signers/ OBJS+= $(BUILD_DIR)signer.o $(BUILD_DIR)signer.o : $(SIGNERS_DIR)signer.c $(SIGNERS_DIR)signer.h $(CC) $(CFLAGS) -c -o $@ $< + +OBJS+= $(BUILD_DIR)hmac_signer.o +$(BUILD_DIR)hmac_signer.o : $(SIGNERS_DIR)hmac_signer.c $(SIGNERS_DIR)hmac_signer.h + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/Source/charon/transforms/signers/hmac_signer.c b/Source/charon/transforms/signers/hmac_signer.c new file mode 100644 index 0000000..caf2b9e --- /dev/null +++ b/Source/charon/transforms/signers/hmac_signer.c @@ -0,0 +1,184 @@ +/** + * @file hmac_signer.c + * + * @brief Implementation of hmac_signer_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "hmac_signer.h" + +#include +#include + +/** + * This class represents a hmac signer with 12 byte (96 bit) output + */ +#define BLOCK_SIZE 12 + +typedef struct private_hmac_signer_t private_hmac_signer_t; + +/** + * private data structure with signing context. + */ +struct private_hmac_signer_t { + /** + * Public interface for this signer. + */ + hmac_signer_t public; + + /* + * Assigned hmac function. + */ + prf_t *hmac_prf; +}; + + +static status_t get_signature (private_hmac_signer_t *this, chunk_t data, u_int8_t *buffer) +{ + u_int8_t full_mac[this->hmac_prf->get_block_size(this->hmac_prf)]; + status_t status; + + status = this->hmac_prf->get_bytes(this->hmac_prf,data,full_mac); + if (status != SUCCESS) + { + return status; + } + + /* copy mac aka signature :-) */ + memcpy(buffer,full_mac,BLOCK_SIZE); + + return SUCCESS; +} + +static status_t allocate_signature (private_hmac_signer_t *this, chunk_t data, chunk_t *chunk) +{ + chunk_t signature; + status_t status; + u_int8_t full_mac[this->hmac_prf->get_block_size(this->hmac_prf)]; + + status = this->hmac_prf->get_bytes(this->hmac_prf,data,full_mac); + if (status != SUCCESS) + { + return status; + } + + signature.ptr = allocator_alloc(BLOCK_SIZE); + if (signature.ptr == NULL) + { + return OUT_OF_RES; + } + signature.len = BLOCK_SIZE; + + /* copy mac aka signature :-) */ + memcpy(signature.ptr,full_mac,BLOCK_SIZE); + + *chunk = signature; + + return SUCCESS; + +} + +static status_t verify_signature (private_hmac_signer_t *this, chunk_t data, chunk_t signature, bool *valid) +{ + status_t status; + u_int8_t full_mac[this->hmac_prf->get_block_size(this->hmac_prf)]; + + status = this->hmac_prf->get_bytes(this->hmac_prf,data,full_mac); + if (status != SUCCESS) + { + return status; + } + + if (signature.len != BLOCK_SIZE) + { + /* signature must have BLOCK_SIZE length */ + return INVALID_ARG; + } + + /* compare mac aka signature :-) */ + if (memcmp(signature.ptr,full_mac,BLOCK_SIZE) == 0) + { + *valid = TRUE; + } + else + { + *valid = FALSE; + } + + return SUCCESS; +} + +static size_t get_block_size (private_hmac_signer_t *this) +{ + return BLOCK_SIZE; +} + +static status_t set_key (private_hmac_signer_t *this, chunk_t key) +{ + return (this->hmac_prf->set_key(this->hmac_prf,key)); +} + +/** + * implementation of signer_t.destroy. + */ +static status_t destroy(private_hmac_signer_t *this) +{ + this->hmac_prf->destroy(this->hmac_prf); + allocator_free(this); + return SUCCESS; +} + + +/* + * Described in header + */ +hmac_signer_t *hmac_signer_create(hash_algorithm_t hash_algoritm) +{ + private_hmac_signer_t *this = allocator_alloc_thing(private_hmac_signer_t); + if (this == NULL) + { + return NULL; + } + + this->hmac_prf = (prf_t *) prf_hmac_create(hash_algoritm); + + if (this->hmac_prf == NULL) + { + /* hmac prf could not be created !!! */ + allocator_free(this); + return NULL; + } + + if (this->hmac_prf->get_block_size(this->hmac_prf) < BLOCK_SIZE) + { + /* hmac prf with given algorithm has to small block size */ + allocator_free(this); + return NULL; + + } + + /* interface functions */ + this->public.signer_interface.get_signature = (status_t (*) (signer_t*, chunk_t, u_int8_t*))get_signature; + this->public.signer_interface.allocate_signature = (status_t (*) (signer_t*, chunk_t, chunk_t*))allocate_signature; + this->public.signer_interface.verify_signature = (status_t (*) (signer_t*, chunk_t, chunk_t,bool *))verify_signature; + this->public.signer_interface.get_block_size = (size_t (*) (signer_t*))get_block_size; + this->public.signer_interface.set_key = (size_t (*) (signer_t*,chunk_t))set_key; + this->public.signer_interface.destroy = (status_t (*) (signer_t*))destroy; + + return &(this->public); +} diff --git a/Source/charon/transforms/signers/hmac_signer.h b/Source/charon/transforms/signers/hmac_signer.h new file mode 100644 index 0000000..129a1ee --- /dev/null +++ b/Source/charon/transforms/signers/hmac_signer.h @@ -0,0 +1,59 @@ +/** + * @file hmac_signer.h + * + * @brief Interface of hmac_signer_t. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#ifndef _HMAC_SIGNER_H_ +#define _HMAC_SIGNER_H_ + +#include +#include + +typedef struct hmac_signer_t hmac_signer_t; + +/** + * @brief Implementation of hmac_signer_t interface using the + * HMAC algorithm in combination with eather MD5 or SHA1. + * + * @ingroup signers + */ +struct hmac_signer_t { + + /** + * generic signer_t interface for this signer + */ + signer_t signer_interface; +}; + +/** + * @brief Creates a new hmac_signer_t. + * + * @param hash_algorithm Hash algorithm to use with signer + * + * @return + * - hmac_signer_t if successfully + * - NULL if out of ressources + * + * @ingroup signers + */ +hmac_signer_t *hmac_signer_create(hash_algorithm_t hash_algoritm); + + +#endif //_HMAC_SIGNER_H_ diff --git a/Source/charon/transforms/signers/signer.c b/Source/charon/transforms/signers/signer.c index 3ecf580..98c639f 100644 --- a/Source/charon/transforms/signers/signer.c +++ b/Source/charon/transforms/signers/signer.c @@ -22,6 +22,7 @@ #include "signer.h" +#include /** * string mappings for integrity_algorithm_t @@ -35,3 +36,21 @@ mapping_t integrity_algorithm_m[] = { {AUTH_AES_XCBC_96, "AUTH_AES_XCBC_96"}, {MAPPING_END, NULL} }; + +signer_t *signer_create(integrity_algorithm_t integrity_algorithm) +{ + switch(integrity_algorithm) + { + case AUTH_HMAC_SHA1_96: + { + return ((signer_t *) hmac_signer_create(HASH_SHA1)); + } + case AUTH_HMAC_MD5_96: + { + return ((signer_t *) hmac_signer_create(HASH_MD5)); + } + + default: + return NULL; + } +} -- 2.7.4