Hi, when working on OCB, and trying to have some consistency between
similar functions, I'm looking at the various "all-in-one"
*_message_encrypt and *_message_decrypt functions. They are motivated in
part by convenience, for applications that always handle complete
messages, and in some cases because that's the only reasonable way (in
particular, CCM mode wants to have the message length as argument to
set_nonce).
In the simplest case, these functions would have a const block cipher
context as the only state that can be shared between messages, but in
some cases, there's additional setup that depends on the key but not
nonce or message, and then it's desirable to be able to share that, even
though it makes the interface more complex.
Some use a const struct nettle_cipher* to represent the cipher, some use
separate function pointers. So it's currently a bit messy. Let me list
the current functions (omitting most decrypt functions and specialized
functions for other ciphers than aes128, and including draft ocb):
void
ccm_encrypt_message(const void *cipher, nettle_cipher_func *f,
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);
More or less the simplest case, only needs a cipher context and the
encryption function. The tag length is configurable (which isn't the
case for all the modes).
void
ccm_aes128_encrypt_message(struct ccm_aes128_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);
This looks wrong, first argument ought to be "const struct aes128_ctx
*ctx".
void
ocb_encrypt_message (const struct ocb_key *ocb_key,
const void *cipher, nettle_cipher_func *f,
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);
The struct ocb_key holds ocb-specific subkeys, derived from the cipher
context. Could be omitted, but then they would have to be recomputed for
each call, so it's a trade-off between convenience and efficiency (and I
usually lean towards efficiency).
int
ocb_decrypt_message (const struct ocb_key *ocb_key,
const void *encrypt_ctx, nettle_cipher_func *encrypt,
const void *decrypt_ctx, nettle_cipher_func *decrypt,
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);
Similar, except that ocb has the peculiarity that it needs bothe the
encrypt and the decrypt function.
void
ocb_aes128_encrypt_message (const struct aes128_ctx *cipher,
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
ocb_aes128_decrypt_message (const struct aes128_ctx *cipher,
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);
Simpler aes128-specific variant. This draft doesn't include ocb_key,
it's recomputed for each call. The decrypt context is also recomputed
(via aes128_invert_key). Not sure that's the right choice.
void
siv_cmac_encrypt_message(const struct cmac128_key *cmac_key, const void
*cmac_cipher_ctx,
const struct nettle_cipher *nc,
const void *ctr_ctx,
size_t nlength, const uint8_t *nonce,
size_t alength, const uint8_t *adata,
size_t clength, uint8_t *dst, const uint8_t *src);
Uses "const struct nettle_cipher *nc" instead of separate function
pointers. Not sure that's the right choice, it needs only the encrypt
function (and then the siv_cmac_set_key function also uses the key_size
constant and the set_encrypt_key function. Argument order looks a bit odd.
void
siv_cmac_aes128_encrypt_message(const struct siv_cmac_aes128_ctx *ctx,
size_t nlength, const uint8_t *nonce,
size_t alength, const uint8_t *adata,
size_t clength, uint8_t *dst, const uint8_t
*src);
The struct siv_cmac_aes128_ctx collects the struct cmac128_key and the
two cipher contexts.
void
siv_gcm_encrypt_message (const struct nettle_cipher *nc,
const void *ctx,
void *ctr_ctx,
size_t nlength, const uint8_t *nonce,
size_t alength, const uint8_t *adata,
size_t clength, uint8_t *dst, const uint8_t *src);
Added recently. Uses struct nettle_cipher, for the encrypt and
set_encrypt_key function pointers, and key_size. The ctr_ctx is for
working storage, allocated but not initialized by the caller. Argument
order is not very consistent with the above siv_cmac functions.
void
siv_gcm_aes128_encrypt_message (const struct aes128_ctx *ctx,
size_t nlength, const uint8_t *nonce,
size_t alength, const uint8_t *adata,
size_t clength, uint8_t *dst, const uint8_t
*src);
This is rather nice and simple.
void
xts_encrypt_message(const void *enc_ctx, const void *twk_ctx,
nettle_cipher_func *encf,
const uint8_t *tweak, size_t length,
uint8_t *dst, const uint8_t *src);
This is not an AEAD mode, but interface is similar.
void
xts_aes128_encrypt_message(struct xts_aes128_key *xtskey,
const uint8_t *tweak, size_t length,
uint8_t *dst, const uint8_t *src);
The struct xts_aes128_key holds two cipher contexts, I think it's an
error that it's not const declared.
Not sure what changes are warranted. It would be good to fix the errors
on argument types for ccm and xts, but at least for ccm that's both an
API and an ABI change, so a bit tricky.
The immediate question is what the new ocb functions should look like.
Regards,
/Niels
--
Niels Möller. PGP key CB4962D070D77D7FCB8BA36271D8F1FF368C6677.
Internet email is subject to wholesale government surveillance.
_______________________________________________
nettle-bugs mailing list -- [email protected]
To unsubscribe send an email to [email protected]