2 This file is part of GNUnet.
3 Copyright (C) 2010 GNUnet e.V.
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
22 * @file src/util/crypto_kdf.c
23 * @brief Key derivation
25 * @author Jeffrey Burdges <burdges@gnunet.org>
31 #include "gnunet_crypto_lib.h"
33 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
37 * @param result buffer for the derived key, allocated by caller
38 * @param out_len desired length of the derived key
40 * @param xts_len length of @a xts
41 * @param skm source key material
42 * @param skm_len length of @a skm
43 * @param argp va_list of void * & size_t pairs for context chunks
44 * @return #GNUNET_YES on success
47 GNUNET_CRYPTO_kdf_v (void *result, size_t out_len,
48 const void *xts, size_t xts_len,
49 const void *skm, size_t skm_len,
53 * "Finally, we point out to a particularly advantageous instantiation using
54 * HMAC-SHA512 as XTR and HMAC-SHA256 in PRF* (in which case the output from SHA-512 is
55 * truncated to 256 bits). This makes sense in two ways: First, the extraction part is where we need a
56 * stronger hash function due to the unconventional demand from the hash function in the extraction
57 * setting. Second, as shown in Section 6, using HMAC with a truncated output as an extractor
58 * allows to prove the security of HKDF under considerably weaker assumptions on the underlying
61 * http://eprint.iacr.org/2010/264
64 return GNUNET_CRYPTO_hkdf_v (result, out_len, GCRY_MD_SHA512, GCRY_MD_SHA256,
65 xts, xts_len, skm, skm_len, argp);
71 * @param result buffer for the derived key, allocated by caller
72 * @param out_len desired length of the derived key
74 * @param xts_len length of @a xts
75 * @param skm source key material
76 * @param skm_len length of @a skm
77 * @param ... void * & size_t pairs for context chunks
78 * @return #GNUNET_YES on success
81 GNUNET_CRYPTO_kdf (void *result, size_t out_len,
82 const void *xts, size_t xts_len,
83 const void *skm, size_t skm_len, ...)
88 va_start (argp, skm_len);
89 ret = GNUNET_CRYPTO_kdf_v (result, out_len, xts, xts_len, skm, skm_len, argp);
97 * Deterministically generate a pseudo-random number uniformly from the
98 * integers modulo a libgcrypt mpi.
100 * @param[out] r MPI value set to the FDH
101 * @param n MPI to work modulo
103 * @param xts_len length of @a xts
104 * @param skm source key material
105 * @param skm_len length of @a skm
106 * @param ctx context string
109 GNUNET_CRYPTO_kdf_mod_mpi (gcry_mpi_t *r,
111 const void *xts, size_t xts_len,
112 const void *skm, size_t skm_len,
120 nbits = gcry_mpi_get_nbits (n);
121 /* GNUNET_assert (nbits > 512); */
125 /* Ain't clear if n is always divisible by 8 */
126 uint8_t buf[ (nbits-1)/8 + 1 ];
128 rc = GNUNET_CRYPTO_kdf (buf,
135 GNUNET_assert (GNUNET_YES == rc);
137 rc = gcry_mpi_scan (r,
139 (const unsigned char *) buf,
142 GNUNET_assert (0 == rc); /* Allocation erro? */
144 gcry_mpi_clear_highbit (*r, nbits);
145 GNUNET_assert( 0 == gcry_mpi_test_bit (*r, nbits) );
147 /* We reject this FDH if either *r > n and retry with another ctr */
148 } while ( 0 <= gcry_mpi_cmp(*r,n) );