Directions for crypto make_checksum/verify_checksum

ghudson@MIT.EDU ghudson at MIT.EDU
Mon Dec 7 12:34:42 EST 2009

I am working on firming up the module SPI for crypto modularity.  The
biggest problem in this area right now is keyhash providers, because
they live in the krb directory but make use of low-level encryption
and hash primitives from the modules.

Currently the logic for krb5_[ck]_make_checksum[_iov] goes through two
tables.  The checksum type is looked up in a table, which determines
one of three possible handlings:

  1. Use a keyhash_provider.
  2. Go through krb5int_dk_make_checksum (which does derived-key HMAC
     using the unkeyed hash provider in the table).
  3. Use a hash_provider to perform an unkeyed checksum.

At first glance, keyhash providers look like a minor variation on hash
providers, but from an implementation perspective they are actually
more like enctype functions: they perform a combination of key
derivations, encryptions, unkeyed hashes, and/or HMACs to create a
token in a Kerberos-specific format.  Therefore, I don't think it
sense to move keyhash providers into the module subdirs.  The current
keyhash provider tokens are:

* descbc: ivec resulting from des-cbc(input)
* hmac_md5: HMAC(HMAC(key, "signaturekey\0"), MD5(usage | input))
* md5_hmac: HMAC(key, MD5(usage | input))
* md4des: des(xorkey, confounder | MD4(confounder | data))
* md5des: des(xorkey, confounder | MD5(confounder | data))

and then the non-keyhash provider tokens are:

* unkeyed: hash(input)
* DK: HMAC(KC, input) where KC is PBKDF2-derived with key usage
  and the HMAC's hash varies according to the checksum type

Aside from some general uncleanliness, the big problem is that descbc
makes use of two internal DES APIs (key scheduling and CBC ivec
computation), and the MD4/MD5-using keyhash providers directly use
internal MD4/MD5 APIs instead of the MD4/MD5 hash providers.  As a
result, those internal DES, MD4, and MD5 APIs are effectively part of
the module SPI, in addition to the enc and hash provider interfaces
implementing the same functionality.

I am currently thinking about a design which throws out the
keyhash_provider concept (which is only used for checksums) and more
closely parallels the way enctypes work.  The idea is that the
checksum table includes:

* A hash provider (already present; the keyhash provider goes away)
* An enc provider (the existing enctype field goes away)
* A function to compute checksums (taking IOV inputs)
* A function to verify checksums (taking IOV inputs), which is optional
* A flags field to indicate whether the checksum is keyed and coll-proof
  (flags field already exists, but the DERIVED flag would go away)
* A truncation size (already existing)

The checksum and verify functions would parallel the encrypt and
encrypt functions of the enctypes table.  The functions I have in mind
are (HMACs always use the hash from the checksum table):

* unkeyed_checksum: computes hash(input)
* dk_checksum: computes HMAC(KC, input)
* cbc_checksum: computes enc(input) and returns the resulting ivec
* confounder_checksum, confounder_verify:
  computes enc(xorkey, confounder | hash(confounder | data))
* hmacmd5_checksum: computes HMAC(KC, hash(usage | input))
  where KC is HMAC(key, "signaturekey\0") for hmac_md5,
  or just the key for md5_hmac

Note that cbc_checksum would have to allocate a temporary buffer to
store the encrypted output in order to compute the resulting ivec,
which is less efficient than the current mechanism of computing descbc
checksums.  I think that's a small price to pay for a smaller module
SPI footprint, since I don't think the descbc checksum type gets any
significant use.

Does this plan seem sane?

More information about the krbdev mailing list