nisse@lysator.liu.se (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