Daniel Kahn Gillmor dkg@fifthhorseman.net writes:
can we define an cipher abstraction that exposes the relevant details in C, provides a framework that is suitable for symmetric decryption, and doesn't violate the minimalistic flavor of nettle?
Feel free to try...
Some points to keep in mind:
1. I think the current nettle_cipher is useful for some applications, even if it's not suitable for language bindings which want to provide access to everything available.
2. Error checking at set_key
So far, i think the errors i've heard are:
bad key size
weak key
Anything else?
One could possibly add parity error for DES, but I doubt anyone really cares about that. One *might* want to make some distinction between "hard" errors, like bad key sizes, and "soft" errors or warnings like weak keys, where the resulting cipher context still can be used, if desired.
3. The set of supported key sizes.
This is the issue with most potential for making things hairy (and this information is not provided by nettle's cipher specific interfaces either; there's a define for a single "recommended" key size, and when applicable there are defines for the minimum and maximum key size. But the user has to look in the documentation to find out which key sizes in this range are actually supported).
Do we want a way to report the range of acceptable key sizes for a given cipher?
I think a general algorithm abstraction ought to provide that. And I think the model for this more general abstraction should be that ciphers are parametrized by key size, which is different from current nettle_cipher (and the design of your perl bindings) which is unaware that the two ciphers aes-128 and aes-256 are in fact related.
There are two types of queries one could support:
a) The ability to ask if a particular key size is ok.
b) The ability to get the complete set of available key sizes.
From a minimality perspective, it seems undesirable to have both, since
a) can be done on top of b). But I think it makes a lot of sense to have the set_key function of this interface check key sizes, thereby almost supporting a) (one would have to provide a particular key, not just a key size). For b), the simplest way that occurs to me would be to export a list of ranges. Something like
struct keysize_range { unsigned short start; unsigned short length; };
Then put a pointer to an array of those structs, sorted by start, into the new nettle_cipher struct, terminated by an entry with length == 0. So for aes, one would have
{{ 16, 1 }, {24, 1}, {32, 1}, {0, 0}}
and for blowfish,
{{BLOWFISH_MIN_KEY_SIZE, BLOWFISH_MAX_KEY_SIZE + 1 - BLOWFISH_MIN_KEY_SIZE}, {0,0}}
Would this be useful? For a particular usecase, could you use something like this in your perl bindings, and would that imply a design change switching to treat AES as a single cipher with several possible key sizes, rather than as three different ciphers?
And that said, I think the model of current nettle_cipher, which treats aes128 and aes256 as different ciphers, is also useful in some cases. I don't know how to reconcile the two views. I'd prefer to not have multiple nettle_cipher-like abstractions in nettle itself.
Regards, /Niels