* @see http://www.rfc-editor.org/rfc/rfc5869.txt
* @todo remove GNUNET references
* @author Nils Durner
+ *
+ * The following list of people have reviewed this code and considered
+ * it correct on the date given (if you reviewed it, please
+ * have your name added to the list):
+ *
+ * - Christian Grothoff (08.10.2010)
+ * - Nathan Evans (08.10.2010)
+ * - Matthias Wachs (08.10.2010)
*/
-#include <gcrypt.h>
+#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
+
+/**
+ * Set this to 0 if you compile this code outside of GNUnet.
+ */
+#define GNUNET_BUILD 1
+
+/**
+ * Enable debugging.
+ */
+#define DEBUG_HKDF 0
+
+
+#if GNUNET_BUILD
#include "platform.h"
#include "gnunet_crypto_lib.h"
+#else
+#define GNUNET_NO 0
+#define GNUNET_YES 1
+#define GNUNET_SYSERR -1
+#include <stdlib.h>
+#endif
+
+#include <gcrypt.h>
-#define DEBUG_HKDF GNUNET_NO
/**
* @brief Compute the HMAC
* @return HMAC, freed by caller via gcry_md_close/_reset
*/
static const void *
-doHMAC (gcry_md_hd_t mac,
- const void *key, size_t key_len,
- const void *buf, size_t buf_len)
+doHMAC (gcry_md_hd_t mac, const void *key, size_t key_len, const void *buf,
+ size_t buf_len)
{
gcry_md_setkey (mac, key, key_len);
gcry_md_write (mac, buf, buf_len);
* @brief Generate pseudo-random key
* @param mac gcrypt HMAC handle
* @param xts salt
- * @param xts_len length of the salt
+ * @param xts_len length of the @a xts salt
* @param skm source key material
- * @param skm_len length of skm
+ * @param skm_len length of @a skm
* @param prk result buffer (allocated by caller; at least gcry_md_dlen() bytes)
- * @return GNUNET_YES on success
+ * @return #GNUNET_YES on success
*/
static int
-getPRK (gcry_md_hd_t mac,
- const void *xts, size_t xts_len,
- const void *skm, size_t skm_len,
- void *prk)
+getPRK (gcry_md_hd_t mac, const void *xts, size_t xts_len, const void *skm,
+ size_t skm_len, void *prk)
{
const void *ret;
ret = doHMAC (mac, xts, xts_len, skm, skm_len);
if (ret == NULL)
return GNUNET_SYSERR;
- memcpy (prk,
- ret,
- gcry_md_get_algo_dlen (gcry_md_get_algo (mac)));
+ GNUNET_memcpy (prk, ret, gcry_md_get_algo_dlen (gcry_md_get_algo (mac)));
return GNUNET_YES;
}
#if DEBUG_HKDF
-static void
-dump(const char *src,
- const void *p,
- unsigned int l)
+static void
+dump (const char *src, const void *p, unsigned int l)
{
unsigned int i;
- printf("\n%s: ", src);
+ printf ("\n%s: ", src);
for (i = 0; i < l; i++)
- {
- printf("%2x", (int) ((const unsigned char *) p)[i]);
- }
- printf("\n");
+ {
+ printf ("%2x", (int) ((const unsigned char *) p)[i]);
+ }
+ printf ("\n");
}
#endif
* @param xtr_algo hash algorithm for the extraction phase, GCRY_MD_...
* @param prf_algo hash algorithm for the expansion phase, GCRY_MD_...
* @param xts salt
- * @param xts_len length of xts
+ * @param xts_len length of @a xts
* @param skm source key material
- * @param skm_len length of skm
+ * @param skm_len length of @a skm
* @param argp va_list of void * & size_t pairs for context chunks
- * @return GNUNET_YES on success
+ * @return #GNUNET_YES on success
*/
int
-GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len,
- int xtr_algo, int prf_algo,
- const void *xts, size_t xts_len,
- const void *skm, size_t skm_len,
- va_list argp)
+GNUNET_CRYPTO_hkdf_v (void *result, size_t out_len, int xtr_algo, int prf_algo,
+ const void *xts, size_t xts_len, const void *skm,
+ size_t skm_len, va_list argp)
{
+ gcry_md_hd_t xtr;
+ gcry_md_hd_t prf;
const void *hc;
- unsigned long i, t, d;
+ unsigned long i;
+ unsigned long t;
+ unsigned long d;
unsigned int k = gcry_md_get_algo_dlen (prf_algo);
unsigned int xtr_len = gcry_md_get_algo_dlen (xtr_algo);
char prk[xtr_len];
int ret;
- gcry_md_hd_t xtr, prf;
size_t ctx_len;
va_list args;
- if (k == 0)
- return GNUNET_SYSERR;
-
- // FIXME: what is the check for?
- if (out_len > (2 ^ 32 * k))
+ if (0 == k)
return GNUNET_SYSERR;
-
- if (gcry_md_open(&xtr, xtr_algo, GCRY_MD_FLAG_HMAC) != GPG_ERR_NO_ERROR)
+ if (GPG_ERR_NO_ERROR !=
+ gcry_md_open (&xtr, xtr_algo, GCRY_MD_FLAG_HMAC))
return GNUNET_SYSERR;
-
- if (gcry_md_open(&prf, prf_algo, GCRY_MD_FLAG_HMAC) != GPG_ERR_NO_ERROR)
+ if (GPG_ERR_NO_ERROR !=
+ gcry_md_open (&prf, prf_algo, GCRY_MD_FLAG_HMAC))
{
gcry_md_close (xtr);
return GNUNET_SYSERR;
}
-
va_copy (args, argp);
ctx_len = 0;
while (NULL != va_arg (args, void *))
- ctx_len += va_arg (args, size_t);
- va_end(args);
+ ctx_len += va_arg (args, size_t);
+
+ va_end (args);
memset (result, 0, out_len);
- if (getPRK (xtr, xts, xts_len, skm, skm_len, prk)
- != GNUNET_YES)
+ if (getPRK (xtr, xts, xts_len, skm, skm_len, prk) != GNUNET_YES)
goto hkdf_error;
#if DEBUG_HKDF
- dump("PRK", prk, xtr_len);
+ dump ("PRK", prk, xtr_len);
#endif
t = out_len / k;
/* K(1) */
{
- size_t plain_len = k + ctx_len + 1;
- char plain[plain_len];
- const void *ctx;
- char *dst;
-
- dst = plain + k;
- va_copy (args, argp);
- while ((ctx = va_arg (args, void *)))
- {
- size_t len;
-
- len = va_arg (args, size_t);
- memcpy (dst, ctx, len);
- dst += len;
- }
- va_end (args);
-
- if (t > 0)
+ size_t plain_len = k + ctx_len + 1;
+ char plain[plain_len];
+ const void *ctx;
+ char *dst;
+
+ dst = plain + k;
+ va_copy (args, argp);
+ while ((ctx = va_arg (args, void *)))
+ {
+ size_t len;
+
+ len = va_arg (args, size_t);
+ GNUNET_memcpy (dst, ctx, len);
+ dst += len;
+ }
+ va_end (args);
+
+ if (t > 0)
{
memset (plain + k + ctx_len, 1, 1);
#if DEBUG_HKDF
- dump("K(1)", plain, plain_len);
+ dump ("K(1)", plain, plain_len);
#endif
- hc = doHMAC (prf,
- prk,
- xtr_len, &plain[k], ctx_len + 1);
+ hc = doHMAC (prf, prk, xtr_len, &plain[k], ctx_len + 1);
if (hc == NULL)
goto hkdf_error;
- memcpy (result, hc, k);
+ GNUNET_memcpy (result, hc, k);
result += k;
}
- /* K(i+1) */
- for (i = 1; i < t; i++)
+ /* K(i+1) */
+ for (i = 1; i < t; i++)
{
- memcpy (plain, result - k, k);
+ GNUNET_memcpy (plain, result - k, k);
memset (plain + k + ctx_len, i + 1, 1);
gcry_md_reset (prf);
#if DEBUG_HKDF
- dump("K(i+1)", plain, plain_len);
+ dump ("K(i+1)", plain, plain_len);
#endif
hc = doHMAC (prf, prk, xtr_len, plain, plain_len);
if (hc == NULL)
goto hkdf_error;
- memcpy (result, hc, k);
+ GNUNET_memcpy (result, hc, k);
result += k;
}
- /* K(t):d */
- if (d > 0)
+ /* K(t):d */
+ if (d > 0)
{
if (t > 0)
- memcpy (plain, result - k, k);
- memset (plain + k + ctx_len, i + 1, 1);
+ {
+ GNUNET_memcpy (plain, result - k, k);
+ i++;
+ }
+ memset (plain + k + ctx_len, i, 1);
gcry_md_reset (prf);
#if DEBUG_HKDF
- dump("K(t):d", plain, plain_len);
+ dump ("K(t):d", plain, plain_len);
#endif
if (t > 0)
hc = doHMAC (prf, prk, xtr_len, plain, plain_len);
hc = doHMAC (prf, prk, xtr_len, plain + k, plain_len - k);
if (hc == NULL)
goto hkdf_error;
- memcpy (result, hc, d);
+ GNUNET_memcpy (result, hc, d);
}
#if DEBUG_HKDF
- dump("result", result - k, out_len);
+ dump ("result", result - k, out_len);
#endif
- ret = GNUNET_YES;
- goto hkdf_ok;
+ ret = GNUNET_YES;
+ goto hkdf_ok;
}
hkdf_error:
ret = GNUNET_SYSERR;
hkdf_ok:
- gcry_md_close (prf);
gcry_md_close (xtr);
-
+ gcry_md_close (prf);
return ret;
}
* @param xtr_algo hash algorithm for the extraction phase, GCRY_MD_...
* @param prf_algo hash algorithm for the expansion phase, GCRY_MD_...
* @param xts salt
- * @param xts_len length of xts
+ * @param xts_len length of @a xts
* @param skm source key material
- * @param skm_len length of skm
- * @param ctx context info
- * @param ctx_len length of ctx
- * @return GNUNET_YES on success
+ * @param skm_len length of @a skm
+ * @return #GNUNET_YES on success
*/
int
-GNUNET_CRYPTO_hkdf (void *result, size_t out_len,
- int xtr_algo, int prf_algo,
- const void *xts, size_t xts_len,
- const void *skm, size_t skm_len,
- ...)
+GNUNET_CRYPTO_hkdf (void *result, size_t out_len, int xtr_algo, int prf_algo,
+ const void *xts, size_t xts_len, const void *skm,
+ size_t skm_len, ...)
{
va_list argp;
int ret;
- va_start(argp, skm_len);
- ret = GNUNET_CRYPTO_hkdf_v (result, out_len, xtr_algo, prf_algo, xts,
- xts_len, skm, skm_len, argp);
- va_end(argp);
+ va_start (argp, skm_len);
+ ret =
+ GNUNET_CRYPTO_hkdf_v (result, out_len, xtr_algo, prf_algo, xts, xts_len,
+ skm, skm_len, argp);
+ va_end (argp);
return ret;
}