From c98857a47e55b8dc6e6bc2b883587a37f3c97a2d Mon Sep 17 00:00:00 2001 From: RyanC Date: Sun, 11 Nov 2012 15:00:19 -0800 Subject: [PATCH 01/10] add hkdf impl --- libtomcrypt.dsp | 5 ++ libtomcrypt_VS2005.vcproj | 22 +++++++ libtomcrypt_VS2008.vcproj | 22 +++++++ makefile | 3 +- makefile.icc | 3 +- makefile.msvc | 3 +- makefile.shared | 3 +- makefile.unix | 3 +- src/headers/tomcrypt.h | 1 + src/headers/tomcrypt_custom.h | 7 +++ src/headers/tomcrypt_hkdf.h | 26 ++++++++ src/misc/hkdf/hkdf.c | 113 ++++++++++++++++++++++++++++++++++ 12 files changed, 206 insertions(+), 5 deletions(-) create mode 100644 src/headers/tomcrypt_hkdf.h create mode 100644 src/misc/hkdf/hkdf.c diff --git a/libtomcrypt.dsp b/libtomcrypt.dsp index a6dbe7a..83b4af9 100644 --- a/libtomcrypt.dsp +++ b/libtomcrypt.dsp @@ -825,6 +825,11 @@ SOURCE=.\src\misc\error_to_string.c SOURCE=.\src\misc\zeromem.c # End Source File # End Group +# Begin Source File + +SOURCE=.\src\misc\hkdf\hkdf.c +# End Source File +# End Group # Begin Group "modes" # PROP Default_Filter "" diff --git a/libtomcrypt_VS2005.vcproj b/libtomcrypt_VS2005.vcproj index 6a93fa2..9eeb4f8 100644 --- a/libtomcrypt_VS2005.vcproj +++ b/libtomcrypt_VS2005.vcproj @@ -2954,6 +2954,28 @@ /> + + + + + + + + diff --git a/libtomcrypt_VS2008.vcproj b/libtomcrypt_VS2008.vcproj index a854068..3e1e851 100644 --- a/libtomcrypt_VS2008.vcproj +++ b/libtomcrypt_VS2008.vcproj @@ -2946,6 +2946,28 @@ /> + + + + + + + + diff --git a/makefile b/makefile index f2d54a9..e9ef4e6 100644 --- a/makefile +++ b/makefile @@ -156,7 +156,8 @@ src/misc/crypt/crypt_prng_is_valid.o src/misc/crypt/crypt_register_cipher.o \ src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o \ src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \ src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/pkcs5/pkcs_5_1.o \ -src/misc/pkcs5/pkcs_5_2.o src/misc/zeromem.o src/modes/cbc/cbc_decrypt.o src/modes/cbc/cbc_done.o \ +src/misc/pkcs5/pkcs_5_2.o src/misc/zeromem.o src/misc/hkdf/hkdf.o \ +src/modes/cbc/cbc_decrypt.o src/modes/cbc/cbc_done.o \ src/modes/cbc/cbc_encrypt.o src/modes/cbc/cbc_getiv.o src/modes/cbc/cbc_setiv.o \ src/modes/cbc/cbc_start.o src/modes/cfb/cfb_decrypt.o src/modes/cfb/cfb_done.o \ src/modes/cfb/cfb_encrypt.o src/modes/cfb/cfb_getiv.o src/modes/cfb/cfb_setiv.o \ diff --git a/makefile.icc b/makefile.icc index 35be3d6..71bb112 100644 --- a/makefile.icc +++ b/makefile.icc @@ -141,7 +141,8 @@ src/misc/crypt/crypt_prng_is_valid.o src/misc/crypt/crypt_register_cipher.o \ src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o \ src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \ src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/pkcs5/pkcs_5_1.o \ -src/misc/pkcs5/pkcs_5_2.o src/misc/zeromem.o src/modes/cbc/cbc_decrypt.o src/modes/cbc/cbc_done.o \ +src/misc/pkcs5/pkcs_5_2.o src/misc/zeromem.o src/misc/hkdf/hkdf.o \ +src/modes/cbc/cbc_decrypt.o src/modes/cbc/cbc_done.o \ src/modes/cbc/cbc_encrypt.o src/modes/cbc/cbc_getiv.o src/modes/cbc/cbc_setiv.o \ src/modes/cbc/cbc_start.o src/modes/cfb/cfb_decrypt.o src/modes/cfb/cfb_done.o \ src/modes/cfb/cfb_encrypt.o src/modes/cfb/cfb_getiv.o src/modes/cfb/cfb_setiv.o \ diff --git a/makefile.msvc b/makefile.msvc index 8b4892a..a0ffe6a 100644 --- a/makefile.msvc +++ b/makefile.msvc @@ -51,7 +51,8 @@ src/misc/crypt/crypt_prng_is_valid.obj src/misc/crypt/crypt_register_cipher.obj src/misc/crypt/crypt_register_hash.obj src/misc/crypt/crypt_register_prng.obj \ src/misc/crypt/crypt_unregister_cipher.obj src/misc/crypt/crypt_unregister_hash.obj \ src/misc/crypt/crypt_unregister_prng.obj src/misc/error_to_string.obj src/misc/pkcs5/pkcs_5_1.obj \ -src/misc/pkcs5/pkcs_5_2.obj src/misc/zeromem.obj src/modes/cbc/cbc_decrypt.obj src/modes/cbc/cbc_done.obj \ +src/misc/pkcs5/pkcs_5_2.obj src/misc/zeromem.obj src/misc/hkdf/hkdf.obj \ +src/modes/cbc/cbc_decrypt.obj src/modes/cbc/cbc_done.obj \ src/modes/cbc/cbc_encrypt.obj src/modes/cbc/cbc_getiv.obj src/modes/cbc/cbc_setiv.obj \ src/modes/cbc/cbc_start.obj src/modes/cfb/cfb_decrypt.obj src/modes/cfb/cfb_done.obj \ src/modes/cfb/cfb_encrypt.obj src/modes/cfb/cfb_getiv.obj src/modes/cfb/cfb_setiv.obj \ diff --git a/makefile.shared b/makefile.shared index 97012ee..2848c36 100644 --- a/makefile.shared +++ b/makefile.shared @@ -146,7 +146,8 @@ src/misc/crypt/crypt_prng_is_valid.o src/misc/crypt/crypt_register_cipher.o \ src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o \ src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \ src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/pkcs5/pkcs_5_1.o \ -src/misc/pkcs5/pkcs_5_2.o src/misc/zeromem.o src/modes/cbc/cbc_decrypt.o src/modes/cbc/cbc_done.o \ +src/misc/pkcs5/pkcs_5_2.o src/misc/zeromem.o src/misc/hkdf/hkdf.o \ +src/modes/cbc/cbc_decrypt.o src/modes/cbc/cbc_done.o \ src/modes/cbc/cbc_encrypt.o src/modes/cbc/cbc_getiv.o src/modes/cbc/cbc_setiv.o \ src/modes/cbc/cbc_start.o src/modes/cfb/cfb_decrypt.o src/modes/cfb/cfb_done.o \ src/modes/cfb/cfb_encrypt.o src/modes/cfb/cfb_getiv.o src/modes/cfb/cfb_setiv.o \ diff --git a/makefile.unix b/makefile.unix index 792c1f3..53882e2 100644 --- a/makefile.unix +++ b/makefile.unix @@ -87,7 +87,8 @@ src/misc/crypt/crypt_prng_is_valid.o src/misc/crypt/crypt_register_cipher.o \ src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o \ src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \ src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/pkcs5/pkcs_5_1.o \ -src/misc/pkcs5/pkcs_5_2.o src/misc/zeromem.o src/modes/cbc/cbc_decrypt.o src/modes/cbc/cbc_done.o \ +src/misc/pkcs5/pkcs_5_2.o src/misc/zeromem.o src/misc/hkdf/hkdf.o \ +src/modes/cbc/cbc_decrypt.o src/modes/cbc/cbc_done.o \ src/modes/cbc/cbc_encrypt.o src/modes/cbc/cbc_getiv.o src/modes/cbc/cbc_setiv.o \ src/modes/cbc/cbc_start.o src/modes/cfb/cfb_decrypt.o src/modes/cfb/cfb_done.o \ src/modes/cfb/cfb_encrypt.o src/modes/cfb/cfb_getiv.o src/modes/cfb/cfb_setiv.o \ diff --git a/src/headers/tomcrypt.h b/src/headers/tomcrypt.h index ad27eec..da5e4f9 100644 --- a/src/headers/tomcrypt.h +++ b/src/headers/tomcrypt.h @@ -74,6 +74,7 @@ enum { #include #include #include +#include #ifdef __cplusplus } diff --git a/src/headers/tomcrypt_custom.h b/src/headers/tomcrypt_custom.h index 97de5de..4f25ba7 100644 --- a/src/headers/tomcrypt_custom.h +++ b/src/headers/tomcrypt_custom.h @@ -360,6 +360,13 @@ #endif /* LTC_NO_PKCS */ +/* LTC_HKDF Key Derivation/Expansion stuff */ +#ifndef LTC_NO_HKDF + +#define LTC_HKDF + +#endif /* LTC_NO_HKDF */ + /* cleanup */ #ifdef LTC_MECC diff --git a/src/headers/tomcrypt_hkdf.h b/src/headers/tomcrypt_hkdf.h new file mode 100644 index 0000000..882fc83 --- /dev/null +++ b/src/headers/tomcrypt_hkdf.h @@ -0,0 +1,26 @@ +/* LTC_HKDF Header Info */ + +/* ===> LTC_HKDF -- RFC5869 HMAC-based Key Derivation Function <=== */ +#ifdef LTC_HKDF + +int hkdf_extract(int hash_idx, + const unsigned char *salt, unsigned long saltlen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen); + +int hkdf_expand(int hash_idx, + const unsigned char *info, unsigned long infolen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long outlen); + +int hkdf(int hash_idx, + const unsigned char *salt, unsigned long saltlen, + const unsigned char *info, unsigned long infolen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long outlen); + +#endif /* LTC_HKDF */ + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/src/misc/hkdf/hkdf.c b/src/misc/hkdf/hkdf.c new file mode 100644 index 0000000..b067663 --- /dev/null +++ b/src/misc/hkdf/hkdf.c @@ -0,0 +1,113 @@ +#include +#include +#include + +#include + +#ifndef MIN +#define MIN(a,b) ((a)<(b))?(a):(b) +#endif + +/* This is mostly just a wrapper around hmac_memory */ +int hkdf_extract(int hash_idx, const unsigned char *salt, unsigned long saltlen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + /* libtomcrypt chokes on a zero length HMAC key, so we need to check for + that. HMAC specifies that keys shorter than the hash's blocksize are + 0 padded to the block size. HKDF specifies that a NULL salt is to be + substituted with a salt comprised of hashLen 0 bytes. HMAC's padding + means that in either case the HMAC is actually using a blocksize long + zero filled key. Unless blocksize < hashLen (which wouldn't make any + sense), we can use a single 0 byte as the HMAC key and still generate + valid results for HKDF. */ + if (salt == NULL || saltlen == 0) { + return hmac_memory(hash_idx, "", 1, in, inlen, out, outlen); + } else { + return hmac_memory(hash_idx, salt, saltlen, in, inlen, out, outlen); + } +} + +int hkdf_expand(int hash_idx, const unsigned char *info, unsigned long infolen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long outlen) +{ + const unsigned long hashsize = hash_descriptor[hash_idx].hashsize; + int err; + unsigned char N; + unsigned long Noutlen, outoff; + + unsigned char *T, *dat; + unsigned long Tlen, datlen; + + /* RFC5869 parameter restrictions */ + if (inlen < hashsize || outlen > hashsize * 255) + return CRYPT_INVALID_ARG; + if (info == NULL && infolen != 0) + return CRYPT_INVALID_ARG; + assert(out != NULL); + + Tlen = hashsize + infolen + 1; + T = XMALLOC(Tlen); /* Replace with static buffer? */ + if (T == NULL) { + return CRYPT_MEM; + } + XMEMCPY(T + hashsize, info, infolen); + + /* HMAC data T(1) doesn't include a previous hash value */ + dat = T + hashsize; + datlen = Tlen - hashsize; + + N = 0; + outoff = 0; /* offset in out to write to */ + while (1) { /* an exit condition breaks mid-loop */ + Noutlen = MIN(hashsize, outlen - outoff); + T[Tlen - 1] = ++N; + if ((err = hmac_memory(hash_idx, in, inlen, dat, datlen, + out + outoff, &Noutlen)) != CRYPT_OK) { + zeromem(T, Tlen); + XFREE(T); + return err; + } + outoff += Noutlen; + + if (outoff >= outlen) /* loop exit condition */ + break; + + /* All subsequent HMAC data T(N) DOES include the previous hash value */ + XMEMCPY(T, out + hashsize * (N-1), hashsize); + if (N == 1) { + dat = T; + datlen = Tlen; + } + } + zeromem(T, Tlen); + XFREE(T); + return CRYPT_OK; +} + +/* all in one step */ +int hkdf(int hash_idx, const unsigned char *salt, unsigned long saltlen, + const unsigned char *info, unsigned long infolen, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long outlen) +{ + unsigned long hashsize = hash_descriptor[hash_idx].hashsize; + int err; + unsigned char *extracted = XMALLOC(hashsize); /* replace with static buffer? */ + if (extracted == NULL) { + return CRYPT_MEM; + } + if ((err = hkdf_extract(hash_idx, salt, saltlen, in, inlen, extracted, &hashsize)) != 0) { + zeromem(extracted, hashsize); + XFREE(extracted); + return err; + } + err = hkdf_expand(hash_idx, extracted, hashsize, info, infolen, out, outlen); + zeromem(extracted, hashsize); + XFREE(extracted); + return err; +} + + +/* vim: set ts=2 sw=2 et ai si: */ From d7a1480f9e78a36939eec3840b233c20298baed0 Mon Sep 17 00:00:00 2001 From: RyanC Date: Tue, 13 Nov 2012 09:30:26 -0800 Subject: [PATCH 02/10] docs for HKDF --- crypt.tex | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/crypt.tex b/crypt.tex index d28f3cc..83e10a4 100644 --- a/crypt.tex +++ b/crypt.tex @@ -5148,6 +5148,82 @@ int main(void) } \end{verbatim} +\mysection{Key Derviation Functions} +\subsection{HKDF} +\index{HKDF} +A key derivation function (KDF) is a basic and essential component of cryptographic systems. Its goal is to take some source of initial +keying material and derive from it one or more cryptographically strong secret keys. + +HKDF follows the "extract-then-expand" paradigm, where the KDF logically consists of two modules. The first stage takes the input +keying material and "extracts" from it a fixed-length pseudorandom key K. The second stage "expands" the key K into several additional +pseudorandom keys (the output of the KDF). + +In many applications, the input keying material is not necessarily distributed uniformly, and the attacker may have some partial +knowledge about it (for example, a Diffie-Hellman value computed by a key exchange protocol) or even partial control of it (as in some +entropy-gathering applications). Thus, the goal of the "extract" stage is to "concentrate" the possibly dispersed entropy of the input +keying material into a short, but cryptographically strong, pseudorandom key. In some applications, the input may already be a +good pseudorandom key; in these cases, the "extract" stage is not necessary, and the "expand" part can be used alone. + +The second stage "expands" the pseudorandom key to the desired length; the number and lengths of the output keys depend on the +specific cryptographic algorithms for which the keys are needed. + +\subsection{HKDF Extract} +To perform the extraction phase, use the following function: + +\index{hkdf\_extract()} +\begin{alltt} +int hkdf_extract( int hash_idx, + const unsigned char *salt, + unsigned long saltlen, + const unsigned char *in, + unsigned long inlen, + unsigned char *out, + unsigned long *outlen); +\end{alltt} +The \textit{hash_idx} parameter is the index into the descriptor table of the hash you want to use. +The \textit{salt} parameter is a pointer to the array of octets of length \textit{saltlen} containing the salt or a NULL pointer if a salt is not being used (in that case set saltlen to 0). +\textit{in} is a pointer to an array of octets of length \textit{inlen} containing the source entropy. The extracted output is stored in the location pointed to by \textit{out}. +You must set \textit{outlen} to the size of the destination buffer before calling this function. It is updated to the length of the extracted output. If \textit{outlen} is too small the extracted output will be truncated. + +While the salt is optional, using one improves HKDF's security. If used, the salt should be randomly chosen, but does not need to be secret and may be re-used. Please see RFC5869 section 3.1 for more details. + +\subsection{HKDF Expand} +To perform the expansion phase, use the following function: + +\index{hkdf\_expand()} +\begin{alltt} +int hkdf_expand( int hash_idx, + const unsigned char *info, + unsigned long infolen, + const unsigned char *in, + unsigned long inlen, + unsigned char *out, + unsigned long outlen); +\end{alltt} + +The \textit{hash_idx} parameter is the index into the descriptor table of the hash you want to use. +The \textit{info} parameter, an array of octets of length \textit{infolen}, is an optional parameter (set \textit{info} to NULL and \textit{infolen} to 0 if not using it) which +may be used to bind the derived keys to some application and context specific information. This prevents the same keying material from being generated in different contexts. Please see RFC5869 section 3.2 for more information. +The extracted keying material is passed as octet array \textit{in} of length \textit{inlen}. Expanded output of length \textit{outlen} is generated and stored in octet arrat \textit{out}. + +\subection{HKDF Extract-and-Expand} +To perform both phases together, use the following function: + +\index{hkdf()} +\begin{alltt} +int hkdf( int hash_idx, + const unsigned char *salt, + unsigned long saltlen, + const unsigned char *info, + unsigned long infolen, + const unsigned char *in, + unsigned long inlen, + unsigned char *out, + unsigned long outlen); +\end{alltt} + +Parameters are as in \textit{hkdf\_extract()} and \textit{hkdf\_expand()}. + \chapter{Miscellaneous} \mysection{Base64 Encoding and Decoding} The library provides functions to encode and decode a RFC 1521 base--64 coding scheme. The characters used in the mappings are: From abeddd6c4b310c6ce7c80e7e9075924db5eecc29 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Fri, 23 Nov 2012 03:02:50 +0100 Subject: [PATCH 03/10] add hkdf_test() --- makefile | 2 +- src/headers/tomcrypt_hkdf.h | 2 + src/misc/hkdf/hkdf_test.c | 148 ++++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 src/misc/hkdf/hkdf_test.c diff --git a/makefile b/makefile index e9ef4e6..6278a20 100644 --- a/makefile +++ b/makefile @@ -156,7 +156,7 @@ src/misc/crypt/crypt_prng_is_valid.o src/misc/crypt/crypt_register_cipher.o \ src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o \ src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \ src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/pkcs5/pkcs_5_1.o \ -src/misc/pkcs5/pkcs_5_2.o src/misc/zeromem.o src/misc/hkdf/hkdf.o \ +src/misc/pkcs5/pkcs_5_2.o src/misc/zeromem.o src/misc/hkdf/hkdf.o src/misc/hkdf/hkdf_test.o \ src/modes/cbc/cbc_decrypt.o src/modes/cbc/cbc_done.o \ src/modes/cbc/cbc_encrypt.o src/modes/cbc/cbc_getiv.o src/modes/cbc/cbc_setiv.o \ src/modes/cbc/cbc_start.o src/modes/cfb/cfb_decrypt.o src/modes/cfb/cfb_done.o \ diff --git a/src/headers/tomcrypt_hkdf.h b/src/headers/tomcrypt_hkdf.h index 882fc83..f6a0228 100644 --- a/src/headers/tomcrypt_hkdf.h +++ b/src/headers/tomcrypt_hkdf.h @@ -3,6 +3,8 @@ /* ===> LTC_HKDF -- RFC5869 HMAC-based Key Derivation Function <=== */ #ifdef LTC_HKDF +int hkdf_test(void); + int hkdf_extract(int hash_idx, const unsigned char *salt, unsigned long saltlen, const unsigned char *in, unsigned long inlen, diff --git a/src/misc/hkdf/hkdf_test.c b/src/misc/hkdf/hkdf_test.c new file mode 100644 index 0000000..d644506 --- /dev/null +++ b/src/misc/hkdf/hkdf_test.c @@ -0,0 +1,148 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + */ +#include "tomcrypt.h" + +/** + @file hkdf_test.c + LTC_HKDF support, self-test, Steffen Jaeckel +*/ + +#ifdef LTC_HKDF + +/* + TEST CASES SOURCE: + +Internet Engineering Task Force (IETF) H. Krawczyk +Request for Comments: 5869 IBM Research +Category: Informational P. Eronen +ISSN: 2070-1721 Nokia + May 2010 +Appendix A. Test Vectors +*/ + +/** + LTC_HKDF self-test + @return CRYPT_OK if successful, CRYPT_NOP if tests have been disabled. +*/ +int hkdf_test(void) +{ + #ifndef LTC_TEST + return CRYPT_NOP; + #else + unsigned char OKM[82]; + int i; + + static const struct hkdf_test_case { + char* Hash; + unsigned char IKM[80]; + unsigned long IKM_l; + unsigned char salt[80]; + unsigned long salt_l; + unsigned char info[80]; + unsigned long info_l; + unsigned long L; + unsigned char PRK[32]; + unsigned char OKM[82]; + } cases[] = { +#ifdef LTC_SHA256 + /* + Basic test case with SHA-256 + + Hash = SHA-256 + IKM = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b (22 octets) + salt = 0x000102030405060708090a0b0c (13 octets) + info = 0xf0f1f2f3f4f5f6f7f8f9 (10 octets) + L = 42 + + PRK = 0x077709362c2e32df0ddc3f0dc47bba63 + 90b6c73bb50f9c3122ec844ad7c2b3e5 (32 octets) + OKM = 0x3cb25f25faacd57a90434f64d0362f2a + 2d2d0a90cf1a5a4c5db02d56ecc4c5bf + 34007208d5b887185865 (42 octets) + */ + + { "sha256", + {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c}, 13, + {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9}, 10, + 42, + {0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, + 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63, + 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, + 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5}, + {0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, + 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, + 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, + 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, + 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, + 0x58, 0x65} } +#endif /* LTC_SHA256 */ + }; + + int err; + int tested=0,failed=0; + for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) { + int hash = find_hash(cases[i].Hash); + if (hash == -1) continue; + ++tested; + if((err = hkdf(hash, cases[i].salt, cases[i].salt_l, + cases[i].info, cases[i].info_l, + cases[i].IKM, cases[i].IKM_l, + OKM, cases[i].L)) != CRYPT_OK) { +#if 0 + printf("LTC_HKDF-%s test #%d, %s\n", cases[i].Hash, i, error_to_string(err)); +#endif + return err; + } + + if(XMEMCMP(OKM, cases[i].OKM, (size_t)cases[i].L) != 0) { + failed++; +#if 0 + { + unsigned int j; + printf("\LTC_HKDF-%s test #%d:\n", cases[i].Hash, i); + printf( "Result: 0x"); + for(j=0; j < cases[i].L; j++) { + printf("%02x ", OKM[j]); + } + printf("\nCorrect: 0x"); + for(j=0; j < cases[i].L; j++) { + printf("%02x ", cases[i].OKM[j]); + } + printf("\n"); + return CRYPT_ERROR; + } +#endif +#if 0 + } else { + printf("LTC_HKDF-%s test #%d: Passed\n", cases[i].Hash, i); +#endif + } + } + + if (failed != 0) { + return CRYPT_FAIL_TESTVECTOR; + } else if (tested == 0) { + return CRYPT_NOP; + } else { + return CRYPT_OK; + } + #endif +} + +#endif + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ From 13c42a00f6c56e54cbfff399ea61256d94c7ed8b Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Fri, 23 Nov 2012 03:03:19 +0100 Subject: [PATCH 04/10] hkdf: fix compiler warning --- src/misc/hkdf/hkdf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/misc/hkdf/hkdf.c b/src/misc/hkdf/hkdf.c index b067663..ee65c61 100644 --- a/src/misc/hkdf/hkdf.c +++ b/src/misc/hkdf/hkdf.c @@ -22,7 +22,7 @@ int hkdf_extract(int hash_idx, const unsigned char *salt, unsigned long saltlen sense), we can use a single 0 byte as the HMAC key and still generate valid results for HKDF. */ if (salt == NULL || saltlen == 0) { - return hmac_memory(hash_idx, "", 1, in, inlen, out, outlen); + return hmac_memory(hash_idx, (const unsigned char *)"", 1, in, inlen, out, outlen); } else { return hmac_memory(hash_idx, salt, saltlen, in, inlen, out, outlen); } From c1243feef24d5e0a910ea9b4881d4657a67ad166 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Fri, 23 Nov 2012 03:03:54 +0100 Subject: [PATCH 05/10] hkdf: improve argument validation --- src/misc/hkdf/hkdf.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/misc/hkdf/hkdf.c b/src/misc/hkdf/hkdf.c index ee65c61..80ea2ab 100644 --- a/src/misc/hkdf/hkdf.c +++ b/src/misc/hkdf/hkdf.c @@ -32,7 +32,7 @@ int hkdf_expand(int hash_idx, const unsigned char *info, unsigned long infolen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long outlen) { - const unsigned long hashsize = hash_descriptor[hash_idx].hashsize; + unsigned long hashsize; int err; unsigned char N; unsigned long Noutlen, outoff; @@ -40,12 +40,19 @@ int hkdf_expand(int hash_idx, const unsigned char *info, unsigned long infolen, unsigned char *T, *dat; unsigned long Tlen, datlen; + /* make sure hash descriptor is valid */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + hashsize = hash_descriptor[hash_idx].hashsize; + /* RFC5869 parameter restrictions */ if (inlen < hashsize || outlen > hashsize * 255) return CRYPT_INVALID_ARG; if (info == NULL && infolen != 0) return CRYPT_INVALID_ARG; - assert(out != NULL); + LTC_ARGCHK(out != NULL); Tlen = hashsize + infolen + 1; T = XMALLOC(Tlen); /* Replace with static buffer? */ @@ -92,9 +99,18 @@ int hkdf(int hash_idx, const unsigned char *salt, unsigned long saltlen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long outlen) { - unsigned long hashsize = hash_descriptor[hash_idx].hashsize; + unsigned long hashsize; int err; - unsigned char *extracted = XMALLOC(hashsize); /* replace with static buffer? */ + unsigned char *extracted; + + /* make sure hash descriptor is valid */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + + hashsize = hash_descriptor[hash_idx].hashsize; + + extracted = XMALLOC(hashsize); /* replace with static buffer? */ if (extracted == NULL) { return CRYPT_MEM; } From e81ac102bdf575e1d003b2d3ab3e822f4c584d6c Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Fri, 23 Nov 2012 03:04:50 +0100 Subject: [PATCH 06/10] add misc_test() --- demos/test.c | 3 ++- testprof/makefile | 2 +- testprof/misc_test.c | 13 +++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 testprof/misc_test.c diff --git a/demos/test.c b/demos/test.c index abfd22a..0d26b95 100644 --- a/demos/test.c +++ b/demos/test.c @@ -18,6 +18,7 @@ int main(void) printf("build == \n%s\n", crypt_build_settings); printf("\nstore_test...."); fflush(stdout); x = store_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + printf("\nmisc_test...."); fflush(stdout); x = misc_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); printf("\ncipher_test..."); fflush(stdout); x = cipher_hash_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); printf("\nmodes_test...."); fflush(stdout); x = modes_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); printf("\nder_test......"); fflush(stdout); x = der_tests(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); @@ -25,7 +26,7 @@ int main(void) printf("\npkcs_1_test..."); fflush(stdout); x = pkcs_1_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); printf("\nrsa_test......"); fflush(stdout); x = rsa_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); printf("\ndh_test......."); fflush(stdout); x = dh_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); - printf("\necc_test......"); fflush(stdout); x = ecc_tests(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); + printf("\necc_test......"); fflush(stdout); x = ecc_tests(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); printf("\ndsa_test......"); fflush(stdout); x = dsa_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); printf("\nkatja_test...."); fflush(stdout); x = katja_test(); printf(x ? "failed" : "passed");if (x) exit(EXIT_FAILURE); printf("\n"); diff --git a/testprof/makefile b/testprof/makefile index c52fe7b..f3ce3db 100644 --- a/testprof/makefile +++ b/testprof/makefile @@ -6,7 +6,7 @@ ifndef RANLIB endif OBJECTS = base64_test.o cipher_hash_test.o der_tests.o \ -dsa_test.o ecc_test.o mac_test.o modes_test.o pkcs_1_test.o rsa_test.o \ +dsa_test.o ecc_test.o mac_test.o misc_test.o modes_test.o pkcs_1_test.o rsa_test.o \ store_test.o test_driver.o x86_prof.o katja_test.o dh_test.o ifndef LIBTEST_S diff --git a/testprof/misc_test.c b/testprof/misc_test.c new file mode 100644 index 0000000..40f4b44 --- /dev/null +++ b/testprof/misc_test.c @@ -0,0 +1,13 @@ +#include + +int misc_test(void) +{ +#ifdef LTC_HKDF + DO(hkdf_test()); +#endif + return 0; +} + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ From 8fcd408a98b1ddfcd343934aafbcceda9386d277 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Thu, 14 Mar 2013 23:25:17 +0100 Subject: [PATCH 07/10] fixed latex compile errors --- crypt.tex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crypt.tex b/crypt.tex index 83e10a4..4a5d59b 100644 --- a/crypt.tex +++ b/crypt.tex @@ -5180,7 +5180,7 @@ int hkdf_extract( int hash_idx, unsigned char *out, unsigned long *outlen); \end{alltt} -The \textit{hash_idx} parameter is the index into the descriptor table of the hash you want to use. +The \textit{hash\_idx} parameter is the index into the descriptor table of the hash you want to use. The \textit{salt} parameter is a pointer to the array of octets of length \textit{saltlen} containing the salt or a NULL pointer if a salt is not being used (in that case set saltlen to 0). \textit{in} is a pointer to an array of octets of length \textit{inlen} containing the source entropy. The extracted output is stored in the location pointed to by \textit{out}. You must set \textit{outlen} to the size of the destination buffer before calling this function. It is updated to the length of the extracted output. If \textit{outlen} is too small the extracted output will be truncated. @@ -5201,12 +5201,12 @@ int hkdf_expand( int hash_idx, unsigned long outlen); \end{alltt} -The \textit{hash_idx} parameter is the index into the descriptor table of the hash you want to use. +The \textit{hash\_idx} parameter is the index into the descriptor table of the hash you want to use. The \textit{info} parameter, an array of octets of length \textit{infolen}, is an optional parameter (set \textit{info} to NULL and \textit{infolen} to 0 if not using it) which may be used to bind the derived keys to some application and context specific information. This prevents the same keying material from being generated in different contexts. Please see RFC5869 section 3.2 for more information. The extracted keying material is passed as octet array \textit{in} of length \textit{inlen}. Expanded output of length \textit{outlen} is generated and stored in octet arrat \textit{out}. -\subection{HKDF Extract-and-Expand} +\subsection{HKDF Extract-and-Expand} To perform both phases together, use the following function: \index{hkdf()} From 1c779b88f16d8ec47533d65c255c6a617d168d9c Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Thu, 14 Mar 2013 23:47:50 +0100 Subject: [PATCH 08/10] moar debug output --- src/misc/hkdf/hkdf.c | 12 ++++++++++++ src/misc/hkdf/hkdf_test.c | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/misc/hkdf/hkdf.c b/src/misc/hkdf/hkdf.c index 80ea2ab..cec3daa 100644 --- a/src/misc/hkdf/hkdf.c +++ b/src/misc/hkdf/hkdf.c @@ -119,6 +119,18 @@ int hkdf(int hash_idx, const unsigned char *salt, unsigned long saltlen, XFREE(extracted); return err; } +#if 0 + { + int j; + printf("\nPRK: 0x"); + for(j=0; j < hashsize; j++) { + printf("%02x ", extracted[j]); + } + for(j=0; j < hashsize; j++) { + printf("%02x ", extracted[j]); + } + } +#endif err = hkdf_expand(hash_idx, extracted, hashsize, info, infolen, out, outlen); zeromem(extracted, hashsize); XFREE(extracted); diff --git a/src/misc/hkdf/hkdf_test.c b/src/misc/hkdf/hkdf_test.c index d644506..a936336 100644 --- a/src/misc/hkdf/hkdf_test.c +++ b/src/misc/hkdf/hkdf_test.c @@ -110,7 +110,7 @@ int hkdf_test(void) #if 0 { unsigned int j; - printf("\LTC_HKDF-%s test #%d:\n", cases[i].Hash, i); + printf("\nLTC_HKDF-%s test #%d:\n", cases[i].Hash, i); printf( "Result: 0x"); for(j=0; j < cases[i].L; j++) { printf("%02x ", OKM[j]); From 11f50bfb3c09cb4d322546fd2a866fec832cb227 Mon Sep 17 00:00:00 2001 From: RyanC Date: Thu, 14 Mar 2013 20:44:53 -0700 Subject: [PATCH 09/10] fix hkdf_expand arguments --- src/misc/hkdf/hkdf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/misc/hkdf/hkdf.c b/src/misc/hkdf/hkdf.c index cec3daa..279c8ed 100644 --- a/src/misc/hkdf/hkdf.c +++ b/src/misc/hkdf/hkdf.c @@ -131,7 +131,7 @@ int hkdf(int hash_idx, const unsigned char *salt, unsigned long saltlen, } } #endif - err = hkdf_expand(hash_idx, extracted, hashsize, info, infolen, out, outlen); + err = hkdf_expand(hash_idx, info, infolen, extracted, hashsize, out, outlen); zeromem(extracted, hashsize); XFREE(extracted); return err; From fe18c95e76b8aac6333df5326281a670ac139cf4 Mon Sep 17 00:00:00 2001 From: RyanC Date: Thu, 14 Mar 2013 21:30:36 -0700 Subject: [PATCH 10/10] add the rest of the hkdf test cases --- src/misc/hkdf/hkdf_test.c | 186 +++++++++++++++++++++++++++++++++++--- 1 file changed, 174 insertions(+), 12 deletions(-) diff --git a/src/misc/hkdf/hkdf_test.c b/src/misc/hkdf/hkdf_test.c index a936336..70bb008 100644 --- a/src/misc/hkdf/hkdf_test.c +++ b/src/misc/hkdf/hkdf_test.c @@ -39,6 +39,7 @@ int hkdf_test(void) int i; static const struct hkdf_test_case { + int num; char* Hash; unsigned char IKM[80]; unsigned long IKM_l; @@ -46,9 +47,10 @@ int hkdf_test(void) unsigned long salt_l; unsigned char info[80]; unsigned long info_l; - unsigned long L; unsigned char PRK[32]; + unsigned long PRK_l; unsigned char OKM[82]; + unsigned long OKM_l; } cases[] = { #ifdef LTC_SHA256 /* @@ -66,8 +68,7 @@ int hkdf_test(void) 2d2d0a90cf1a5a4c5db02d56ecc4c5bf 34007208d5b887185865 (42 octets) */ - - { "sha256", + {1, "sha256", {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22, @@ -75,18 +76,179 @@ int hkdf_test(void) 0x08, 0x09, 0x0a, 0x0b, 0x0c}, 13, {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9}, 10, - 42, {0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63, 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, - 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5}, + 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5}, 32, {0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, - 0x58, 0x65} } + 0x58, 0x65}, 42}, + /* Test with SHA-256 and longer inputs/outputs */ + {2, "sha256", + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f}, 80, + {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, 80, + {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}, 80, + {0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, + 0x06, 0x10, 0x4c, 0x9c, 0xeb, 0x35, 0xb4, 0x5c, + 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01, + 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44}, 32, + {0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, + 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, + 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, + 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, + 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, + 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, + 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, + 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, + 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, + 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, + 0x1d, 0x87}, 82}, + /* Test with SHA-256 and zero length salt/info */ + {3, "sha256", + {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22, + {0}, 0, + {0}, 0, + {0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, + 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf, + 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, + 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04}, 32, + {0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, + 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, + 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, + 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, + 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, + 0x96, 0xc8}, 42}, #endif /* LTC_SHA256 */ +#ifdef LTC_SHA1 + /* Basic test case with SHA-1 */ + {4, "sha1", + {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b}, 11, + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c}, 13, + {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9}, 10, + {0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f, + 0x0e, 0x71, 0xc8, 0xeb, 0x88, 0xf4, 0xb3, 0x0b, + 0xaa, 0x2b, 0xa2, 0x43}, 20, + {0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, + 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81, + 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, + 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, + 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3, + 0xf8, 0x96}, 42}, + /* Test with SHA-1 and longer inputs/outputs */ + {5, "sha1", + {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, + 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f}, 80, + {0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, + 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, + 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, + 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, + 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf}, 80, + {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, + 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, + 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, + 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, + 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}, 80, + {0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59, + 0x47, 0x8d, 0x30, 0x9b, 0x26, 0xc4, 0x11, 0x5a, + 0x22, 0x4c, 0xfa, 0xf6}, 20, + {0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, + 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb, + 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, + 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, + 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3, + 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, + 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, + 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e, + 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, + 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, + 0xd3, 0xb4}, 82}, + /* Test with SHA-1 and zero-length salt/info */ + {6, "sha1", + {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 22, + {0}, 0, + {0}, 0, + {0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28, + 0x8e, 0xc6, 0xf5, 0xe7, 0xc2, 0x97, 0x78, 0x6a, + 0xa0, 0xd3, 0x2d, 0x01}, 20, + {0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, + 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06, + 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, + 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, + 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3, + 0x49, 0x18}, 42}, + /* Test with SHA-1, salt not provided (defaults to HashLen zero octets), + zero-length info */ + {7, "sha1", + {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, 22, + {0}, 0, /* pass a null pointer */ + {0}, 0, + {0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c, + 0x20, 0x77, 0xad, 0x2e, 0xb1, 0x9d, 0x3f, 0x3e, + 0x73, 0x13, 0x85, 0xdd}, 20, + {0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, + 0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a, + 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23, + 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, + 0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac, + 0xfc, 0x48}, 42}, +#endif /* LTC_SHA1 */ }; int err; @@ -98,25 +260,25 @@ int hkdf_test(void) if((err = hkdf(hash, cases[i].salt, cases[i].salt_l, cases[i].info, cases[i].info_l, cases[i].IKM, cases[i].IKM_l, - OKM, cases[i].L)) != CRYPT_OK) { + OKM, cases[i].OKM_l)) != CRYPT_OK) { #if 0 printf("LTC_HKDF-%s test #%d, %s\n", cases[i].Hash, i, error_to_string(err)); #endif return err; } - if(XMEMCMP(OKM, cases[i].OKM, (size_t)cases[i].L) != 0) { + if(XMEMCMP(OKM, cases[i].OKM, (size_t)cases[i].OKM_l) != 0) { failed++; #if 0 { unsigned int j; - printf("\nLTC_HKDF-%s test #%d:\n", cases[i].Hash, i); + printf("\nLTC_HKDF-%s test #%d:\n", cases[i].Hash, cases[i].num); printf( "Result: 0x"); - for(j=0; j < cases[i].L; j++) { + for(j=0; j < cases[i].OKM_l; j++) { printf("%02x ", OKM[j]); } printf("\nCorrect: 0x"); - for(j=0; j < cases[i].L; j++) { + for(j=0; j < cases[i].OKM_l; j++) { printf("%02x ", cases[i].OKM[j]); } printf("\n"); @@ -125,7 +287,7 @@ int hkdf_test(void) #endif #if 0 } else { - printf("LTC_HKDF-%s test #%d: Passed\n", cases[i].Hash, i); + printf("LTC_HKDF-%s test #%d: Passed\n", cases[i].Hash, cases[i].num); #endif } }