Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Nettle
nettle
Commits
195edb37
Commit
195edb37
authored
Sep 06, 2017
by
Niels Möller
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'hkdf-support'
parents
2351995b
94f8644f
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
358 additions
and
8 deletions
+358
-8
ChangeLog
ChangeLog
+16
-0
Makefile.in
Makefile.in
+2
-2
hkdf.c
hkdf.c
+82
-0
hkdf.h
hkdf.h
+67
-0
nettle.texinfo
nettle.texinfo
+44
-5
testsuite/.test-rules.make
testsuite/.test-rules.make
+3
-0
testsuite/Makefile.in
testsuite/Makefile.in
+1
-1
testsuite/hkdf-test.c
testsuite/hkdf-test.c
+143
-0
No files found.
ChangeLog
View file @
195edb37
2017-09-06 Niels Möller <nisse@lysator.liu.se>
* hkdf.c (hkdf_expand): Eliminate a (signed) ssize_t variable, use
break rather than return at loop termination.
2017-09-06 Niels Möller <nisse@lysator.liu.se>
HKDF implementation, contributed by Nikos Mavrogiannopoulos.
* hkdf.c (hkdf_extract, hkdf_expand): New file, new functions.
* hkdf.h: New file.
* Makefile.in (nettle_SOURCES): Add hkdf.c.
(HEADERS): Add hkdf.h.
* testsuite/hkdf-test.c: Tests for hkdf-sha256 and hkdf-sha1.
* testsuite/Makefile.in (TS_NETTLE_SOURCES): Added hkdf-test.c.
* nettle.texinfo (Key derivation functions): Document HKDF.
2017-09-04 Andreas Schneider <asn@samba.org>
* fat-arm.c: Add missing define for _GNU_SOURCE.
...
...
Makefile.in
View file @
195edb37
...
...
@@ -106,7 +106,7 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt.c \
gosthash94.c gosthash94-meta.c
\
hmac.c hmac-md5.c hmac-ripemd160.c hmac-sha1.c
\
hmac-sha224.c hmac-sha256.c hmac-sha384.c hmac-sha512.c
\
knuth-lfib.c
\
knuth-lfib.c
hkdf.c
\
md2.c md2-meta.c md4.c md4-meta.c
\
md5.c md5-compress.c md5-compat.c md5-meta.c
\
memeql-sec.c memxor.c memxor3.c
\
...
...
@@ -192,7 +192,7 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h \
curve25519.h des.h des-compat.h dsa.h dsa-compat.h eax.h
\
ecc-curve.h ecc.h ecdsa.h eddsa.h
\
gcm.h gosthash94.h hmac.h
\
knuth-lfib.h
\
knuth-lfib.h
hkdf.h
\
macros.h
\
md2.h md4.h
\
md5.h md5-compat.h
\
...
...
hkdf.c
0 → 100644
View file @
195edb37
/*
* Copyright (C) 2017 Red Hat, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
* This file is part of GnuTLS.
*
* The GnuTLS is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
/* Functions for the HKDF handling.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
/* Needed for alloca on freebsd */
#include <stdlib.h>
#include <string.h>
#include "hmac.h"
#include "memxor.h"
#include "nettle-internal.h"
#include "hkdf.h"
/* hkdf_extract: Outputs a PRK of digest_size
*/
void
hkdf_extract
(
void
*
mac_ctx
,
nettle_hash_update_func
*
update
,
nettle_hash_digest_func
*
digest
,
size_t
digest_size
,
size_t
secret_size
,
const
uint8_t
*
secret
,
uint8_t
*
dst
)
{
update
(
mac_ctx
,
secret_size
,
secret
);
digest
(
mac_ctx
,
digest_size
,
dst
);
}
/* hkdf_expand: Outputs an arbitrary key of size specified by length
*/
void
hkdf_expand
(
void
*
mac_ctx
,
nettle_hash_update_func
*
update
,
nettle_hash_digest_func
*
digest
,
size_t
digest_size
,
size_t
info_size
,
const
uint8_t
*
info
,
size_t
length
,
uint8_t
*
dst
)
{
uint8_t
i
=
1
;
if
(
!
length
)
return
;
for
(;;
dst
+=
digest_size
,
length
-=
digest_size
,
i
++
)
{
update
(
mac_ctx
,
info_size
,
info
);
update
(
mac_ctx
,
1
,
&
i
);
if
(
length
<=
digest_size
)
break
;
digest
(
mac_ctx
,
digest_size
,
dst
);
update
(
mac_ctx
,
digest_size
,
dst
);
}
digest
(
mac_ctx
,
length
,
dst
);
}
hkdf.h
0 → 100644
View file @
195edb37
/* hkdf.h
TLS PRF code (RFC-5246, RFC-2246).
Copyright (C) 2017 Red Hat, Inc.
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#ifndef NETTLE_HKDF_H_INCLUDED
#define NETTLE_HKDF_H_INCLUDED
#include "nettle-meta.h"
#ifdef __cplusplus
extern
"C"
{
#endif
/* Namespace mangling */
#define hkdf_extract nettle_hkdf_extract
#define hkdf_expand nettle_hkdf_expand
void
hkdf_extract
(
void
*
mac_ctx
,
nettle_hash_update_func
*
update
,
nettle_hash_digest_func
*
digest
,
size_t
digest_size
,
size_t
secret_size
,
const
uint8_t
*
secret
,
uint8_t
*
dst
);
void
hkdf_expand
(
void
*
mac_ctx
,
nettle_hash_update_func
*
update
,
nettle_hash_digest_func
*
digest
,
size_t
digest_size
,
size_t
info_size
,
const
uint8_t
*
info
,
size_t
length
,
uint8_t
*
dst
);
#ifdef __cplusplus
}
#endif
#endif
/* NETTLE_HKDF_H_INCLUDED */
nettle.texinfo
View file @
195edb37
...
...
@@ -3366,12 +3366,7 @@ processing a new message.
@node Key derivation functions, Public-key algorithms, Keyed hash functions, Reference
@comment node-name, next, previous, up
@section Key derivation Functions
@cindex Key Derivation Function
@cindex Password Based Key Derivation Function
@cindex PKCS #5
@cindex KDF
@cindex PBKDF
A @dfn
{
key derivation function
}
(@acronym
{
KDF
}
) is a function that from
a given symmetric key derives other symmetric keys. A sub-class of KDFs
...
...
@@ -3380,7 +3375,51 @@ which take as input a password or passphrase, and its purpose is
typically to strengthen it and protect against certain pre-computation
attacks by using salting and expensive computation.
@subsection HKDF: HMAC-based Extract-and-Expand
@cindex HKDF
HKDF is a key derivation function used as a building block of
higher-level protocols like TLS 1.3. It is a derivation function
based on HMAC described in @cite
{
RFC 5869
}
,
and is split into two logical modules, called 'extract' and 'expand'.
The extract module takes an initial secret and a random
salt to "extract" a fixed-length pseudorandom key (PRK). The second stage
takes as input the previous PRK and some informational data (e.g.,
text) and expands them into multiple keys.
Nettle's @acronym
{
HKDF
}
functions are defined in
@file
{
<nettle/hkdf.h>
}
. There are two abstract functions for the extract
and expand operations that operate on any HMAC implemented via the @code
{
nettle
_
hash
_
update
_
func
}
,
and @code
{
nettle
_
hash
_
digest
_
func
}
interfaces.
@deftypefun void hkdf
_
extract (void *mac
_
ctx, nettle
_
hash
_
update
_
func *update, nettle
_
hash
_
digest
_
func *digest, size
_
t digest
_
size,size
_
t secret
_
size, const uint8
_
t *secret, uint8
_
t *dst)
Extract a Pseudorandom Key (PRK) from a secret and a salt according
to HKDF. The HMAC must have been initialized, with its key being the
salt for the Extract operation. This function will call the
@var
{
update
}
and @var
{
digest
}
functions passing the @var
{
mac
_
ctx
}
context parameter as an argument in order to compute digest of size
@var
{
digest
_
size
}
. Inputs are the secret @var
{
secret
}
of length
@var
{
secret
_
length
}
. The output length is fixed to @var
{
digest
_
size
}
octets,
thus the output buffer @var
{
dst
}
must have room for at least @var
{
digest
_
size
}
octets.
@end deftypefun
@deftypefun void hkdf
_
expand (void *mac
_
ctx, nettle
_
hash
_
update
_
func *update, nettle
_
hash
_
digest
_
func *digest, size
_
t digest
_
size, size
_
t info
_
size, const uint8
_
t *info, size
_
t length, uint8
_
t *dst)
Expand a Pseudorandom Key (PRK) to an arbitrary size according to HKDF.
The HMAC must have been initialized, with its key being the
PRK from the Extract operation. This function will call the
@var
{
update
}
and @var
{
digest
}
functions passing the @var
{
mac
_
ctx
}
context parameter as an argument in order to compute digest of size
@var
{
digest
_
size
}
. Inputs are the info @var
{
info
}
of length
@var
{
info
_
length
}
, and the desired derived output length @var
{
length
}
.
The output buffer is @var
{
dst
}
which must have room for at least @var
{
length
}
octets.
@end deftypefun
@subsection @acronym
{
PBKDF2
}
@cindex Password Based Key Derivation Function
@cindex PKCS #5
@cindex KDF
@cindex PBKDF
The most well known PBKDF is the @code
{
PKCS #5 PBKDF2
}
described in
@cite
{
RFC 2898
}
which uses a pseudo-random function such as
@acronym
{
HMAC-SHA1
}
.
...
...
testsuite/.test-rules.make
View file @
195edb37
...
...
@@ -58,6 +58,9 @@ gosthash94-test$(EXEEXT): gosthash94-test.$(OBJEXT)
ripemd160-test$(EXEEXT)
:
ripemd160-test.$(OBJEXT)
$(LINK)
ripemd160-test.
$(OBJEXT)
$(TEST_OBJS)
-o
ripemd160-test
$(EXEEXT)
hkdf-test$(EXEEXT)
:
hkdf-test.$(OBJEXT)
$(LINK)
hkdf-test.
$(OBJEXT)
$(TEST_OBJS)
-o
hkdf-test
$(EXEEXT)
salsa20-test$(EXEEXT)
:
salsa20-test.$(OBJEXT)
$(LINK)
salsa20-test.
$(OBJEXT)
$(TEST_OBJS)
-o
salsa20-test
$(EXEEXT)
...
...
testsuite/Makefile.in
View file @
195edb37
...
...
@@ -17,7 +17,7 @@ TS_NETTLE_SOURCES = aes-test.c arcfour-test.c arctwo-test.c \
des-test.c des3-test.c des-compat-test.c
\
md2-test.c md4-test.c md5-test.c md5-compat-test.c
\
memeql-test.c memxor-test.c gosthash94-test.c
\
ripemd160-test.c
\
ripemd160-test.c
hkdf-test.c
\
salsa20-test.c
\
sha1-test.c sha224-test.c sha256-test.c
\
sha384-test.c sha512-test.c sha512-224-test.c sha512-256-test.c
\
...
...
testsuite/hkdf-test.c
0 → 100644
View file @
195edb37
#include "testutils.h"
#include "hkdf.h"
#include "hmac.h"
static
void
test_hkdf_sha256
(
const
struct
tstring
*
ikm
,
const
struct
tstring
*
salt
,
const
struct
tstring
*
info
,
const
struct
tstring
*
extract_output
,
const
struct
tstring
*
expand_output
)
{
struct
hmac_sha256_ctx
ctx
;
uint8_t
prk
[
SHA256_DIGEST_SIZE
];
uint8_t
*
buffer
=
xalloc
(
expand_output
->
length
);
hmac_sha256_set_key
(
&
ctx
,
salt
->
length
,
salt
->
data
);
hkdf_extract
(
&
ctx
,
(
nettle_hash_update_func
*
)
hmac_sha256_update
,
(
nettle_hash_digest_func
*
)
hmac_sha256_digest
,
SHA256_DIGEST_SIZE
,
ikm
->
length
,
ikm
->
data
,
prk
);
if
(
MEMEQ
(
SHA256_DIGEST_SIZE
,
prk
,
extract_output
->
data
)
==
0
)
{
fprintf
(
stdout
,
"
\n
Got:
\n
"
);
print_hex
(
SHA256_DIGEST_SIZE
,
prk
);
fprintf
(
stdout
,
"
\n
Expected:
\n
"
);
print_hex
(
extract_output
->
length
,
extract_output
->
data
);
abort
();
}
hmac_sha256_set_key
(
&
ctx
,
SHA256_DIGEST_SIZE
,
prk
);
hkdf_expand
(
&
ctx
,
(
nettle_hash_update_func
*
)
hmac_sha256_update
,
(
nettle_hash_digest_func
*
)
hmac_sha256_digest
,
SHA256_DIGEST_SIZE
,
info
->
length
,
info
->
data
,
expand_output
->
length
,
buffer
);
if
(
MEMEQ
(
expand_output
->
length
,
expand_output
->
data
,
buffer
)
==
0
)
{
fprintf
(
stdout
,
"
\n
Got:
\n
"
);
print_hex
(
expand_output
->
length
,
buffer
);
fprintf
(
stdout
,
"
\n
Expected:
\n
"
);
print_hex
(
expand_output
->
length
,
expand_output
->
data
);
abort
();
}
free
(
buffer
);
}
static
void
test_hkdf_sha1
(
const
struct
tstring
*
ikm
,
const
struct
tstring
*
salt
,
const
struct
tstring
*
info
,
const
struct
tstring
*
extract_output
,
const
struct
tstring
*
expand_output
)
{
struct
hmac_sha1_ctx
ctx
;
uint8_t
prk
[
SHA1_DIGEST_SIZE
];
uint8_t
*
buffer
=
xalloc
(
expand_output
->
length
);
hmac_sha1_set_key
(
&
ctx
,
salt
->
length
,
salt
->
data
);
hkdf_extract
(
&
ctx
,
(
nettle_hash_update_func
*
)
hmac_sha1_update
,
(
nettle_hash_digest_func
*
)
hmac_sha1_digest
,
SHA1_DIGEST_SIZE
,
ikm
->
length
,
ikm
->
data
,
prk
);
if
(
MEMEQ
(
SHA1_DIGEST_SIZE
,
prk
,
extract_output
->
data
)
==
0
)
{
fprintf
(
stdout
,
"
\n
Got:
\n
"
);
print_hex
(
SHA1_DIGEST_SIZE
,
prk
);
fprintf
(
stdout
,
"
\n
Expected:
\n
"
);
print_hex
(
extract_output
->
length
,
extract_output
->
data
);
abort
();
}
hmac_sha1_set_key
(
&
ctx
,
SHA1_DIGEST_SIZE
,
prk
);
hkdf_expand
(
&
ctx
,
(
nettle_hash_update_func
*
)
hmac_sha1_update
,
(
nettle_hash_digest_func
*
)
hmac_sha1_digest
,
SHA1_DIGEST_SIZE
,
info
->
length
,
info
->
data
,
expand_output
->
length
,
buffer
);
if
(
MEMEQ
(
expand_output
->
length
,
expand_output
->
data
,
buffer
)
==
0
)
{
fprintf
(
stdout
,
"
\n
Got:
\n
"
);
print_hex
(
expand_output
->
length
,
buffer
);
fprintf
(
stdout
,
"
\n
Expected:
\n
"
);
print_hex
(
expand_output
->
length
,
expand_output
->
data
);
abort
();
}
free
(
buffer
);
}
void
test_main
(
void
)
{
/* HKDF test vectors from RFC5869 */
test_hkdf_sha256
(
SHEX
(
"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"
),
SHEX
(
"000102030405060708090a0b0c"
),
SHEX
(
"f0f1f2f3f4f5f6f7f8f9"
),
SHEX
(
"077709362c2e32df0ddc3f0dc47bba6390b6c73bb50f9c3122ec844ad7c2b3e5"
),
SHEX
(
"3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865"
));
test_hkdf_sha256
(
SHEX
(
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
),
SHEX
(
"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
),
SHEX
(
"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
),
SHEX
(
"06a6b88c5853361a06104c9ceb35b45cef760014904671014a193f40c15fc244"
),
SHEX
(
"b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87"
));
test_hkdf_sha256
(
SHEX
(
"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"
),
SDATA
(
""
),
SDATA
(
""
),
SHEX
(
"19ef24a32c717b167f33a91d6f648bdf96596776afdb6377ac434c1c293ccb04"
),
SHEX
(
"8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8"
));
test_hkdf_sha1
(
SHEX
(
"0b0b0b0b0b0b0b0b0b0b0b"
),
SHEX
(
"000102030405060708090a0b0c"
),
SHEX
(
"f0f1f2f3f4f5f6f7f8f9"
),
SHEX
(
"9b6c18c432a7bf8f0e71c8eb88f4b30baa2ba243"
),
SHEX
(
"085a01ea1b10f36933068b56efa5ad81a4f14b822f5b091568a9cdd4f155fda2c22e422478d305f3f896"
));
test_hkdf_sha1
(
SHEX
(
"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f"
),
SHEX
(
"606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
),
SHEX
(
"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
),
SHEX
(
"8adae09a2a307059478d309b26c4115a224cfaf6"
),
SHEX
(
"0bd770a74d1160f7c9f12cd5912a06ebff6adcae899d92191fe4305673ba2ffe8fa3f1a4e5ad79f3f334b3b202b2173c486ea37ce3d397ed034c7f9dfeb15c5e927336d0441f4c4300e2cff0d0900b52d3b4"
));
test_hkdf_sha1
(
SHEX
(
"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"
),
SDATA
(
""
),
SDATA
(
""
),
SHEX
(
"da8c8a73c7fa77288ec6f5e7c297786aa0d32d01"
),
SHEX
(
"0ac1af7002b3d761d1e55298da9d0506b9ae52057220a306e07b6b87e8df21d0ea00033de03984d34918"
));
test_hkdf_sha1
(
SHEX
(
"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c"
),
SHEX
(
""
),
SHEX
(
""
),
SHEX
(
"2adccada18779e7c2077ad2eb19d3f3e731385dd"
),
SHEX
(
"2c91117204d745f3500d636a62f64f0ab3bae548aa53d423b0d1f27ebba6f5e5673a081d70cce7acfc48"
));
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment