Hi,
I'm trying to use the Nettle PBKDF2 functionality from Emacs.
This call (assume that the macros and variables are correct):
pbkdf2_hmac_sha1 (SCHARS (key), SDATA (key), XINT (iterations), SCHARS (salt), SDATA (salt), outlength, digest);
works great, but I'd like to be able to use any generic nettle_hash.
I tried this, given alg is a pointer to a nettle_hash:
HMAC_SET_KEY(ctx, alg, SCHARS (key), SDATA (key)); PBKDF2 (ctx, alg->update, alg->digest, alg->digest_size, XINT (iterations), SCHARS (salt), SDATA (salt), outlength, digest);
in many combinations but couldn't get it to work (the tests don't match up), and the docs don't explain how the PRF needs to be initialized. I tried to copy what pbkdf2_hmac_sha1() does but wasn't successful. Is there an example you could provide here or in the Nettle sources?
(The confusing part is that "ctx" is used for both the HMAC context (the one with inner, outer, and state contexts) and for the hashing state context itself. At one point in the macro chain the HMAC context is passed where a hashing state context is expected, I think, and I really need an example to ensure I'm doing it correctly. I am verifying with the RFC 6070 test vectors and can provide the full source if necessary.)
Thanks! Ted
Ted Zlatanov tzz@lifelogs.com writes:
I'm trying to use the Nettle PBKDF2 functionality from Emacs.
Cool! What will it be used for?
I tried this, given alg is a pointer to a nettle_hash:
HMAC_SET_KEY(ctx, alg, SCHARS (key), SDATA (key)); PBKDF2 (ctx, alg->update, alg->digest, alg->digest_size, XINT (iterations), SCHARS (salt), SDATA (salt), outlength, digest);
I'm afraid the HMAC_CTX macro, if that's what you are using, doesn't work so well with the nettle_hash abstraction. It wants to know the concrete type, e.g., struct sha1_ctx, which you don't have if you work with the struct nettle_hash interface.
In the above example, the ctx argument to HMAC_SET_KEY needs to have fields outer, inner and state, each with size (and struct offsets) matching alg->context_size. And the update and digest pointers passed to PBKDF2 must be update and digest for the HMAC operation, *not* for the underlying hash.
To use hmac with an arbitrary nettle_hash object, I'd suggest something like
struct hmac_gen_ctx { const struct nettle_hash *alg; uint8_t state[1]; /* Variable size; three hashing contexts */ };
struct hmac_gen_ctx * hmac_gen_new (const struct nettle_hash *alg, unsigned length, const uint8_t *key) { /* NOTE: This could possibly produce bad alignment; if so, allocate * separate storage for outer, inner and state, or round up the * context size. */ struct hmac_gen_ctx *ctx = xalloc (sizeof(*ctx) - 1 + 3*alg->context_size); ctx->alg = alg; hmac_set_key (ctx->state, /* outer */ ctx->state + ctx->alg->context_size, /* inner */ ctx->state + 2*ctx->alg->context_size, /* hmac state */ ctx->alg, length, key);
return ctx; }
void hmac_gen_update (struct hmac_gen_ctx *ctx, unsigned length, const uint8_t *data) { hmac_update(ctx->state + 2*ctx->alg->context_size, ctx->alg, length, data); }
void hmac_gen_digest (struct hmac_gen_ctx *ctx, unsigned length, uint8_t *digest) { hmac_digest (ctx->state, /* outer */ ctx->state + ctx->alg->context_size, /* inner */ ctx->state + 2*ctx->alg->context_size, /* hmac state */ ctx->alg, length, digest); }
Then you can can pass a struct hmac_gen_ctx * pointer together with the hmac_gen_update and hmac_gen_digest functions to the pbkdf2 call, like
pbkdf2_gen (const struct nettle_hash *alg, unsigned key_length, const uint8_t *key, unsigned iterations, unsigned salt_length, const uint8_t *salt, unsigned length, uint8_t *dst) { struct hmac_gen_ctx *prf = hmac_gen_new (alg, key_length, key); pbkdf2 (prf, (nettle_hash_update_func *) hmac_gen_update, (nettle_hash_digest_func *) hmac_gen_digest, alg->digest_size, iterations, salt_length, salt, length, *dst); free (prf); }
Code above totally untested, but I hope you get the idea.
Any concrete suggestions on how to improve the documentation?
Happy hacking, /Niels
On Sat, 05 Oct 2013 15:45:03 +0200 nisse@lysator.liu.se (Niels Möller) wrote:
NM> Ted Zlatanov tzz@lifelogs.com writes:
I'm trying to use the Nettle PBKDF2 functionality from Emacs.
NM> Cool! What will it be used for?
Exposing it for other packages (so it's a very bare implementation); my first goal is to write an OpenPGP-compatible signature verification package.
... NM> Code above totally untested, but I hope you get the idea.
Thanks, will try it ASAP :)
NM> Any concrete suggestions on how to improve the documentation?
It's pretty good, this was the one area not well covered so far. Let me finish the Emacs integration and then I can say better what's missing. I'll post issues with the code as I find them.
Ted
nettle-bugs@lists.lysator.liu.se