Maybe it's time to specify some nettle-meta.h types for stream ciphers and algorithms for authenticated encryption.
Currently we have nettle_hash, which I don't think needs any changes, and nettle_cipher, where I'm considering the following changes:
1. Drop the length argument from nettle_set_key_func.
2. Make the context argument of nettle_crypt_func const.
3. Previous point implies that we can no longer have struct nettle_cipher nettle_arcfour128. nettle_cipher will then be limited to block ciphers only.
Then there are some minor variations. Maybe nettle_crypt_func should be left unmodified, and we should have a new type, say nettle_cipher_func, for block ciphers with a const context.
What should the right abstraction look like for stream ciphers? Currently, arcfour, salsa20, and (soon) chacha. Consider
struct nettle_stream_cipher { const char *name;
unsigned context_size; unsigned key_size; unsigned nonce_size;
nettle_set_key_func *set_key; nettle_set_key_func *set_nonce;
nettle_crypt_func *crypt; };
Here, nettle_crypt_func should be the current definition without const. This assumes encryption and decryption are identical, which is the case for out current stream cipher list (and anything else xoring a stream to the plaintext). For arcfour, set_nonce would be NULL. Not sure how useful that really is to applications, ciphers with a nonce might not be used interchangably with a cipher that has no nonce.
So lacking features in that definition are
* Support for stream ciphers with different processing for encryption and decryption.
* Support for the random-access possibilities in salsa20 and chacha.
* Support for algorithms with arbitrary nonce size.
Also, internal block size is not visible. To use salsa20 with this interface, one would need a one-block buffer, and new logic to handle partial blocks.
For applications of stream ciphers, as well as ctr mode, is it important to be able to process a message byte by byte? Or is it sufficient to do like the current ctr and salsa20 code, to require that if a message is processed using several calls to the crypt function, all but the last must be an integral number of blocks? If we keep that requirement, we'd have to add a block_size field to struct nettle_stream_cipher.
Next, AEAD (authenticated encryption with associated data). Currently implemented algorithms are GCM and EAX. For internal use, nettle-internal.h currently defines
/* Tentative interface for "authenticated encryption with associated data" algorithms. Should be moved to nettle-meta.h when stable. */ struct nettle_aead { const char *name;
size_t context_size; /* Block size of the input, and the size of the output digest */ size_t block_size;
/* Suggested key size; other sizes are sometimes possible. */ size_t key_size;
nettle_set_key_func *set_key; nettle_set_key_func *set_iv; nettle_hash_update_func *update; nettle_crypt_func *encrypt; nettle_crypt_func *decrypt; nettle_hash_digest_func *digest; };
Like for stream ciphers, nettle_crypt_func is the variant without const; the context *is* modified as the message is processed.
Limitations:
* Assumes identical key setup for encrypt and decrypt, which is true for GCM and AEX (both based on CTR mode for the encryption). Do we need separate set_encrypt_key and set_decrypt_key functions?
* Assumes block size and digest size are identical. They might not be.
* set_iv should be renamed to set_nonce. Can the nonce be restricted to fixed size here? Both gcm and eax are specified for arbitrary nonce size. We may need two nettle_set_* function typedefs, one without length argument (used for set_key in all these abstractions), and one with a length argument, used for arbitrary size nonces, as well as any interfaces supporting variable key size.
One might use the same abstraction for constructions with no associated data (say, aes128-ctr-hmac-sha256) by setting update to NULL, or for schemes with no authentication at all, like aes 128-ctr, by also setting digest to NULL. Or for methods to provide authentication but no encryption, like hmac-sha256 or poly1305. But I doubt that's very useful.
Regards, /Niels