add hkdf impl

This commit is contained in:
RyanC 2012-11-11 15:00:19 -08:00 committed by Steffen Jaeckel
parent d84af284a3
commit c98857a47e
12 changed files with 206 additions and 5 deletions

View File

@ -825,6 +825,11 @@ SOURCE=.\src\misc\error_to_string.c
SOURCE=.\src\misc\zeromem.c SOURCE=.\src\misc\zeromem.c
# End Source File # End Source File
# End Group # End Group
# Begin Source File
SOURCE=.\src\misc\hkdf\hkdf.c
# End Source File
# End Group
# Begin Group "modes" # Begin Group "modes"
# PROP Default_Filter "" # PROP Default_Filter ""

View File

@ -2954,6 +2954,28 @@
/> />
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath="src\misc\hkdf\hkdf.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<Filter <Filter
Name="base64" Name="base64"
> >

View File

@ -2946,6 +2946,28 @@
/> />
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath="src\misc\hkdf\hkdf.c"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
/>
</FileConfiguration>
</File>
<Filter <Filter
Name="base64" Name="base64"
> >

View File

@ -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_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_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/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_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/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 \ src/modes/cfb/cfb_encrypt.o src/modes/cfb/cfb_getiv.o src/modes/cfb/cfb_setiv.o \

View File

@ -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_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_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/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_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/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 \ src/modes/cfb/cfb_encrypt.o src/modes/cfb/cfb_getiv.o src/modes/cfb/cfb_setiv.o \

View File

@ -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_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_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/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_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/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 \ src/modes/cfb/cfb_encrypt.obj src/modes/cfb/cfb_getiv.obj src/modes/cfb/cfb_setiv.obj \

View File

@ -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_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_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/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_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/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 \ src/modes/cfb/cfb_encrypt.o src/modes/cfb/cfb_getiv.o src/modes/cfb/cfb_setiv.o \

View File

@ -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_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_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/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_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/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 \ src/modes/cfb/cfb_encrypt.o src/modes/cfb/cfb_getiv.o src/modes/cfb/cfb_setiv.o \

View File

@ -74,6 +74,7 @@ enum {
#include <tomcrypt_misc.h> #include <tomcrypt_misc.h>
#include <tomcrypt_argchk.h> #include <tomcrypt_argchk.h>
#include <tomcrypt_pkcs.h> #include <tomcrypt_pkcs.h>
#include <tomcrypt_hkdf.h>
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -360,6 +360,13 @@
#endif /* LTC_NO_PKCS */ #endif /* LTC_NO_PKCS */
/* LTC_HKDF Key Derivation/Expansion stuff */
#ifndef LTC_NO_HKDF
#define LTC_HKDF
#endif /* LTC_NO_HKDF */
/* cleanup */ /* cleanup */
#ifdef LTC_MECC #ifdef LTC_MECC

View File

@ -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$ */

113
src/misc/hkdf/hkdf.c Normal file
View File

@ -0,0 +1,113 @@
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <tomcrypt.h>
#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: */