Ted Zlatanov <[email protected]> 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
--
Niels Möller. PGP-encrypted email is preferred. Keyid C0B98E26.
Internet email is subject to wholesale government surveillance.
_______________________________________________
nettle-bugs mailing list
[email protected]
http://lists.lysator.liu.se/mailman/listinfo/nettle-bugs