On Tue, Jan 23, 2018 at 7:34 PM, Niels Möller nisse@lysator.liu.se wrote:
Nikos Mavrogiannopoulos nmav@redhat.com writes:
As it is now AEAD ciphers in nettle are supported with their own API. AES-CCM provides: ccm_aes128_set_key ccm_aes128_set_nonce ccm_aes128_update ccm_aes128_encrypt ccm_aes128_decrypt ccm_aes128_digest ccm_aes128_encrypt_message ccm_aes128_decrypt_message
I've considered ccm odd because it doesn't support a "streaming" mode where the mesage length isn't known up-front.
It seems that the streaming mode is not a feature of AEAD ciphers. The AES-SIV-CMAC is similar in that aspect as the whole plaintext is needed to create the IV.
AES-GCM: gcm_aes128_set_key gcm_aes128_update gcm_aes128_set_iv
And gcm is a bit special because it uses pretty large tables which depend on the key but not the nonce. And it would make sense to rename set_iv to set_nonce, for consitency.
Would be nice.
chacha-poly1305: chacha_poly1305_set_key chacha_poly1305_set_nonce chacha_poly1305_update chacha_poly1305_encrypt chacha_poly1305_decrypt chacha_poly1305_digest
These are the methods I'd expect "most" AEADs to have, and it's what the nettle_aead struct is intended to capture. But maybe there are too many exceptions. It's good to have several examples to consider.
I think that the nettle_aead is too specific to gcm. chacha20-poly1305 fitted in there, but it seems that other AEAD ciphers would not fit.
I'm checking the AES-SIV-CMAC mode which cannot even be put in that abstraction as the MAC in SIV is the IV and thus the MAC-style API doesn't really suit it.
Does that mean that it processes data twice (first mac, then encryption), so that it can't support "streaming" mode at all, even if lenghts are provided up front?
Right. It is tailored towards packet/message encryption.
My understanding is that AEAD modes according to RFC5116 need to have 4 inputs: key, nonce, associated data, plaintext so the CCM encrypt and decrypt message seem to be the closer to that API. Would it make sense to standardize on these, and only provide that API for AEAD modes?
It would make a lot of sense to have some convenience functions to do that, which are consistent between AEADs. However, I think I'd prefer to at least make the set_key method separate, to avoid redoing all of the key setup per message. So then we'de have something similar to the ccm_*_message functions. Should the nonce length and tag length be variable per message?
The tag is fixed since it is used as the IV. On the branch I'm working on I have the following interface:
struct siv_aes128_cmac_ctx { struct aes128_ctx cipher; uint8_t s2vk[AES128_KEY_SIZE]; };
void siv_aes128_cmac_set_key(struct siv_aes128_cmac_ctx *ctx, const uint8_t *key);
void siv_aes128_cmac_encrypt_message(struct siv_aes128_cmac_ctx *ctx, size_t nlength, const uint8_t *nonce, size_t alength, const uint8_t *adata, size_t tlength, size_t clength, uint8_t *dst, const uint8_t *src);
int siv_aes128_cmac_decrypt_message(struct siv_aes128_cmac_ctx *ctx, size_t nlength, const uint8_t *nonce, size_t alength, const uint8_t *adata, size_t tlength, size_t mlength, uint8_t *dst, const uint8_t *src);
Would it be useful with a separate area for reading and writing the tag, or should we always attach the tag at the end of the ciphertext, like the current _message functions?
I think the expectation is to prepend the tag/IV to the message. As the message interface above doesn't distinguish between tag and ciphertext, I think it quite conveniently fits it.
The reason I'm asking is because SIV could benefit of a very custom API as well because it can take advantage of multiple associated data, but in the end I believe AEAD is about simplicity. Providing a unique API per AEAD cipher seems to me quite contradictory to that goal.
I think it's nice to support special features of SIV, but using those functions should be optional.
A possible interface could be: void siv_aes128_cmac_set_key(struct siv_aes128_cmac_ctx *ctx, const uint8_t *key) void siv_aes128_cmac_s2v(struct siv_aes128_cmac_ctx *ctx, size_t nlength, const uint8_t *nonce, size_t adatalen, size_t *alength, const uint8_t **adata, size_t plength, size_t pdata);
(notice the pointer to pointer for adata)
The generic non-aes version of it should also contain the pointers to relevant CMAC functions such as: nettle_set_key_func *cmac_set_key, nettle_hash_update_func *cmac_update, nettle_hash_digest_func *cmac_digest and the size of context.
I think with all these parameters, the current API I have could be classified as unbearable even for a low-level one.
regards, Nikos