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

Reply via email to