[email protected] (Niels Möller) writes:

> Next, AEAD (authenticated encryption with associated data).

Some questions on a general abstraction for this, and my tentative answers:

Q: Should it expose the block size?

A: Yes. The caller must pass data in chunks which are an integral number
   of blocks. Motivation: (i) Byte-by-byte processing seems to be an
   obscure usecase, in particular for AEAD where you're not supposed to
   use the decrypted data for anything until the authentication is
   properly checked. (ii) This is how related nettle functions already
   work.


Q: Should we have a separate _digest function, which exposes the
   structure, of authentication tag appended to the crypto text?

A: Yes. Cons: For decryption, it's easier for the caller to pass the
   complete message, and not have to call digest and memcmp. Maybe there
   are some aead construction which doesn't do authentication by
   appending some kind of MAC at the end, so that is is verified by
   computing the same value and comparing it? I'm not aware of any,
   though.

   Pro: By having the caller separate ciphertext and tag, we avoid extra
   buffering in the implementation. And it simplifies the interface if
   the encrypt and decrypt functions have the same size for input and
   output, without having to delay processing until it is known that a
   piece of the data is ciphertext rather than tag.


Q: Should calling set_nonce be mandatory for each message, or should we
   provide automatically incrementing nonces, starting from zero?

A: Mandatory. Motivation: Some aead algorithms hash the nonce, and then
   we would need extra storage to be able to increment it. This includes
   EAX, and GCM with a nonce-size different from 12.


Q: Should the nonce size be fixed?

A: Yes. Motivation: For a given key, fixed nonce size is good enough for
   RFC 5116. It's unclear if there are use-cases for varying the nonce size,
   and if needed one can define separate nettle_aead objects differing
   only in nonce size.


Q: Should we include the rfc 5116 limits P_MAX and A_MAX?

A: No. Motivation: I think it's an obscure use-case to make decisions
   based on those limits at runtime. I'd expect a human to examine those
   limits when deciding which aead algorithms should be supported in a
   protocol or in an application.


Comments highly appreciated. This leads to the following abstraction:

  struct nettle_aead
  {
    const char *name;
    unsigned context_size;
    
    unsigned block_size;
    unsigned key_size;
    unsigned nonce_size;
    unsigned digest_size;
  
    nettle_set_key_func *set_encrypt_key;
    nettle_set_key_func *set_decrypt_key;
    nettle_set_key_func *set_nonce;
  
    nettle_crypt_func *encrypt;
    nettle_crypt_func *decrypt;

    nettle_hash_update_func *update;
    nettle_hash_digest_func *digest;
  };

The sequence of calls would be

  aead->set_encrypt_key(...);
  for (...)
    {
      aead->set_nonce(...);
      for (...) 
        aead->update(...);
      for (...) 
        aead->encrypt(...);
      aead->digest(...);
    }

For convenience maybe one could have a verify helper function which does
verify + memcmp. And helper functions for encrypting and decrypting of
complete messages, with no streaming, which I'd expect to be sufficient
for most aplications. Say,

  void
  aead_encrypt (const struct nettle_aead *aead, void *ctx, 
                const uint8_t *nonce, 
                size_t adata_size, const uint8_t *adata,
                size_t msg_size, uint8_t *gibberish, const uint8_t *msg);

  int
  aead_decrypt (const struct nettle_aead *aead, void *ctx, 
                const uint8_t *nonce, 
                size_t adata_size, const uint8_t *adata,
                size_t msg_size, uint8_t *msg, const uint8_t *gibberish);

where gibberish is of size msg_size + aead->digest_size.

Some possible extensions for things which aren't proper aead
constructions:

  If ->set_nonce is NULL, there's no nonce, and each key can be used for
  only a single message.

  If ->update is NULL, there can be no associated data

  If ->digest is NULL, there's no authentication, it's a stream cipher
  or CTR-mode or the like (but plain CBC doesn't fit, due to its padding
  needs)

  If ->encrypt and ->decrypt is NULL, it's a MAC mechanism

I think it may be a good idea to implement chacha-poly1305 before doing
this abstraction, so there's at least three different aead mechanism to
test it with.

Regards,
/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