diff --git a/crypt.tex b/crypt.tex
index d28f3cc..4a5d59b 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}.
+
+\subsection{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:
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/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..6278a20 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/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 \
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..f6a0228
--- /dev/null
+++ b/src/headers/tomcrypt_hkdf.h
@@ -0,0 +1,28 @@
+/* LTC_HKDF Header Info */
+
+/* ===> 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,
+ 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..279c8ed
--- /dev/null
+++ b/src/misc/hkdf/hkdf.c
@@ -0,0 +1,141 @@
+#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, (const unsigned char *)"", 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)
+{
+ unsigned long hashsize;
+ int err;
+ unsigned char N;
+ unsigned long Noutlen, outoff;
+
+ 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;
+ LTC_ARGCHK(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;
+ int err;
+ 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;
+ }
+ if ((err = hkdf_extract(hash_idx, salt, saltlen, in, inlen, extracted, &hashsize)) != 0) {
+ zeromem(extracted, hashsize);
+ 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, info, infolen, extracted, hashsize, out, outlen);
+ zeromem(extracted, hashsize);
+ XFREE(extracted);
+ return err;
+}
+
+
+/* vim: set ts=2 sw=2 et ai si: */
diff --git a/src/misc/hkdf/hkdf_test.c b/src/misc/hkdf/hkdf_test.c
new file mode 100644
index 0000000..70bb008
--- /dev/null
+++ b/src/misc/hkdf/hkdf_test.c
@@ -0,0 +1,310 @@
+/* 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 {
+ int num;
+ 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 char PRK[32];
+ unsigned long PRK_l;
+ unsigned char OKM[82];
+ unsigned long OKM_l;
+ } 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)
+ */
+ {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,
+ {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,
+ {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}, 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}, 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;
+ 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].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].OKM_l) != 0) {
+ failed++;
+#if 0
+ {
+ unsigned int j;
+ printf("\nLTC_HKDF-%s test #%d:\n", cases[i].Hash, cases[i].num);
+ printf( "Result: 0x");
+ for(j=0; j < cases[i].OKM_l; j++) {
+ printf("%02x ", OKM[j]);
+ }
+ printf("\nCorrect: 0x");
+ for(j=0; j < cases[i].OKM_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, cases[i].num);
+#endif
+ }
+ }
+
+ if (failed != 0) {
+ return CRYPT_FAIL_TESTVECTOR;
+ } else if (tested == 0) {
+ return CRYPT_NOP;
+ } else {
+ return CRYPT_OK;
+ }
+ #endif
+}
+
+#endif
+
+
+/* $Source$ */
+/* $Revision$ */
+/* $Date$ */
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$ */