From d9f9cb8ad5943ec7d16725e797f20cb410466c8d Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Mon, 21 Dec 2015 09:56:12 -0600 Subject: [PATCH 1/3] Add SHA3 and HMAC-SHA3 support --- client/config_init.c | 6 +- common/fko_util.c | 20 +++ lib/Makefile.am | 2 +- lib/digest.c | 35 +++++ lib/digest.h | 5 + lib/fko.h | 4 + lib/fko_digest.c | 20 +++ lib/fko_hmac.c | 20 +++ lib/hmac.c | 84 +++++++++++ lib/hmac.h | 6 +- lib/sha3.c | 334 +++++++++++++++++++++++++++++++++++++++++++ lib/sha3.h | 40 ++++++ server/access.c | 2 +- 13 files changed, 572 insertions(+), 6 deletions(-) create mode 100644 lib/sha3.c create mode 100644 lib/sha3.h diff --git a/client/config_init.c b/client/config_init.c index 62c71afb..b3dd6734 100644 --- a/client/config_init.c +++ b/client/config_init.c @@ -1120,7 +1120,7 @@ parse_rc_param(fko_cli_options_t *options, const char *var_name, char * val) if(tmpint < 0) { log_msg(LOG_VERBOSITY_WARNING, - "HMAC_DIGEST_TYPE argument '%s' must be one of {md5,sha1,sha256,sha384,sha512}", + "HMAC_DIGEST_TYPE argument '%s' must be one of {md5,sha1,sha256,sha384,sha512,sha3_256,sha3_512}", val); parse_error = -1; } @@ -2157,7 +2157,7 @@ config_init(fko_cli_options_t *options, int argc, char **argv) if((options->hmac_type = hmac_digest_strtoint(optarg)) < 0) { log_msg(LOG_VERBOSITY_ERROR, - "* Invalid hmac digest type: %s, use {md5,sha1,sha256,sha384,sha512}", + "* Invalid hmac digest type: %s, use {md5,sha1,sha256,sha384,sha512,sha3_256,sha3_512}", optarg); exit(EXIT_FAILURE); } @@ -2208,7 +2208,7 @@ config_init(fko_cli_options_t *options, int argc, char **argv) if((options->digest_type = digest_strtoint(optarg)) < 0) { log_msg(LOG_VERBOSITY_ERROR, - "* Invalid digest type: %s, use {md5,sha1,sha256,sha384,sha512}", + "* Invalid digest type: %s, use {md5,sha1,sha256,sha384,sha512,sha3_256,sha3_512}", optarg); exit(EXIT_FAILURE); } diff --git a/common/fko_util.c b/common/fko_util.c index 4e98ab5a..7095c54c 100644 --- a/common/fko_util.c +++ b/common/fko_util.c @@ -182,6 +182,10 @@ digest_strtoint(const char *dt_str) return(FKO_DIGEST_SHA384); else if(strcasecmp(dt_str, "sha512") == 0) return(FKO_DIGEST_SHA512); + else if(strcasecmp(dt_str, "sha3_256") == 0) + return(FKO_DIGEST_SHA3_512); + else if(strcasecmp(dt_str, "sha3_512") == 0) + return(FKO_DIGEST_SHA3_512); else return(-1); } @@ -222,6 +226,12 @@ digest_inttostr(int digest, char* digest_str, size_t digest_size) case FKO_DIGEST_SHA512: strlcpy(digest_str, "SHA512", digest_size); break; + case FKO_DIGEST_SHA3_256: + strlcpy(digest_str, "SHA3_256", digest_size); + break; + case FKO_DIGEST_SHA3_512: + strlcpy(digest_str, "SHA3_512", digest_size); + break; default: strlcpy(digest_str, "Unknown", digest_size); digest_not_valid = -1; @@ -244,6 +254,10 @@ hmac_digest_strtoint(const char *dt_str) return(FKO_HMAC_SHA384); else if(strcasecmp(dt_str, "sha512") == 0) return(FKO_HMAC_SHA512); + else if(strcasecmp(dt_str, "sha3_256") == 0) + return(FKO_HMAC_SHA3_256); + else if(strcasecmp(dt_str, "sha3_512") == 0) + return(FKO_HMAC_SHA3_512); else return(-1); } @@ -322,6 +336,12 @@ hmac_digest_inttostr(int digest, char* digest_str, size_t digest_size) case FKO_HMAC_SHA512: strlcpy(digest_str, "SHA512", digest_size); break; + case FKO_HMAC_SHA3_256: + strlcpy(digest_str, "SHA3_256", digest_size); + break; + case FKO_HMAC_SHA3_512: + strlcpy(digest_str, "SHA3_512", digest_size); + break; default: strlcpy(digest_str, "Unknown", digest_size); digest_not_valid = -1; diff --git a/lib/Makefile.am b/lib/Makefile.am index 6cb1ae39..d98e5177 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -7,7 +7,7 @@ libfko_source_files = \ fko_message.h fko_nat_access.c fko_rand_value.c fko_server_auth.c \ fko.h fko_limits.h fko_timestamp.c fko_hmac.c hmac.c hmac.h \ fko_user.c fko_user.h md5.c md5.h rijndael.c rijndael.h sha1.c \ - sha1.h sha2.c sha2.h fko_context.h fko_state.h \ + sha1.h sha2.c sha2.h sha3.c sha3.h fko_context.h fko_state.h \ gpgme_funcs.c gpgme_funcs.h diff --git a/lib/digest.c b/lib/digest.c index 061721c6..0c8926c0 100644 --- a/lib/digest.c +++ b/lib/digest.c @@ -154,4 +154,39 @@ sha512_base64(char *out, unsigned char *in, size_t size) strip_b64_eq(out); } +void +sha3_256(unsigned char *out, unsigned char *in, size_t size) +{ + FIPS202_SHA3_256(in, size, out); +} + +void +sha3_256_base64(char *out, unsigned char *in, size_t size) +{ + uint8_t md[SHA3_256_DIGEST_LEN]; + + FIPS202_SHA3_256(in, size, md); + b64_encode(md, out, SHA3_256_DIGEST_LEN); + + strip_b64_eq(out); + +} +void +sha3_512(unsigned char *out, unsigned char *in, size_t size) +{ + FIPS202_SHA3_512(in, size, out); +} + +void +sha3_512_base64(char *out, unsigned char *in, size_t size) +{ + uint8_t md[SHA3_512_DIGEST_LEN]; + + FIPS202_SHA3_512(in, size, md); + b64_encode(md, out, SHA3_512_DIGEST_LEN); + + strip_b64_eq(out); + +} + /***EOF***/ diff --git a/lib/digest.h b/lib/digest.h index 981eb4ea..b9f3842f 100644 --- a/lib/digest.h +++ b/lib/digest.h @@ -34,6 +34,7 @@ #include "md5.h" #include "sha1.h" #include "sha2.h" +#include "sha3.h" /* Size calculation macros */ @@ -49,6 +50,10 @@ void sha384(unsigned char* out, unsigned char* in, size_t size); void sha384_base64(char* out, unsigned char* in, size_t size); void sha512(unsigned char* out, unsigned char* in, size_t size); void sha512_base64(char* out, unsigned char* in, size_t size); +void sha3_256(unsigned char* out, unsigned char* in, size_t size); +void sha3_256_base64(char* out, unsigned char* in, size_t size); +void sha3_512(unsigned char* out, unsigned char* in, size_t size); +void sha3_512_base64(char* out, unsigned char* in, size_t size); #endif /* DIGEST_H */ diff --git a/lib/fko.h b/lib/fko.h index 19772dc2..6b49afae 100644 --- a/lib/fko.h +++ b/lib/fko.h @@ -87,6 +87,8 @@ typedef enum { FKO_DIGEST_SHA256, /**< SHA256 digest type*/ FKO_DIGEST_SHA384, /**< SHA384 digest type*/ FKO_DIGEST_SHA512, /**< SHA512 digest type*/ + FKO_DIGEST_SHA3_256, /**< SHA3 256 digest type*/ + FKO_DIGEST_SHA3_512, /**< SHA3 512 digest type*/ FKO_LAST_DIGEST_TYPE /**< Always leave this as the last one */ } fko_digest_type_t; @@ -104,6 +106,8 @@ typedef enum { FKO_HMAC_SHA256, /**< SHA256 HMAC type*/ FKO_HMAC_SHA384, /**< SHA384 HMAC type*/ FKO_HMAC_SHA512, /**< SHA512 HMAC type*/ + FKO_HMAC_SHA3_256, /**< SHA3 256 HMAC type */ + FKO_HMAC_SHA3_512, /**< SHA3 512 HMAC type*/ FKO_LAST_HMAC_MODE /**< Always leave this as the last one */ } fko_hmac_type_t; diff --git a/lib/fko_digest.c b/lib/fko_digest.c index 06c076d7..0779314b 100644 --- a/lib/fko_digest.c +++ b/lib/fko_digest.c @@ -193,6 +193,26 @@ set_digest(char *data, char **digest, short digest_type, int *digest_len) *digest_len = SHA512_B64_LEN; break; + case FKO_DIGEST_SHA3_256: + md = calloc(1, MD_HEX_SIZE(SHA3_256_DIGEST_LEN)+1); + if(md == NULL) + return(FKO_ERROR_MEMORY_ALLOCATION); + + sha3_256_base64(md, + (unsigned char*)data, data_len); + *digest_len = SHA3_256_B64_LEN; + break; + + case FKO_DIGEST_SHA3_512: + md = calloc(1, MD_HEX_SIZE(SHA3_512_DIGEST_LEN)+1); + if(md == NULL) + return(FKO_ERROR_MEMORY_ALLOCATION); + + sha3_512_base64(md, + (unsigned char*)data, data_len); + *digest_len = SHA3_512_B64_LEN; + break; + default: return(FKO_ERROR_INVALID_DIGEST_TYPE); } diff --git a/lib/fko_hmac.c b/lib/fko_hmac.c index d6186ff4..2cd37351 100644 --- a/lib/fko_hmac.c +++ b/lib/fko_hmac.c @@ -67,6 +67,10 @@ fko_verify_hmac(fko_ctx_t ctx, hmac_b64_digest_len = SHA384_B64_LEN; else if(ctx->hmac_type == FKO_HMAC_SHA512) hmac_b64_digest_len = SHA512_B64_LEN; + else if(ctx->hmac_type == FKO_HMAC_SHA3_256) + hmac_b64_digest_len = SHA3_256_B64_LEN; + else if(ctx->hmac_type == FKO_HMAC_SHA3_512) + hmac_b64_digest_len = SHA3_512_B64_LEN; else return(FKO_ERROR_UNSUPPORTED_HMAC_MODE); @@ -289,6 +293,22 @@ int fko_set_spa_hmac(fko_ctx_t ctx, hmac_digest_len = SHA512_DIGEST_LEN; hmac_digest_str_len = SHA512_DIGEST_STR_LEN; } + else if(ctx->hmac_type == FKO_HMAC_SHA3_256) + { + hmac_sha3_256(ctx->encrypted_msg, + ctx->encrypted_msg_len, hmac, hmac_key, hmac_key_len); + hmac_digest_len = SHA3_256_DIGEST_LEN; + hmac_digest_str_len = SHA3_256_DIGEST_STR_LEN; + + } + else if(ctx->hmac_type == FKO_HMAC_SHA3_512) + { + hmac_sha3_512(ctx->encrypted_msg, + ctx->encrypted_msg_len, hmac, hmac_key, hmac_key_len); + hmac_digest_len = SHA3_512_DIGEST_LEN; + hmac_digest_str_len = SHA3_512_DIGEST_STR_LEN; + + } hmac_base64 = calloc(1, MD_HEX_SIZE(hmac_digest_len)+1); if (hmac_base64 == NULL) diff --git a/lib/hmac.c b/lib/hmac.c index 80cb1016..efc7a968 100644 --- a/lib/hmac.c +++ b/lib/hmac.c @@ -430,3 +430,87 @@ hmac_sha512(const char *msg, const unsigned int msg_len, return; } + +void +hmac_sha3_256(const char *msg, const unsigned int msg_len, + unsigned char *hmac, const char *hmac_key, const int hmac_key_len) +{ + unsigned char inner_hash[SHA3_256_DIGEST_LEN] = {0}; + unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN] = {0}; + unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN] = {0}; + unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0}; + unsigned char padded_hash[2 * MAX_DIGEST_BLOCK_LEN + 1] = {0}; + unsigned char *padded_msg = malloc(msg_len + MAX_DIGEST_BLOCK_LEN + 1); + int final_len = hmac_key_len; + + if(SHA3_256_BLOCK_LEN < hmac_key_len) + { + /* Calculate the digest of the key + */ + FIPS202_SHA3_256((unsigned char *)hmac_key, final_len, final_key); + final_len = SHA3_256_DIGEST_LEN; + } + else + { + memcpy(final_key, hmac_key, hmac_key_len); + } + pad_init(block_inner_pad, block_outer_pad, final_key, final_len); + //The first step is to hash the inner_pad + message + memcpy(padded_msg, block_inner_pad, SHA3_256_BLOCK_LEN); + memcpy(padded_msg + SHA3_256_BLOCK_LEN, msg, msg_len); + + //Calculate the inner hash + FIPS202_SHA3_256(padded_msg, msg_len + SHA3_256_BLOCK_LEN, inner_hash); + + //Then hash the outer pad + inner hash + memcpy(padded_hash, block_outer_pad, SHA3_256_BLOCK_LEN); + memcpy(padded_hash + SHA3_256_BLOCK_LEN, inner_hash, SHA3_256_DIGEST_LEN); + + //the outer hash is the final hmac + FIPS202_SHA3_256(padded_hash, SHA3_256_BLOCK_LEN + SHA3_256_DIGEST_LEN, hmac); + + free(padded_msg); +} + +void +hmac_sha3_512(const char *msg, const unsigned int msg_len, + unsigned char *hmac, const char *hmac_key, const int hmac_key_len) +{ + unsigned char inner_hash[SHA3_512_DIGEST_LEN] = {0}; + unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN] = {0}; + unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN] = {0}; + unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0}; + unsigned char padded_hash[SHA3_512_BLOCK_LEN + SHA3_512_DIGEST_LEN + 1] = {0}; + unsigned char *padded_msg = malloc(msg_len + MAX_DIGEST_BLOCK_LEN + 1); + + int final_len = hmac_key_len; + + if(SHA3_512_BLOCK_LEN < hmac_key_len) + { + /* Calculate the digest of the key + */ + FIPS202_SHA3_512((unsigned char *)hmac_key, final_len, final_key); + final_len = SHA3_512_DIGEST_LEN; + } + else + { + memcpy(final_key, hmac_key, hmac_key_len); + } + pad_init(block_inner_pad, block_outer_pad, final_key, final_len); + + //The first step is to hash the inner_pad + message + memcpy(padded_msg, block_inner_pad, SHA3_512_BLOCK_LEN); + memcpy(padded_msg + SHA3_512_BLOCK_LEN, msg, msg_len); + + //Calculate the inner hash + FIPS202_SHA3_512(padded_msg, msg_len + SHA3_512_BLOCK_LEN, inner_hash); + + //Then hash the outer pad + inner hash + memcpy(padded_hash, block_outer_pad, SHA3_512_BLOCK_LEN); + memcpy(padded_hash + SHA3_512_BLOCK_LEN, inner_hash, SHA3_512_DIGEST_LEN); + + //the outer hash is the final hmac + FIPS202_SHA3_512(padded_hash, SHA3_512_BLOCK_LEN + SHA3_512_DIGEST_LEN, hmac); + + free(padded_msg); +} diff --git a/lib/hmac.h b/lib/hmac.h index 55499a6d..8eb05645 100644 --- a/lib/hmac.h +++ b/lib/hmac.h @@ -33,7 +33,7 @@ #include "digest.h" -#define MAX_DIGEST_BLOCK_LEN SHA512_BLOCK_LEN +#define MAX_DIGEST_BLOCK_LEN SHA3_256_BLOCK_LEN /** * \brief Generate MD5 based HMAC * @@ -56,6 +56,10 @@ void hmac_sha384(const char *msg, const unsigned int msg_len, unsigned char *hmac, const char *hmac_key, const int hmac_key_len); void hmac_sha512(const char *msg, const unsigned int msg_len, unsigned char *hmac, const char *hmac_key, const int hmac_key_len); +void hmac_sha3_256(const char *msg, const unsigned int msg_len, + unsigned char *hmac, const char *hmac_key, const int hmac_key_len); +void hmac_sha3_512(const char *msg, const unsigned int msg_len, + unsigned char *hmac, const char *hmac_key, const int hmac_key_len); #endif /* HMAC_H */ diff --git a/lib/sha3.c b/lib/sha3.c new file mode 100644 index 00000000..75559ecb --- /dev/null +++ b/lib/sha3.c @@ -0,0 +1,334 @@ +/* +Implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni, +Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer, hereby +denoted as "the implementer". + +For more information, feedback or questions, please refer to our websites: +http://keccak.noekeon.org/ +http://keyak.noekeon.org/ +http://ketje.noekeon.org/ + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +/* +================================================================ +The purpose of this source file is to demonstrate a readable and compact +implementation of all the Keccak instances approved in the FIPS 202 standard, +including the hash functions and the extendable-output functions (XOFs). + +We focused on clarity and on source-code compactness, +rather than on the performance. + +The advantages of this implementation are: + + The source code is compact, after removing the comments, that is. :-) + + There are no tables with arbitrary constants. + + For clarity, the comments link the operations to the specifications using + the same notation as much as possible. + + There is no restriction in cryptographic features. In particular, + the SHAKE128 and SHAKE256 XOFs can produce any output length. + + The code does not use much RAM, as all operations are done in place. + +The drawbacks of this implementation are: + - There is no message queue. The whole message must be ready in a buffer. + - It is not optimized for peformance. + +The implementation is even simpler on a little endian platform. Just define the +LITTLE_ENDIAN symbol in that case. + +For a more complete set of implementations, please refer to +the Keccak Code Package at https://github.com/gvanas/KeccakCodePackage + +For more information, please refer to: + * [Keccak Reference] http://keccak.noekeon.org/Keccak-reference-3.0.pdf + * [Keccak Specifications Summary] http://keccak.noekeon.org/specs_summary.html + +This file uses UTF-8 encoding, as some comments use Greek letters. +================================================================ +*/ + +/** + * Function to compute the Keccak[r, c] sponge function over a given input. + * @param rate The value of the rate r. + * @param capacity The value of the capacity c. + * @param input Pointer to the input message. + * @param inputByteLen The number of input bytes provided in the input message. + * @param delimitedSuffix Bits that will be automatically appended to the end + * of the input message, as in domain separation. + * This is a byte containing from 0 to 7 bits + * These n bits must be in the least significant bit positions + * and must be delimited with a bit 1 at position n + * (counting from 0=LSB to 7=MSB) and followed by bits 0 + * from position n+1 to position 7. + * Some examples: + * - If no bits are to be appended, then @a delimitedSuffix must be 0x01. + * - If the 2-bit sequence 0,1 is to be appended (as for SHA3-*), @a delimitedSuffix must be 0x06. + * - If the 4-bit sequence 1,1,1,1 is to be appended (as for SHAKE*), @a delimitedSuffix must be 0x1F. + * - If the 7-bit sequence 1,1,0,1,0,0,0 is to be absorbed, @a delimitedSuffix must be 0x8B. + * @param output Pointer to the buffer where to store the output. + * @param outputByteLen The number of output bytes desired. + * @pre One must have r+c=1600 and the rate a multiple of 8 bits in this implementation. + */ +//void Keccak(unsigned int rate, unsigned int capacity, const unsigned char *input, unsigned long long int inputByteLen, unsigned char delimitedSuffix, unsigned char *output, unsigned long long int outputByteLen); + +/** + * Function to compute SHAKE128 on the input message with any output length. + */ +#include "sha3.h" +void FIPS202_SHAKE128(const unsigned char *input, unsigned int inputByteLen, unsigned char *output, int outputByteLen) +{ + Keccak(1344, 256, input, inputByteLen, 0x1F, output, outputByteLen); +} + +/** + * Function to compute SHAKE256 on the input message with any output length. + */ +void FIPS202_SHAKE256(const unsigned char *input, unsigned int inputByteLen, unsigned char *output, int outputByteLen) +{ + Keccak(1088, 512, input, inputByteLen, 0x1F, output, outputByteLen); +} + +/** + * Function to compute SHA3-224 on the input message. The output length is fixed to 28 bytes. + */ +void FIPS202_SHA3_224(const unsigned char *input, unsigned int inputByteLen, unsigned char *output) +{ + Keccak(1152, 448, input, inputByteLen, 0x06, output, 28); +} + +/** + * Function to compute SHA3-256 on the input message. The output length is fixed to 32 bytes. + */ +void FIPS202_SHA3_256(const unsigned char *input, unsigned int inputByteLen, unsigned char *output) +{ + Keccak(1088, 512, input, inputByteLen, 0x06, output, 32); +} + +/** + * Function to compute SHA3-384 on the input message. The output length is fixed to 48 bytes. + */ +void FIPS202_SHA3_384(const unsigned char *input, unsigned int inputByteLen, unsigned char *output) +{ + Keccak(832, 768, input, inputByteLen, 0x06, output, 48); +} + +/** + * Function to compute SHA3-512 on the input message. The output length is fixed to 64 bytes. + */ +void FIPS202_SHA3_512(const unsigned char *input, unsigned int inputByteLen, unsigned char *output) +{ + Keccak(576, 1024, input, inputByteLen, 0x06, output, 64); +} + +/* +================================================================ +Technicalities +================================================================ +*/ + +typedef unsigned char UINT8; +typedef unsigned long long int UINT64; +typedef UINT64 tKeccakLane; + +#ifndef LITTLE_ENDIAN +/** Function to load a 64-bit value using the little-endian (LE) convention. + * On a LE platform, this could be greatly simplified using a cast. + */ +static UINT64 load64(const UINT8 *x) +{ + int i; + UINT64 u=0; + + for(i=7; i>=0; --i) { + u <<= 8; + u |= x[i]; + } + return u; +} + +/** Function to store a 64-bit value using the little-endian (LE) convention. + * On a LE platform, this could be greatly simplified using a cast. + */ +static void store64(UINT8 *x, UINT64 u) +{ + unsigned int i; + + for(i=0; i<8; ++i) { + x[i] = u; + u >>= 8; + } +} + +/** Function to XOR into a 64-bit value using the little-endian (LE) convention. + * On a LE platform, this could be greatly simplified using a cast. + */ +static void xor64(UINT8 *x, UINT64 u) +{ + unsigned int i; + + for(i=0; i<8; ++i) { + x[i] ^= u; + u >>= 8; + } +} +#endif + +/* +================================================================ +A readable and compact implementation of the Keccak-f[1600] permutation. +================================================================ +*/ + +#define ROL64(a, offset) ((((UINT64)a) << offset) ^ (((UINT64)a) >> (64-offset))) +#define i(x, y) ((x)+5*(y)) + +#ifdef LITTLE_ENDIAN + #define readLane(x, y) (((tKeccakLane*)state)[i(x, y)]) + #define writeLane(x, y, lane) (((tKeccakLane*)state)[i(x, y)]) = (lane) + #define XORLane(x, y, lane) (((tKeccakLane*)state)[i(x, y)]) ^= (lane) +#else + #define readLane(x, y) load64((UINT8*)state+sizeof(tKeccakLane)*i(x, y)) + #define writeLane(x, y, lane) store64((UINT8*)state+sizeof(tKeccakLane)*i(x, y), lane) + #define XORLane(x, y, lane) xor64((UINT8*)state+sizeof(tKeccakLane)*i(x, y), lane) +#endif + +/** + * Function that computes the linear feedback shift register (LFSR) used to + * define the round constants (see [Keccak Reference, Section 1.2]). + */ +int LFSR86540(UINT8 *LFSR) +{ + int result = ((*LFSR) & 0x01) != 0; + if (((*LFSR) & 0x80) != 0) + // Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1 + (*LFSR) = ((*LFSR) << 1) ^ 0x71; + else + (*LFSR) <<= 1; + return result; +} + +/** + * Function that computes the Keccak-f[1600] permutation on the given state. + */ +void KeccakF1600_StatePermute(void *state) +{ + unsigned int round, x, y, j, t; + UINT8 LFSRstate = 0x01; + + for(round=0; round<24; round++) { + { // === θ step (see [Keccak Reference, Section 2.3.2]) === + tKeccakLane C[5], D; + + // Compute the parity of the columns + for(x=0; x<5; x++) + C[x] = readLane(x, 0) ^ readLane(x, 1) ^ readLane(x, 2) ^ readLane(x, 3) ^ readLane(x, 4); + for(x=0; x<5; x++) { + // Compute the θ effect for a given column + D = C[(x+4)%5] ^ ROL64(C[(x+1)%5], 1); + // Add the θ effect to the whole column + for (y=0; y<5; y++) + XORLane(x, y, D); + } + } + + { // === ρ and π steps (see [Keccak Reference, Sections 2.3.3 and 2.3.4]) === + tKeccakLane current, temp; + // Start at coordinates (1 0) + x = 1; y = 0; + current = readLane(x, y); + // Iterate over ((0 1)(2 3))^t * (1 0) for 0 ≤ t ≤ 23 + for(t=0; t<24; t++) { + // Compute the rotation constant r = (t+1)(t+2)/2 + unsigned int r = ((t+1)*(t+2)/2)%64; + // Compute ((0 1)(2 3)) * (x y) + unsigned int Y = (2*x+3*y)%5; x = y; y = Y; + // Swap current and state(x,y), and rotate + temp = readLane(x, y); + writeLane(x, y, ROL64(current, r)); + current = temp; + } + } + + { // === χ step (see [Keccak Reference, Section 2.3.1]) === + tKeccakLane temp[5]; + for(y=0; y<5; y++) { + // Take a copy of the plane + for(x=0; x<5; x++) + temp[x] = readLane(x, y); + // Compute χ on the plane + for(x=0; x<5; x++) + writeLane(x, y, temp[x] ^((~temp[(x+1)%5]) & temp[(x+2)%5])); + } + } + + { // === ι step (see [Keccak Reference, Section 2.3.5]) === + for(j=0; j<7; j++) { + unsigned int bitPosition = (1< +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +void Keccak(unsigned int rate, unsigned int capacity, const unsigned char *input, unsigned long long int inputByteLen, unsigned char delimitedSuffix, unsigned char *output, unsigned long long int outputByteLen) +{ + UINT8 state[200]; + unsigned int rateInBytes = rate/8; + unsigned int blockSize = 0; + unsigned int i; + + if (((rate + capacity) != 1600) || ((rate % 8) != 0)) + return; + + // === Initialize the state === + memset(state, 0, sizeof(state)); + + // === Absorb all the input blocks === + while(inputByteLen > 0) { + blockSize = MIN(inputByteLen, rateInBytes); + for(i=0; i 0) { + blockSize = MIN(outputByteLen, rateInBytes); + memcpy(output, state, blockSize); + output += blockSize; + outputByteLen -= blockSize; + + if (outputByteLen > 0) + KeccakF1600_StatePermute(state); + } +} diff --git a/lib/sha3.h b/lib/sha3.h new file mode 100644 index 00000000..88afcc51 --- /dev/null +++ b/lib/sha3.h @@ -0,0 +1,40 @@ +#define SHA3_256_DIGEST_LEN 32 +#define SHA3_512_DIGEST_LEN 64 +#define SHA3_256_BLOCK_LEN 136 +#define SHA3_512_BLOCK_LEN 72 +#define SHA3_256_B64_LEN 43 +#define SHA3_512_B64_LEN 86 +#define SHA3_256_DIGEST_STR_LEN (SHA3_256_DIGEST_LEN * 2 + 1) +#define SHA3_512_DIGEST_STR_LEN (SHA3_512_DIGEST_LEN * 2 + 1) + +void Keccak(unsigned int rate, unsigned int capacity, const unsigned char *input, unsigned long long int inputByteLen, unsigned char delimitedSuffix, unsigned char *output, unsigned long long int outputByteLen); + +/** + * Function to compute SHAKE128 on the input message with any output length. + */ +void FIPS202_SHAKE128(const unsigned char *input, unsigned int inputByteLen, unsigned char *output, int outputByteLen); + +/** + * Function to compute SHAKE256 on the input message with any output length. + */ +void FIPS202_SHAKE256(const unsigned char *input, unsigned int inputByteLen, unsigned char *output, int outputByteLen); + +/** + * Function to compute SHA3-224 on the input message. The output length is fixed to 28 bytes. + */ +void FIPS202_SHA3_224(const unsigned char *input, unsigned int inputByteLen, unsigned char *output); + +/** + * Function to compute SHA3-256 on the input message. The output length is fixed to 32 bytes. + */ +void FIPS202_SHA3_256(const unsigned char *input, unsigned int inputByteLen, unsigned char *output); + +/** + * Function to compute SHA3-384 on the input message. The output length is fixed to 48 bytes. + */ +void FIPS202_SHA3_384(const unsigned char *input, unsigned int inputByteLen, unsigned char *output); + +/** + * Function to compute SHA3-512 on the input message. The output length is fixed to 64 bytes. + */ +void FIPS202_SHA3_512(const unsigned char *input, unsigned int inputByteLen, unsigned char *output); diff --git a/server/access.c b/server/access.c index ec599560..9d2a69c2 100644 --- a/server/access.c +++ b/server/access.c @@ -1638,7 +1638,7 @@ parse_access_file(fko_srv_options_t *opts, char *access_filename, int *depth) if(curr_acc->hmac_type < 0) { log_msg(LOG_ERR, - "[*] HMAC_DIGEST_TYPE argument '%s' must be one of {md5,sha1,sha256,sha384,sha512}", + "[*] HMAC_DIGEST_TYPE argument '%s' must be one of {md5,sha1,sha256,sha384,sha512,sha3_256,sha3_512}", val); fclose(file_ptr); return EXIT_FAILURE; From 32a37f7e1fcf6d4aa7d42ce4c0c4ef85173c2f14 Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Mon, 21 Dec 2015 10:32:29 -0600 Subject: [PATCH 2/3] Add CUnit tests for various crypto functions --- lib/cipher_funcs.c | 247 ++++++++++ lib/digest.c | 388 +++++++++++++++- lib/fko.h | 4 + lib/fko_utests.c | 5 +- lib/hmac.c | 1097 +++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 1738 insertions(+), 3 deletions(-) diff --git a/lib/cipher_funcs.c b/lib/cipher_funcs.c index d652d0d6..5c62b665 100644 --- a/lib/cipher_funcs.c +++ b/lib/cipher_funcs.c @@ -49,6 +49,10 @@ #endif #endif +#ifdef HAVE_C_UNIT_TESTS +DECLARE_TEST_SUITE(digest_test, "Cipher functions test suite"); +#endif + /* Get random data. */ void @@ -414,4 +418,247 @@ add_gpg_prefix(fko_ctx_t ctx) return(FKO_SUCCESS); } +#ifdef HAVE_C_UNIT_TESTS + + + +DECLARE_UTEST(test_aes_ecb_128, "aes ecb 128 test vectors") //http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors#aes-cbc-128 +{ + RIJNDAEL_context ctx; + unsigned char in[1024] = {0}; + unsigned char out[1024] = {0}; + unsigned char expected_out1[1024] = {0}; + unsigned char expected_out2[1024] = {0}; + unsigned char expected_out3[1024] = {0}; + unsigned char expected_out4[1024] = {0}; + + memcpy(expected_out1, "\x3a\xd7\x7b\xb4\x0d\x7a\x36\x60\xa8\x9e\xca\xf3\x24\x66\xef\x97", 16); + memcpy(expected_out2, "\xf5\xd3\xd5\x85\x03\xb9\x69\x9d\xe7\x85\x89\x5a\x96\xfd\xba\xaf", 16); + memcpy(expected_out3, "\x43\xb1\xcd\x7f\x59\x8e\xce\x23\x88\x1b\x00\xe3\xed\x03\x06\x88", 16); + memcpy(expected_out4, "\x7b\x0c\x78\x5e\x27\xe8\xad\x3f\x82\x23\x20\x71\x04\x72\x5d\xd4", 16); + memcpy(ctx.key, "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16); + rijndael_setup(&ctx, 16, ctx.key); + + memcpy(in, "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16); + rijndael_encrypt(&ctx, in, out); + CU_ASSERT(memcmp(out, expected_out1, 16) == 0); + + memcpy(in, "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", 16); + rijndael_encrypt(&ctx, in, out); + CU_ASSERT(memcmp(out, expected_out2, 16) == 0); + + memcpy(in, "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", 16); + rijndael_encrypt(&ctx, in, out); + CU_ASSERT(memcmp(out, expected_out3, 16) == 0); + + memcpy(in, "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 16); + rijndael_encrypt(&ctx, in, out); + CU_ASSERT(memcmp(out, expected_out4, 16) == 0); + +} +DECLARE_UTEST(test_aes_ecb_192, "aes ecb 192 test vectors") //http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors#aes-cbc-128 +{ + RIJNDAEL_context ctx; + unsigned char in[1024] = {0}; + unsigned char out[1024] = {0}; + unsigned char expected_out1[1024] = {0}; + unsigned char expected_out2[1024] = {0}; + unsigned char expected_out3[1024] = {0}; + unsigned char expected_out4[1024] = {0}; + + memcpy(expected_out1, "\xbd\x33\x4f\x1d\x6e\x45\xf2\x5f\xf7\x12\xa2\x14\x57\x1f\xa5\xcc", 16); + memcpy(expected_out2, "\x97\x41\x04\x84\x6d\x0a\xd3\xad\x77\x34\xec\xb3\xec\xee\x4e\xef", 16); + memcpy(expected_out3, "\xef\x7a\xfd\x22\x70\xe2\xe6\x0a\xdc\xe0\xba\x2f\xac\xe6\x44\x4e", 16); + memcpy(expected_out4, "\x9a\x4b\x41\xba\x73\x8d\x6c\x72\xfb\x16\x69\x16\x03\xc1\x8e\x0e", 16); + memcpy(ctx.key, "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", 24); + rijndael_setup(&ctx, 24, ctx.key); + + memcpy(in, "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16); + rijndael_encrypt(&ctx, in, out); + CU_ASSERT(memcmp(out, expected_out1, 16) == 0); + + memcpy(in, "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", 16); + rijndael_encrypt(&ctx, in, out); + CU_ASSERT(memcmp(out, expected_out2, 16) == 0); + + memcpy(in, "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", 16); + rijndael_encrypt(&ctx, in, out); + CU_ASSERT(memcmp(out, expected_out3, 16) == 0); + + memcpy(in, "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 16); + rijndael_encrypt(&ctx, in, out); + CU_ASSERT(memcmp(out, expected_out4, 16) == 0); + +} +DECLARE_UTEST(test_aes_ecb_256, "aes ecb 256 test vectors") //http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors#aes-cbc-128 +{ + RIJNDAEL_context ctx; + unsigned char in[1024] = {0}; + unsigned char out[1024] = {0}; + unsigned char expected_out1[1024] = {0}; + unsigned char expected_out2[1024] = {0}; + unsigned char expected_out3[1024] = {0}; + unsigned char expected_out4[1024] = {0}; + + memcpy(expected_out1, "\xf3\xee\xd1\xbd\xb5\xd2\xa0\x3c\x06\x4b\x5a\x7e\x3d\xb1\x81\xf8", 16); + memcpy(expected_out2, "\x59\x1c\xcb\x10\xd4\x10\xed\x26\xdc\x5b\xa7\x4a\x31\x36\x28\x70", 16); + memcpy(expected_out3, "\xb6\xed\x21\xb9\x9c\xa6\xf4\xf9\xf1\x53\xe7\xb1\xbe\xaf\xed\x1d", 16); + memcpy(expected_out4, "\x23\x30\x4b\x7a\x39\xf9\xf3\xff\x06\x7d\x8d\x8f\x9e\x24\xec\xc7", 16); + memcpy(ctx.key, "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", 32); + rijndael_setup(&ctx, 32, ctx.key); + + memcpy(in, "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16); + rijndael_encrypt(&ctx, in, out); + CU_ASSERT(memcmp(out, expected_out1, 16) == 0); + + memcpy(in, "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", 16); + rijndael_encrypt(&ctx, in, out); + CU_ASSERT(memcmp(out, expected_out2, 16) == 0); + + memcpy(in, "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", 16); + rijndael_encrypt(&ctx, in, out); + CU_ASSERT(memcmp(out, expected_out3, 16) == 0); + + memcpy(in, "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 16); + rijndael_encrypt(&ctx, in, out); + CU_ASSERT(memcmp(out, expected_out4, 16) == 0); + +} + +DECLARE_UTEST(test_aes_cbc_128, "aes cbc 128 test vectors") //http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors#aes-cbc-128 +{ //would like to test rij_encrypt against known test vectors, but the method of generating the key and iv make this impossible. + RIJNDAEL_context ctx; + unsigned char in[1024] = {0}; + unsigned char out[1024] = {0}; + unsigned char expected_out1[1024] = {0}; + unsigned char expected_out2[1024] = {0}; + unsigned char expected_out3[1024] = {0}; + unsigned char expected_out4[1024] = {0}; + + memcpy(ctx.key, "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", 16); + memcpy(expected_out1, "\x76\x49\xab\xac\x81\x19\xb2\x46\xce\xe9\x8e\x9b\x12\xe9\x19\x7d", 16); + memcpy(expected_out2, "\x50\x86\xcb\x9b\x50\x72\x19\xee\x95\xdb\x11\x3a\x91\x76\x78\xb2", 16); + memcpy(expected_out3, "\x73\xbe\xd6\xb8\xe3\xc1\x74\x3b\x71\x16\xe6\x9e\x22\x22\x95\x16", 16); + memcpy(expected_out4, "\x3f\xf1\xca\xa1\x68\x1f\xac\x09\x12\x0e\xca\x30\x75\x86\xe1\xa7", 16); + ctx.mode = MODE_CBC; + rijndael_setup(&ctx, 16, ctx.key); + + memcpy(ctx.iv, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16); + memcpy(in, "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16); + block_encrypt(&ctx, in, 16, out, ctx.iv); + CU_ASSERT(memcmp(out, expected_out1, 16) == 0); + + memcpy(ctx.iv, "\x76\x49\xAB\xAC\x81\x19\xB2\x46\xCE\xE9\x8E\x9B\x12\xE9\x19\x7D", 16); + memcpy(in, "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", 16); + block_encrypt(&ctx, in, 16, out, ctx.iv); + CU_ASSERT(memcmp(out, expected_out2, 16) == 0); + + memcpy(ctx.iv, "\x50\x86\xCB\x9B\x50\x72\x19\xEE\x95\xDB\x11\x3A\x91\x76\x78\xB2", 16); + memcpy(in, "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", 16); + block_encrypt(&ctx, in, 16, out, ctx.iv); + CU_ASSERT(memcmp(out, expected_out3, 16) == 0); + + memcpy(ctx.iv, "\x73\xBE\xD6\xB8\xE3\xC1\x74\x3B\x71\x16\xE6\x9E\x22\x22\x95\x16", 16); + memcpy(in, "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 16); + block_encrypt(&ctx, in, 16, out, ctx.iv); + CU_ASSERT(memcmp(out, expected_out4, 16) == 0); + + +} + +DECLARE_UTEST(test_aes_cbc_192, "aes cbc 192 test vectors") //http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors#aes-cbc-128 +{ //would like to test rij_encrypt against known test vectors, but the method of generating the key and iv make this impossible. + RIJNDAEL_context ctx; + unsigned char in[1024] = {0}; + unsigned char out[1024] = {0}; + unsigned char expected_out1[1024] = {0}; + unsigned char expected_out2[1024] = {0}; + unsigned char expected_out3[1024] = {0}; + unsigned char expected_out4[1024] = {0}; + + memcpy(ctx.key, "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", 24); + memcpy(expected_out1, "\x4f\x02\x1d\xb2\x43\xbc\x63\x3d\x71\x78\x18\x3a\x9f\xa0\x71\xe8", 16); + memcpy(expected_out2, "\xb4\xd9\xad\xa9\xad\x7d\xed\xf4\xe5\xe7\x38\x76\x3f\x69\x14\x5a", 16); + memcpy(expected_out3, "\x57\x1b\x24\x20\x12\xfb\x7a\xe0\x7f\xa9\xba\xac\x3d\xf1\x02\xe0", 16); + memcpy(expected_out4, "\x08\xb0\xe2\x79\x88\x59\x88\x81\xd9\x20\xa9\xe6\x4f\x56\x15\xcd", 16); + ctx.mode = MODE_CBC; + rijndael_setup(&ctx, 24, ctx.key); + + memcpy(ctx.iv, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16); + memcpy(in, "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16); + block_encrypt(&ctx, in, 16, out, ctx.iv); + CU_ASSERT(memcmp(out, expected_out1, 16) == 0); + + memcpy(ctx.iv, out, 16); + memcpy(in, "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", 16); + block_encrypt(&ctx, in, 16, out, ctx.iv); + CU_ASSERT(memcmp(out, expected_out2, 16) == 0); + + memcpy(ctx.iv, out, 16); + memcpy(in, "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", 16); + block_encrypt(&ctx, in, 16, out, ctx.iv); + CU_ASSERT(memcmp(out, expected_out3, 16) == 0); + + memcpy(ctx.iv, out, 16); + memcpy(in, "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 16); + block_encrypt(&ctx, in, 16, out, ctx.iv); + CU_ASSERT(memcmp(out, expected_out4, 16) == 0); + + +} + +DECLARE_UTEST(test_aes_cbc_256, "aes cbc 256 test vectors") //http://www.inconteam.com/software-development/41-encryption/55-aes-test-vectors#aes-cbc-128 +{ //would like to test rij_encrypt against known test vectors, but the method of generating the key and iv make this impossible. + RIJNDAEL_context ctx; + unsigned char in[1024] = {0}; + unsigned char out[1024] = {0}; + unsigned char expected_out1[1024] = {0}; + unsigned char expected_out2[1024] = {0}; + unsigned char expected_out3[1024] = {0}; + unsigned char expected_out4[1024] = {0}; + + memcpy(ctx.key, "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", 32); + memcpy(expected_out1, "\xf5\x8c\x4c\x04\xd6\xe5\xf1\xba\x77\x9e\xab\xfb\x5f\x7b\xfb\xd6", 16); + memcpy(expected_out2, "\x9c\xfc\x4e\x96\x7e\xdb\x80\x8d\x67\x9f\x77\x7b\xc6\x70\x2c\x7d", 16); + memcpy(expected_out3, "\x39\xf2\x33\x69\xa9\xd9\xba\xcf\xa5\x30\xe2\x63\x04\x23\x14\x61", 16); + memcpy(expected_out4, "\xb2\xeb\x05\xe2\xc3\x9b\xe9\xfc\xda\x6c\x19\x07\x8c\x6a\x9d\x1b", 16); + ctx.mode = MODE_CBC; + rijndael_setup(&ctx, 32, ctx.key); + + memcpy(ctx.iv, "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F", 16); + memcpy(in, "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", 16); + block_encrypt(&ctx, in, 16, out, ctx.iv); + CU_ASSERT(memcmp(out, expected_out1, 16) == 0); + + memcpy(ctx.iv, out, 16); + memcpy(in, "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", 16); + block_encrypt(&ctx, in, 16, out, ctx.iv); + CU_ASSERT(memcmp(out, expected_out2, 16) == 0); + + memcpy(ctx.iv, out, 16); + memcpy(in, "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef", 16); + block_encrypt(&ctx, in, 16, out, ctx.iv); + CU_ASSERT(memcmp(out, expected_out3, 16) == 0); + + memcpy(ctx.iv, out, 16); + memcpy(in, "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", 16); + block_encrypt(&ctx, in, 16, out, ctx.iv); + CU_ASSERT(memcmp(out, expected_out4, 16) == 0); + + +} + +int register_ts_aes_test(void) +{ + ts_init(&TEST_SUITE(digest_test), TEST_SUITE_DESCR(digest_test), NULL, NULL); + ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_aes_ecb_128), UTEST_DESCR(test_aes_ecb_128)); + ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_aes_ecb_192), UTEST_DESCR(test_aes_ecb_192)); + ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_aes_ecb_256), UTEST_DESCR(test_aes_ecb_256)); + ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_aes_cbc_128), UTEST_DESCR(test_aes_cbc_128)); + ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_aes_cbc_192), UTEST_DESCR(test_aes_cbc_192)); + ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_aes_cbc_256), UTEST_DESCR(test_aes_cbc_256)); + + return register_ts(&TEST_SUITE(digest_test)); +} +#endif /***EOF***/ diff --git a/lib/digest.c b/lib/digest.c index 0c8926c0..e3f7b063 100644 --- a/lib/digest.c +++ b/lib/digest.c @@ -28,7 +28,9 @@ #include "fko_common.h" #include "digest.h" #include "base64.h" - +#ifdef HAVE_C_UNIT_TESTS +DECLARE_TEST_SUITE(digest_test, "digest functions test suite"); +#endif /* Compute MD5 hash on in and store result in out. */ void @@ -189,4 +191,388 @@ sha3_512_base64(char *out, unsigned char *in, size_t size) } +#ifdef HAVE_C_UNIT_TESTS + +DECLARE_UTEST(test_md5, "md5 test vectors") //https://tools.ietf.org/html/rfc1321.html +{ + char msg[1024] = {0}; + unsigned char digest[1024] = {0}; + char digest_txt[1024] = {0}; + char expected_digest1[1024] = {0}; + char expected_digest2[1024] = {0}; + char expected_digest3[1024] = {0}; + char expected_digest4[1024] = {0}; + char expected_digest5[1024] = {0}; + char expected_digest6[1024] = {0}; + char expected_digest7[1024] = {0}; + int i = 0; + + strcpy(expected_digest1, "d41d8cd98f00b204e9800998ecf8427e"); + strcpy(expected_digest2, "0cc175b9c0f1b6a831c399e269772661"); + strcpy(expected_digest3, "900150983cd24fb0d6963f7d28e17f72"); + strcpy(expected_digest4, "f96b697d7cb7938d525a2f31aaf161d0"); + strcpy(expected_digest5, "c3fcd3d76192e4007dfb496cca67e13b"); + strcpy(expected_digest6, "d174ab98d277d9f5a5611c2c9f419d9f"); + strcpy(expected_digest7, "57edf4a22be3c955ac49da2e2107b67a"); + + strcpy(msg, ""); + md5(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < MD5_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest1, MD5_DIGEST_LEN) == 0); + + strcpy(msg, "a"); + md5(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < MD5_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest2, MD5_DIGEST_LEN) == 0); + + strcpy(msg, "abc"); + md5(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < MD5_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest3, MD5_DIGEST_LEN) == 0); + + strcpy(msg, "message digest"); + md5(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < MD5_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest4, MD5_DIGEST_LEN) == 0); + strcpy(msg, "abcdefghijklmnopqrstuvwxyz"); + md5(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < MD5_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest5, MD5_DIGEST_LEN) == 0); + strcpy(msg, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"); + md5(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < MD5_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest6, MD5_DIGEST_LEN) == 0); + strcpy(msg, "12345678901234567890123456789012345678901234567890123456789012345678901234567890"); + md5(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < MD5_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest7, MD5_DIGEST_LEN) == 0); + +} + +DECLARE_UTEST(test_sha1, "sha1 test vectors") //http://www.di-mgt.com.au/sha_testvectors.html +{ + char msg[1024] = {0}; + unsigned char digest[1024] = {0}; + char digest_txt[1024] = {0}; + char expected_digest1[1024] = {0}; + char expected_digest2[1024] = {0}; + char expected_digest3[1024] = {0}; + char expected_digest4[1024] = {0}; + int i = 0; + + strcpy(msg, "abc"); + strcpy(expected_digest1, "a9993e364706816aba3e25717850c26c9cd0d89d"); + sha1(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA1_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest1, SHA1_DIGEST_LEN) == 0); + + strcpy(msg, ""); + strcpy(expected_digest2, "da39a3ee5e6b4b0d3255bfef95601890afd80709"); + sha1(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA1_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest2, SHA1_DIGEST_LEN) == 0); + + strcpy(msg, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); + strcpy(expected_digest3, "84983e441c3bd26ebaae4aa1f95129e5e54670f1"); + sha1(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA1_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest3, SHA1_DIGEST_LEN) == 0); + + strcpy(msg, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); + strcpy(expected_digest4, "a49b2446a02c645bf419f995b67091253a04a259"); + sha1(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA1_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest4, SHA1_DIGEST_LEN) == 0); + +} +DECLARE_UTEST(test_sha256, "sha-256 test vectors") //http://www.di-mgt.com.au/sha_testvectors.html +{ + char msg[1024] = {0}; + unsigned char digest[1024] = {0}; + char digest_txt[1024] = {0}; + char expected_digest1[1024] = {0}; + char expected_digest2[1024] = {0}; + char expected_digest3[1024] = {0}; + char expected_digest4[1024] = {0}; + int i = 0; + + strcpy(msg, "abc"); + strcpy(expected_digest1, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); + sha256(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA256_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest1, SHA256_DIGEST_LEN) == 0); + + strcpy(msg, ""); + strcpy(expected_digest2, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); + sha256(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA256_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest2, SHA256_DIGEST_LEN) == 0); + + strcpy(msg, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); + strcpy(expected_digest3, "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"); + sha256(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA256_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest3, SHA256_DIGEST_LEN) == 0); + + strcpy(msg, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); + strcpy(expected_digest4, "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1"); + sha256(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA256_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest4, SHA256_DIGEST_LEN) == 0); +} +DECLARE_UTEST(test_sha384, "sha-384 test vectors") //http://www.di-mgt.com.au/sha_testvectors.html +{ + char msg[1024] = {0}; + unsigned char digest[1024] = {0}; + char digest_txt[1024] = {0}; + char expected_digest1[1024] = {0}; + char expected_digest2[1024] = {0}; + char expected_digest3[1024] = {0}; + char expected_digest4[1024] = {0}; + int i = 0; + + strcpy(msg, "abc"); + strcpy(expected_digest1, "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7"); + sha384(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA384_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest1, SHA384_DIGEST_LEN) == 0); + + strcpy(msg, ""); + strcpy(expected_digest2, "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"); + sha384(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA384_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest2, SHA384_DIGEST_LEN) == 0); + + strcpy(msg, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); + strcpy(expected_digest3, "3391fdddfc8dc7393707a65b1b4709397cf8b1d162af05abfe8f450de5f36bc6b0455a8520bc4e6f5fe95b1fe3c8452b"); + sha384(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA384_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest3, SHA384_DIGEST_LEN) == 0); + + strcpy(msg, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); + strcpy(expected_digest4, "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039"); + sha384(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA384_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest4, SHA384_DIGEST_LEN) == 0); + +} +DECLARE_UTEST(test_sha512, "sha-512 test vectors") //http://www.di-mgt.com.au/sha_testvectors.html +{ + char msg[1024] = {0}; + unsigned char digest[1024] = {0}; + char digest_txt[1024] = {0}; + char expected_digest1[1024] = {0}; + char expected_digest2[1024] = {0}; + char expected_digest3[1024] = {0}; + char expected_digest4[1024] = {0}; + int i = 0; + + strcpy(msg, "abc"); + strcpy(expected_digest1, "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f"); + sha512(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA512_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest1, SHA512_DIGEST_LEN) == 0); + + strcpy(msg, ""); + strcpy(expected_digest2, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + sha512(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA512_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest2, SHA512_DIGEST_LEN) == 0); + + strcpy(msg, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); + strcpy(expected_digest3, "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445"); + sha512(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA512_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest3, SHA512_DIGEST_LEN) == 0); + + strcpy(msg, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); + strcpy(expected_digest4, "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"); + sha512(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA512_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest4, SHA512_DIGEST_LEN) == 0); + +} + +DECLARE_UTEST(test_sha3_256, "sha3_256 test vectors") //http://www.di-mgt.com.au/sha_testvectors.html +{ + char msg[1024] = {0}; + unsigned char digest[1024] = {0}; + char digest_txt[1024] = {0}; + char expected_digest1[1024] = {0}; + char expected_digest2[1024] = {0}; + char expected_digest3[1024] = {0}; + char expected_digest4[1024] = {0}; + int i = 0; + + strcpy(msg, "abc"); + strcpy(expected_digest1, "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532"); + sha3_256(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest1, SHA3_256_DIGEST_LEN) == 0); + + strcpy(msg, ""); + strcpy(expected_digest2, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"); + sha3_256(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest2, SHA3_256_DIGEST_LEN) == 0); + + strcpy(msg, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); + strcpy(expected_digest3, "41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376"); + sha3_256(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest3, SHA3_256_DIGEST_LEN) == 0); + + strcpy(msg, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); + strcpy(expected_digest4, "916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18"); + sha3_256(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest4, SHA3_256_DIGEST_LEN) == 0); + +} + +DECLARE_UTEST(test_sha3_512, "sha3_512 test vectors") //http://www.di-mgt.com.au/sha_testvectors.html +{ + char msg[1024] = {0}; + unsigned char digest[1024] = {0}; + char digest_txt[1024] = {0}; + char expected_digest1[1024] = {0}; + char expected_digest2[1024] = {0}; + char expected_digest3[1024] = {0}; + char expected_digest4[1024] = {0}; + int i = 0; + + strcpy(msg, "abc"); + strcpy(expected_digest1, "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0"); + sha3_512(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA3_512_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest1, SHA3_512_DIGEST_LEN) == 0); + + strcpy(msg, ""); + strcpy(expected_digest2, "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"); + sha3_512(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA3_512_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest2, SHA3_512_DIGEST_LEN) == 0); + + strcpy(msg, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); + strcpy(expected_digest3, "04a371e84ecfb5b8b77cb48610fca8182dd457ce6f326a0fd3d7ec2f1e91636dee691fbe0c985302ba1b0d8dc78c086346b533b49c030d99a27daf1139d6e75e"); + sha3_512(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA3_512_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest3, SHA3_512_DIGEST_LEN) == 0); + + strcpy(msg, "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); + strcpy(expected_digest4, "afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185"); + sha3_512(digest, (unsigned char *)msg, strlen(msg)); + for ( i = 0; i < SHA3_512_DIGEST_LEN; i++) + { + sprintf(digest_txt + (2 * i), "%02x", digest[i]); + } + CU_ASSERT(memcmp(digest_txt, expected_digest4, SHA3_512_DIGEST_LEN) == 0); + +} + +int register_ts_digest_test(void) +{ + ts_init(&TEST_SUITE(digest_test), TEST_SUITE_DESCR(digest_test), NULL, NULL); + ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_md5), UTEST_DESCR(test_md5)); + ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_sha1), UTEST_DESCR(test_sha1)); + ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_sha256), UTEST_DESCR(test_sha256)); + ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_sha384), UTEST_DESCR(test_sha384)); + ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_sha512), UTEST_DESCR(test_sha512)); + ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_sha3_256), UTEST_DESCR(test_sha3_256)); + ts_add_utest(&TEST_SUITE(digest_test), UTEST_FCT(test_sha3_512), UTEST_DESCR(test_sha3_512)); + + return register_ts(&TEST_SUITE(digest_test)); +} + +#endif /* HAVE_C_UNIT_TESTS */ /***EOF***/ diff --git a/lib/fko.h b/lib/fko.h index 6b49afae..8824b2d4 100644 --- a/lib/fko.h +++ b/lib/fko.h @@ -1398,6 +1398,10 @@ DLL_API int fko_gpg_signature_fpr_match(fko_ctx_t ctx, const char * const fpr, #ifdef HAVE_C_UNIT_TESTS int register_ts_fko_decode(void); +int register_ts_hmac_test(void); +int register_ts_digest_test(void); +int register_ts_aes_test(void); + #endif #endif /* FKO_H */ diff --git a/lib/fko_utests.c b/lib/fko_utests.c index 6312d2db..22b8b339 100755 --- a/lib/fko_utests.c +++ b/lib/fko_utests.c @@ -4,13 +4,16 @@ /** * Register test suites from FKO files. - * + * * The module should fetch functions according to used modules. All of them follow the same * naming convention. */ static void register_test_suites(void) { register_ts_fko_decode(); + register_ts_hmac_test(); + register_ts_digest_test(); + register_ts_aes_test(); } /* The main() function for setting up and running the tests. diff --git a/lib/hmac.c b/lib/hmac.c index efc7a968..1dd5d60c 100644 --- a/lib/hmac.c +++ b/lib/hmac.c @@ -30,7 +30,9 @@ */ #include "hmac.h" - +#ifdef HAVE_C_UNIT_TESTS +DECLARE_TEST_SUITE(hmac_test, "hmac functions test suite"); +#endif typedef struct { MD5Context ctx_inside; MD5Context ctx_outside; @@ -514,3 +516,1096 @@ hmac_sha3_512(const char *msg, const unsigned int msg_len, free(padded_msg); } + +#ifdef HAVE_C_UNIT_TESTS + +DECLARE_UTEST(test_hmac_md5, "hmac_md5 test vectors") // https://tools.ietf.org/html/rfc2202 +{ + char msg[1024] = {0}; + unsigned char hmac[1024] = {0}; + char hmac_txt[1024] = {0}; + char hmac_key[1024] = {0}; + char expected_hmac1[1024] = {0}; + char expected_hmac2[1024] = {0}; + char expected_hmac3[1024] = {0}; + char expected_hmac4[1024] = {0}; + char expected_hmac5[1024] = {0}; + char expected_hmac6[1024] = {0}; + char expected_hmac7[1024] = {0}; + int msg_len, key_len; + int i = 0; + + //vector 1 + for ( i = 0; i < 16; i++) + { + hmac_key[i] = 0x0b; + } + key_len = 16; + strcpy(msg, "Hi There"); + msg_len = 8; + strcpy(expected_hmac1, "9294727a3638bb1c13f48ef8158bfc9d"); + + hmac_md5(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < MD5_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac1, MD5_DIGEST_LEN) == 0); + + //vector 2 + strcpy(hmac_key, "Jefe"); + key_len = 4; + strcpy(msg, "what do ya want for nothing?"); + msg_len = 28; + strcpy(expected_hmac2, "750c783e6ab0b503eaa86e310a5db738"); + + hmac_md5(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac2, MD5_DIGEST_LEN) == 0); + + //vector 3 + for ( i = 0; i < 16; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 16; + for ( i = 0; i < 50; i++) + { + msg[i] = 0xdd; + } + msg_len = 50; + strcpy(expected_hmac3, "56be34521d144c88dbb8c733f0e8b3f6"); + + hmac_md5(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac3, MD5_DIGEST_LEN) == 0); + + //vector 4 + strcpy(hmac_key, "\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"); + key_len = 25; + for ( i = 0; i < 50; i++) + { + msg[i] = 0xcd; + } + msg_len = 50; + strcpy(expected_hmac4, "697eaf0aca3a3aea3a75164746ffaa79"); + + hmac_md5(msg, 50, (unsigned char *)hmac, hmac_key, strlen(hmac_key)); + + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac4, MD5_DIGEST_LEN) == 0); + + //vector 5 + for ( i = 0; i < 16; i++) + { + hmac_key[i] = 0x0c; + } + key_len = 16; + strcpy(msg, "Test With Truncation"); + msg_len = 20; + strcpy(expected_hmac5, "56461ef2342edc00f9bab995690efd4c"); + + hmac_md5(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac5, MD5_DIGEST_LEN) == 0); + + //vector 6 + for ( i = 0; i < 80; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 80; + strcpy(msg, "Test Using Larger Than Block-Size Key - Hash Key First"); + msg_len = 54; + strcpy(expected_hmac6, "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd"); + + hmac_md5(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac6, MD5_DIGEST_LEN) == 0); + + //vector 7 + for ( i = 0; i < 80; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 80; + strcpy(msg, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"); + msg_len = 73; + strcpy(expected_hmac7, "6f630fad67cda0ee1fb1f562db3aa53e"); + + hmac_md5(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac7, MD5_DIGEST_LEN) == 0); + +} + +DECLARE_UTEST(test_hmac_sha1, "hmac_sha1 test vectors") // https://tools.ietf.org/html/rfc2202 +{ + char msg[1024] = {0}; + unsigned char hmac[1024] = {0}; + char hmac_txt[1024] = {0}; + char hmac_key[1024] = {0}; + char expected_hmac1[1024] = {0}; + char expected_hmac2[1024] = {0}; + char expected_hmac3[1024] = {0}; + char expected_hmac4[1024] = {0}; + char expected_hmac5[1024] = {0}; + char expected_hmac6[1024] = {0}; + char expected_hmac7[1024] = {0}; + int msg_len, key_len; + int i = 0; + + //vector 1 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0x0b; + } + key_len = 20; + strcpy(msg, "Hi There"); + msg_len = 8; + strcpy(expected_hmac1, "b617318655057264e28bc0b6fb378c8ef146be00"); + + hmac_sha1(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA1_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac1, SHA1_DIGEST_LEN) == 0); + + //vector 2 + strcpy(hmac_key, "Jefe"); + key_len = 4; + strcpy(msg, "what do ya want for nothing?"); + msg_len = 28; + strcpy(expected_hmac2, "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79"); + + hmac_sha1(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA1_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac2, SHA1_DIGEST_LEN) == 0); + + //vector 3 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 20; + for ( i = 0; i < 50; i++) + { + msg[i] = 0xdd; + } + msg_len = 50; + strcpy(expected_hmac3, "125d7342b9ac11cd91a39af48aa17b4f63f175d3"); + + hmac_sha1(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA1_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac3, SHA1_DIGEST_LEN) == 0); + + //vector 4 + strcpy(hmac_key, "\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"); + key_len = 25; + for ( i = 0; i < 50; i++) + { + msg[i] = 0xcd; + } + msg_len = 50; + strcpy(expected_hmac4, "4c9007f4026250c6bc8414f9bf50c86c2d7235da"); + + hmac_sha1(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA1_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac4, SHA1_DIGEST_LEN) == 0); + + //vector 5 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0x0c; + } + key_len = 20; + strcpy(msg, "Test With Truncation"); + msg_len = 20; + strcpy(expected_hmac5, "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04"); + + hmac_sha1(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA1_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac5, SHA1_DIGEST_LEN) == 0); + + //vector 6 + for ( i = 0; i < 80; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 80; + strcpy(msg, "Test Using Larger Than Block-Size Key - Hash Key First"); + msg_len = 54; + strcpy(expected_hmac6, "aa4ae5e15272d00e95705637ce8a3b55ed402112"); + + hmac_sha1(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA1_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac6, SHA1_DIGEST_LEN) == 0); + + //vector 7 + for ( i = 0; i < 80; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 80; + strcpy(msg, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"); + msg_len = 73; + strcpy(expected_hmac7, "e8e99d0f45237d786d6bbaa7965c7808bbff1a91"); + + hmac_sha1(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA1_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac7, SHA1_DIGEST_LEN) == 0); +} + +DECLARE_UTEST(test_hmac_sha256, "hmac_sha256 test vectors") // https://tools.ietf.org/html/rfc4231 +{ + char msg[1024] = {0}; + unsigned char hmac[1024] = {0}; + char hmac_txt[1024] = {0}; + char hmac_key[1024] = {0}; + char expected_hmac1[1024] = {0}; + char expected_hmac2[1024] = {0}; + char expected_hmac3[1024] = {0}; + char expected_hmac4[1024] = {0}; + char expected_hmac5[1024] = {0}; + char expected_hmac6[1024] = {0}; + char expected_hmac7[1024] = {0}; + int msg_len, key_len; + int i = 0; + + //vector 1 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0x0b; + } + key_len = 20; + strcpy(msg, "Hi There"); + msg_len = 8; + strcpy(expected_hmac1, "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"); + + hmac_sha256(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac1, SHA256_DIGEST_LEN) == 0); + + //vector 2 + strcpy(hmac_key, "Jefe"); + key_len = 4; + strcpy(msg, "what do ya want for nothing?"); + msg_len = 28; + strcpy(expected_hmac2, "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"); + + hmac_sha256(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac2, SHA256_DIGEST_LEN) == 0); + + //vector 3 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 20; + for ( i = 0; i < 50; i++) + { + msg[i] = 0xdd; + } + msg_len = 50; + strcpy(expected_hmac3, "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe"); + + hmac_sha256(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac3, SHA256_DIGEST_LEN) == 0); + + //vector 4 + strcpy(hmac_key, "\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"); + key_len = 25; + for ( i = 0; i < 50; i++) + { + msg[i] = 0xcd; + } + msg_len = 50; + strcpy(expected_hmac4, "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b"); + + hmac_sha256(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac4, SHA256_DIGEST_LEN) == 0); + + //vector 5 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0x0c; + } + key_len = 20; + strcpy(msg, "Test With Truncation"); + msg_len = 20; + strcpy(expected_hmac5, "a3b6167473100ee06e0c796c2955552b"); + + hmac_sha256(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < 16; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac5, 16) == 0); //test specifies truncated output + + //vector 6 + for ( i = 0; i < 131; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 131; + strcpy(msg, "Test Using Larger Than Block-Size Key - Hash Key First"); + msg_len = 54; + strcpy(expected_hmac6, "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54"); + + hmac_sha256(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac6, SHA256_DIGEST_LEN) == 0); + + //vector 7 + for ( i = 0; i < 131; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 131; + strcpy(msg, "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."); + msg_len = strlen(msg); + strcpy(expected_hmac7, "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"); + + hmac_sha256(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac7, SHA256_DIGEST_LEN) == 0); +} + +DECLARE_UTEST(test_hmac_sha384, "hmac_sha384 test vectors") +{ + char msg[1024] = {0}; + unsigned char hmac[1024] = {0}; + char hmac_txt[1024] = {0}; + char hmac_key[1024] = {0}; + char expected_hmac1[1024] = {0}; + char expected_hmac2[1024] = {0}; + char expected_hmac3[1024] = {0}; + char expected_hmac4[1024] = {0}; + char expected_hmac5[1024] = {0}; + char expected_hmac6[1024] = {0}; + char expected_hmac7[1024] = {0}; + int msg_len, key_len; + int i = 0; + + //vector 1 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0x0b; + } + key_len = 20; + strcpy(msg, "Hi There"); + msg_len = 8; + strcpy(expected_hmac1, "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6"); + + hmac_sha384(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA384_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac1, SHA384_DIGEST_LEN) == 0); + + //vector 2 + strcpy(hmac_key, "Jefe"); + key_len = 4; + strcpy(msg, "what do ya want for nothing?"); + msg_len = 28; + strcpy(expected_hmac2, "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649"); + + hmac_sha384(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA384_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac2, SHA384_DIGEST_LEN) == 0); + + //vector 3 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 20; + for ( i = 0; i < 50; i++) + { + msg[i] = 0xdd; + } + msg_len = 50; + strcpy(expected_hmac3, "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27"); + + hmac_sha384(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA384_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac3, SHA384_DIGEST_LEN) == 0); + + //vector 4 + strcpy(hmac_key, "\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"); + key_len = 25; + for ( i = 0; i < 50; i++) + { + msg[i] = 0xcd; + } + msg_len = 50; + strcpy(expected_hmac4, "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb"); + + hmac_sha384(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA384_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac4, SHA384_DIGEST_LEN) == 0); + + //vector 5 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0x0c; + } + key_len = 20; + strcpy(msg, "Test With Truncation"); + msg_len = 20; + strcpy(expected_hmac5, "3abf34c3503b2a23a46efc619baef897"); + + hmac_sha384(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < 16; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac5, 16) == 0); //test specifies truncated output + + //vector 6 + for ( i = 0; i < 131; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 131; + strcpy(msg, "Test Using Larger Than Block-Size Key - Hash Key First"); + msg_len = 54; + strcpy(expected_hmac6, "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4030fe8296248df163f44952"); + + hmac_sha384(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA384_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac6, SHA384_DIGEST_LEN) == 0); + + //vector 7 + for ( i = 0; i < 131; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 131; + strcpy(msg, "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."); + msg_len = strlen(msg); + strcpy(expected_hmac7, "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e799176d3860e6110c46523e"); + + hmac_sha384(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA384_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac7, SHA384_DIGEST_LEN) == 0); +} + +DECLARE_UTEST(test_hmac_sha512, "hmac_sha512 test vectors") +{ + char msg[1024] = {0}; + unsigned char hmac[1024] = {0}; + char hmac_txt[1024] = {0}; + char hmac_key[1024] = {0}; + char expected_hmac1[1024] = {0}; + char expected_hmac2[1024] = {0}; + char expected_hmac3[1024] = {0}; + char expected_hmac4[1024] = {0}; + char expected_hmac5[1024] = {0}; + char expected_hmac6[1024] = {0}; + char expected_hmac7[1024] = {0}; + int msg_len, key_len; + int i = 0; + + //vector 1 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0x0b; + } + key_len = 20; + strcpy(msg, "Hi There"); + msg_len = 8; + strcpy(expected_hmac1, "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854"); + + hmac_sha512(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA512_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac1, SHA512_DIGEST_LEN) == 0); + + //vector 2 + strcpy(hmac_key, "Jefe"); + key_len = 4; + strcpy(msg, "what do ya want for nothing?"); + msg_len = 28; + strcpy(expected_hmac2, "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737"); + + hmac_sha512(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA512_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac2, SHA512_DIGEST_LEN) == 0); + + //vector 3 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 20; + for ( i = 0; i < 50; i++) + { + msg[i] = 0xdd; + } + msg_len = 50; + strcpy(expected_hmac3, "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb"); + + hmac_sha512(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA512_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac3, SHA512_DIGEST_LEN) == 0); + + //vector 4 + strcpy(hmac_key, "\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"); + key_len = 25; + for ( i = 0; i < 50; i++) + { + msg[i] = 0xcd; + } + msg_len = 50; + strcpy(expected_hmac4, "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd"); + + hmac_sha512(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA512_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac4, SHA512_DIGEST_LEN) == 0); + + //vector 5 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0x0c; + } + key_len = 20; + strcpy(msg, "Test With Truncation"); + msg_len = 20; + strcpy(expected_hmac5, "415fad6271580a531d4179bc891d87a6"); + + hmac_sha512(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < 16; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac5, 16) == 0); //test specifies truncated output + + //vector 6 + for ( i = 0; i < 131; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 131; + strcpy(msg, "Test Using Larger Than Block-Size Key - Hash Key First"); + msg_len = 54; + strcpy(expected_hmac6, "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598"); + + hmac_sha512(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA512_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac6, SHA512_DIGEST_LEN) == 0); + + //vector 7 + for ( i = 0; i < 131; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 131; + strcpy(msg, "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."); + msg_len = strlen(msg); + strcpy(expected_hmac7, "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"); + + hmac_sha512(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA512_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac7, SHA512_DIGEST_LEN) == 0); +} + +DECLARE_UTEST(test_hmac_sha3_256, "hmac_sha3_256 test vectors") //http://wolfgang-ehrhardt.de/hmac-sha3-testvectors.html +{ + char msg[1024] = {0}; + unsigned char hmac[1024] = {0}; + char hmac_txt[1024] = {0}; + char hmac_key[1024] = {0}; + char expected_hmac1[1024] = {0}; + char expected_hmac2[1024] = {0}; + char expected_hmac3[1024] = {0}; + char expected_hmac4[1024] = {0}; + char expected_hmac5[1024] = {0}; + char expected_hmac6[1024] = {0}; + char expected_hmac6a[1024] = {0}; + char expected_hmac7[1024] = {0}; + char expected_hmac7a[1024] = {0}; + int msg_len, key_len; + int i = 0; + + //vector 1 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0x0b; + } + key_len = 20; + strcpy(msg, "Hi There"); + msg_len = 8; + strcpy(expected_hmac1, "ba85192310dffa96e2a3a40e69774351140bb7185e1202cdcc917589f95e16bb"); + + hmac_sha3_256(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac1, SHA3_256_DIGEST_LEN) == 0); + + //vector 2 + strcpy(hmac_key, "Jefe"); + key_len = 4; + strcpy(msg, "what do ya want for nothing?"); + msg_len = 28; + strcpy(expected_hmac2, "c7d4072e788877ae3596bbb0da73b887c9171f93095b294ae857fbe2645e1ba5"); + + hmac_sha3_256(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac2, SHA3_256_DIGEST_LEN) == 0); + + //vector 3 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 20; + for ( i = 0; i < 50; i++) + { + msg[i] = 0xdd; + } + msg_len = 50; + strcpy(expected_hmac3, "84ec79124a27107865cedd8bd82da9965e5ed8c37b0ac98005a7f39ed58a4207"); + + hmac_sha3_256(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac3, SHA3_256_DIGEST_LEN) == 0); + + //vector 4 + strcpy(hmac_key, "\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"); + key_len = 25; + for ( i = 0; i < 50; i++) + { + msg[i] = 0xcd; + } + msg_len = 50; + strcpy(expected_hmac4, "57366a45e2305321a4bc5aa5fe2ef8a921f6af8273d7fe7be6cfedb3f0aea6d7"); + + hmac_sha3_256(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac4, SHA3_256_DIGEST_LEN) == 0); + + //vector 5 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0x0c; + } + key_len = 20; + strcpy(msg, "Test With Truncation"); + msg_len = 20; + strcpy(expected_hmac5, "6e02c64537fb118057abb7fb66a23b3c"); + + hmac_sha3_256(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac5, 16) == 0); //test specifies truncated output + + //vector 6 + for ( i = 0; i < 131; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 131; + strcpy(msg, "Test Using Larger Than Block-Size Key - Hash Key First"); + msg_len = 54; + strcpy(expected_hmac6, "ed73a374b96c005235f948032f09674a58c0ce555cfc1f223b02356560312c3b"); + + hmac_sha3_256(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac6, SHA3_256_DIGEST_LEN) == 0); + + //vector 6a + for ( i = 0; i < 147; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 147; + strcpy(msg, "Test Using Larger Than Block-Size Key - Hash Key First"); + msg_len = 54; + strcpy(expected_hmac6a, "a6072f86de52b38bb349fe84cd6d97fb6a37c4c0f62aae93981193a7229d3467"); + + hmac_sha3_256(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac6a, SHA3_256_DIGEST_LEN) == 0); + + //vector 7 + for ( i = 0; i < 131; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 131; + strcpy(msg, "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."); + msg_len = strlen(msg); + strcpy(expected_hmac7, "65c5b06d4c3de32a7aef8763261e49adb6e2293ec8e7c61e8de61701fc63e123"); + + hmac_sha3_256(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac7, SHA3_256_DIGEST_LEN) == 0); + + //vector 7a + for ( i = 0; i < 147; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 147; + strcpy(msg, "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."); + msg_len = strlen(msg); + strcpy(expected_hmac7a, "e6a36d9b915f86a093cac7d110e9e04cf1d6100d30475509c2475f571b758b5a"); + + hmac_sha3_256(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_256_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac7a, SHA3_256_DIGEST_LEN) == 0); +} + +DECLARE_UTEST(test_hmac_sha3_512, "hmac_sha3_512 test vectors") +{ + char msg[1024] = {0}; + unsigned char hmac[1024] = {0}; + char hmac_txt[1024] = {0}; + char hmac_key[1024] = {0}; + char expected_hmac1[1024] = {0}; + char expected_hmac2[1024] = {0}; + char expected_hmac3[1024] = {0}; + char expected_hmac4[1024] = {0}; + char expected_hmac5[1024] = {0}; + char expected_hmac6[1024] = {0}; + char expected_hmac6a[1024] = {0}; + char expected_hmac7[1024] = {0}; + char expected_hmac7a[1024] = {0}; + int msg_len, key_len; + int i = 0; + + //vector 1 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0x0b; + } + key_len = 20; + strcpy(msg, "Hi There"); + msg_len = 8; + strcpy(expected_hmac1, "eb3fbd4b2eaab8f5c504bd3a41465aacec15770a7cabac531e482f860b5ec7ba47ccb2c6f2afce8f88d22b6dc61380f23a668fd3888bb80537c0a0b86407689e"); + + hmac_sha3_512(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_512_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac1, SHA3_512_DIGEST_LEN) == 0); + + //vector 2 + strcpy(hmac_key, "Jefe"); + key_len = 4; + strcpy(msg, "what do ya want for nothing?"); + msg_len = 28; + strcpy(expected_hmac2, "5a4bfeab6166427c7a3647b747292b8384537cdb89afb3bf5665e4c5e709350b287baec921fd7ca0ee7a0c31d022a95e1fc92ba9d77df883960275beb4e62024"); + + hmac_sha3_512(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_512_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac2, SHA3_512_DIGEST_LEN) == 0); + + //vector 3 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 20; + for ( i = 0; i < 50; i++) + { + msg[i] = 0xdd; + } + msg_len = 50; + strcpy(expected_hmac3, "309e99f9ec075ec6c6d475eda1180687fcf1531195802a99b5677449a8625182851cb332afb6a89c411325fbcbcd42afcb7b6e5aab7ea42c660f97fd8584bf03"); + + hmac_sha3_512(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_512_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac3, SHA3_512_DIGEST_LEN) == 0); + + //vector 4 + strcpy(hmac_key, "\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"); + key_len = 25; + for ( i = 0; i < 50; i++) + { + msg[i] = 0xcd; + } + msg_len = 50; + strcpy(expected_hmac4, "b27eab1d6e8d87461c29f7f5739dd58e98aa35f8e823ad38c5492a2088fa0281993bbfff9a0e9c6bf121ae9ec9bb09d84a5ebac817182ea974673fb133ca0d1d"); + + hmac_sha3_512(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_512_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac4, SHA3_512_DIGEST_LEN) == 0); + + //vector 5 + for ( i = 0; i < 20; i++) + { + hmac_key[i] = 0x0c; + } + key_len = 20; + strcpy(msg, "Test With Truncation"); + msg_len = 20; + strcpy(expected_hmac5, "0fa7475948f43f48ca0516671e18978c"); + + hmac_sha3_512(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < 16; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac5, 16) == 0); //test specifies truncated output + + //vector 6 + for ( i = 0; i < 131; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 131; + strcpy(msg, "Test Using Larger Than Block-Size Key - Hash Key First"); + msg_len = 54; + strcpy(expected_hmac6, "00f751a9e50695b090ed6911a4b65524951cdc15a73a5d58bb55215ea2cd839ac79d2b44a39bafab27e83fde9e11f6340b11d991b1b91bf2eee7fc872426c3a4"); + + hmac_sha3_512(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_512_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac6, SHA3_512_DIGEST_LEN) == 0); + + //vector 6a + for ( i = 0; i < 147; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 147; + strcpy(msg, "Test Using Larger Than Block-Size Key - Hash Key First"); + msg_len = 54; + strcpy(expected_hmac6a, "b14835c819a290efb010ace6d8568dc6b84de60bc49b004c3b13eda763589451e5dd74292884d1bdce64e6b919dd61dc9c56a282a81c0bd14f1f365b49b83a5b"); + + hmac_sha3_512(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_512_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac6a, SHA3_512_DIGEST_LEN) == 0); + + //vector 7 + for ( i = 0; i < 131; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 131; + strcpy(msg, "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."); + msg_len = strlen(msg); + strcpy(expected_hmac7, "38a456a004bd10d32c9ab8336684112862c3db61adcca31829355eaf46fd5c73d06a1f0d13fec9a652fb3811b577b1b1d1b9789f97ae5b83c6f44dfcf1d67eba"); + + hmac_sha3_512(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_512_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac7, SHA3_512_DIGEST_LEN) == 0); + + //vector 7a + for ( i = 0; i < 147; i++) + { + hmac_key[i] = 0xaa; + } + key_len = 147; + strcpy(msg, "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."); + msg_len = strlen(msg); + strcpy(expected_hmac7a, "dc030ee7887034f32cf402df34622f311f3e6cf04860c6bbd7fa488674782b4659fdbdf3fd877852885cfe6e22185fe7b2ee952043629bc9d5f3298a41d02c66"); + + hmac_sha3_512(msg, msg_len, (unsigned char *)hmac, hmac_key, key_len); + + for ( i = 0; i < SHA3_512_DIGEST_LEN; i++) + { + sprintf(hmac_txt + (2 * i), "%02x", hmac[i]); + } + CU_ASSERT(memcmp(hmac_txt, expected_hmac7a, SHA3_512_DIGEST_LEN) == 0); +} + +int register_ts_hmac_test(void) +{ + ts_init(&TEST_SUITE(hmac_test), TEST_SUITE_DESCR(hmac_test), NULL, NULL); + ts_add_utest(&TEST_SUITE(hmac_test), UTEST_FCT(test_hmac_md5), UTEST_DESCR(test_hmac_md5)); + ts_add_utest(&TEST_SUITE(hmac_test), UTEST_FCT(test_hmac_sha1), UTEST_DESCR(test_hmac_sha1)); + ts_add_utest(&TEST_SUITE(hmac_test), UTEST_FCT(test_hmac_sha256), UTEST_DESCR(test_hmac_sha256)); + ts_add_utest(&TEST_SUITE(hmac_test), UTEST_FCT(test_hmac_sha384), UTEST_DESCR(test_hmac_sha384)); + ts_add_utest(&TEST_SUITE(hmac_test), UTEST_FCT(test_hmac_sha512), UTEST_DESCR(test_hmac_sha512)); + ts_add_utest(&TEST_SUITE(hmac_test), UTEST_FCT(test_hmac_sha3_256), UTEST_DESCR(test_hmac_sha3_256)); + ts_add_utest(&TEST_SUITE(hmac_test), UTEST_FCT(test_hmac_sha3_512), UTEST_DESCR(test_hmac_sha3_512)); + + return register_ts(&TEST_SUITE(hmac_test)); +} + +#endif /* HAVE_C_UNIT_TESTS */ From 2edbc04bc7b5a5b3d5100c0f27bbbe4423d3ceda Mon Sep 17 00:00:00 2001 From: Jonathan Bennett Date: Mon, 21 Dec 2015 10:49:09 -0600 Subject: [PATCH 3/3] properly handle longer HMAC keys for hmac_sha384 and hmac_sha512 --- lib/hmac.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/lib/hmac.c b/lib/hmac.c index 1dd5d60c..52a36b0e 100644 --- a/lib/hmac.c +++ b/lib/hmac.c @@ -320,10 +320,16 @@ hmac_sha384_init(hmac_sha384_ctx *ctx, const char *key, const int key_len) if(key_len > MAX_DIGEST_BLOCK_LEN) final_len = MAX_DIGEST_BLOCK_LEN; - /* When we eventually support arbitrary key sizes, take the digest - * of the key with: sha384(final_key, init_key, final_len); - */ - memcpy(final_key, key, final_len); + if(SHA384_BLOCK_LEN < key_len) + { + /* Calculate the digest of the key + */ + sha384(final_key, (unsigned char *)key, final_len); + } + else + { + memcpy(final_key, key, key_len); + } pad_init(ctx->block_inner_pad, ctx->block_outer_pad, final_key, final_len); @@ -382,10 +388,17 @@ hmac_sha512_init(hmac_sha512_ctx *ctx, const char *key, const int key_len) if(key_len > MAX_DIGEST_BLOCK_LEN) final_len = MAX_DIGEST_BLOCK_LEN; - /* When we eventually support arbitrary key sizes, take the digest - * of the key with: sha512(final_key, init_key, final_len); - */ - memcpy(final_key, key, final_len); + if(SHA512_BLOCK_LEN < key_len) + { + /* Calculate the digest of the key + */ + sha512(final_key, (unsigned char *)key, final_len); + final_len = SHA512_DIGEST_LEN; + } + else + { + memcpy(final_key, key, key_len); + } pad_init(ctx->block_inner_pad, ctx->block_outer_pad, final_key, final_len);