Crypto IOV/non-IOV code consolidation

ghudson@MIT.EDU ghudson at MIT.EDU
Tue Nov 17 15:51:09 EST 2009

There is a lot of code duplication in libk5crypto right now for three

  1. The IOV code was added in in parallel to the existing code,
     duplicating much of the non-IOV code.

  2. The AES derived-key code was added in in parallel to the existing
     DES3 derived-key key, duplicating much of it.  (Only for the
     normal path, though; the IOV implementation factors out the
     differing code.)

  3. Encryption and decryption code commonly does a lot of the same
     derived-key logic.  I don't plan to do anything about that at
     this time, but it does add another factor of two.

As a result, you can run across the same bit of logic as many as six
times while traversing the library.

The simplest starting point would be to take advantage of the existing
hatch in krb5_k_encrypt, which invokes krb5int_c_encrypt_aead_compat
if the enctype entry has no encrypt function (and likewise for
decryption).  That would allow us to eliminate the non-IOV encryption

Tom has expressed concerns about the extra copying in the aead_compat
functions resulting from the IOV code assuming in-place encryption and
decryption.  I am not certain whether these copies have a significant
impact on performance, but I believe we can eliminate the need for
them by using a unified internal interface which would look a bit

    krb5_error_code (*encrypt)(<pointers to providers>,
                               krb5_key key, krb5_keyusage keyusage,
                               krb5_data *ivec,
                               krb5_crypto_iov *input, krb5_crypto_iov *output,
                               size_t num_data);

(And similarly for decrypt.)  The IOV interfaces would pass the same
iov pointer for input and output.  The non-IOV interfaces would
construct separate fixed-length iovs for input and output.

I'm hoping to find time to do this bit of code reorg.  Some notes:

* The input and output iov structures aren't intrinsically parallel;
  the ciphertext contains a header, padding, and trailer while the
  plaintext is only data.  At this point I don't know whether the
  non-IOV APIs will construct plaintext IOV structures containing
  dummy header/padding/trailer entries so that the input and output
  have a 1:1 correspondence.

* krb5int_c_iov_{get,put}_block (internal functions used by the
  enc_provider implementations) will need some massaging.

* I'd like to eliminate the aead_provider structure at the same time,
  since it is confusing to have provider structures at two different
  levels of abstraction.  Since krb5int_dk_encrypt_iov needs to be
  polymorphic in which crypto_length function it calls, the enctype
  encrypt/decrypt functions will probably just receive a pointer to
  the enctype entry instead of the enc/hash/aead providers, and the
  crypto_length function will move from aead_provider to the enctype

* Another bit of grossness is that gss-krb5 calls into krb5int_hmac,
  passing a pointer to the RC4 enc_provider and the MD5 hash_provider.
  (All three symbols are obtained via krb5int_accessor.)  I need to
  take a good hard look at that to see whether it can be cleaned up.
  At a minimum it will need to be adjusted since the non-IOV functions
  it relies on will be going away.

More information about the krbdev mailing list