questions regarding master key enctype migration
Ken Raeburn
raeburn at MIT.EDU
Wed Feb 27 01:13:53 EST 2008
I dug up some design notes from last year on this project. I had
expected to add a couple new TL-data types to the database for
supporting multiple master key versions. Sorry I didn't remember the
specifics when we talked Monday.
Here are the notes:
> Currently the DAL assumes there is one "master key". Rather than
> rewrite big chunks of it, I'm taking the approach that the supplied
> "master key" needs to be enough to get at all the keys that are
> used to encrypt principal keys in the database. Actually, from
> what I'm doing, it would be a very small step to decouple the set
> of keys used to encrypt principals' keys in the database from the
> set of keys any one of which is needed to gain access to the former
> set; they don't actually need to be the same. And with the changes
> I'm looking at, the master principal entry will become a single
> point of failure, in the sense that if that entry is lost to
> database corruption, some fraction of principals' keys may be lost,
> whereas currently they can be recovered with the master key that
> may also be stored in the stash file.
>
> First, change the stash file to a keytab file, so it can store kvno
> and enctype. It *can* store multiple keys, but only *needs* to
> have one.
>
> I'm thinking of introducing two new TL data types in the database.
>
> The first, KRB5_TL_MKVNO, would apply to all principals but K/M,
> and would store the version number of the master key used to
> encrypt the keys of that principal. The db2 back end would store
> it as opaque TL-data, but I think the LDAP back end has a slot for it.
>
> The second, KRB5_TL_MKEY_AUX, would apply only to K/M, which still
> has one key encrypted in itself. This new TL data would contain
> all the additional master-key related info that needs to be
> introduced by this change:
>
> * The default master key version number for principals that have
> not yet had the other TL-data type added. (Optional; must be used
> when this TL data is initially created, but can be removed when the
> indicated mkvno is purged.)
>
> * The master key version number that should be used when changing
> database entries. (I think it would actually be safe to always use
> the latest, because principal data encrypted in it should never
> reach a slave server before the updated K/M, but do we require that
> all database back ends that handle propagation of changes do so
> fully serialized? If we make that assumption, this field goes
> away. But if there's any doubt, we should use it. Alternatively,
> the lists below could include future key versions if the current
> key isn't the just-added one.) This field (or the current kvno)
> would probably be cached along with the keys, so after a new key is
> introduced, at some point, servers using the database should be
> restarted or otherwise told to re-check K/M. Trying to decrypt a
> principal key encrypted using the newest mkvno would trigger a re-
> read of the K/M key data, and this cached datum should probably be
> updated at the same time.
>
> * The other master keys still supported, in {kvno,keydata,enctype}
> tuples, with keys encrypted in the current K/M key.
>
> * The current key for K/M, encrypted in each of the other
> supported keys, in {old-kvno,keydata} tuples. Thus the "master
> key" used in DAL need only be any one of these keys.
>
> * Trailing stuff is ignored for now, making the structure extensible.
>
> These two lists of keys don't actually need to be kept in sync.
> The first must include all keys in which any principal keys are
> encrypted, and the second must include all old master keys that
> could be stored in any KDC's stash file or could be in use by
> running processes as "the master key". But unless we decide to
> decouple them, for now they'll use the same sets of keys.
>
> I'm assuming that for each key version number, there will be only
> one master key, with one enctype.
>
> Q: Do we want to be able to use non-default salt strings for the
> master keys? We don't currently, but if so, salt strings for old
> keys need to be stored too.
>
> When a new master key is installed (via kdb5_util or maybe
> kadmin.local), the TL data hanging off K/M needs to be updated
> simultaneously to move the old key into the old-keys list, encrypt
> the new key in all the old keys, and update the default mkvno to
> use. With these updated all at once, the KDC doesn't have to be
> taken offline.
>
> Removing an old key is trickier, and will need steps documented
> that the administrator must run in order. The admin must manually
> ensure that all KDC stash files have been updated to newer keys,
> and the KDCs restarted to use them. A new command in kdb5_util or
> kadmin.local will iterate over all principals, and re-encrypt the
> key data for any principals using an mkvno older than some
> specified minimum; any password-changing servers like kadmind
> should be taken offline while this is done, in case password
> changes happen around the same time. Then the old now-unused entry
> is removed from K/M. If we don't fully serialize data propagation,
> the re-encrypting and the K/M pruning should be two separated
> steps, with the second run after the administrator is confident the
> new data has propagated. (And if re-encrypting is runnable on a
> per-principal basis, a clueful admin might be able to do a more
> efficient search of the back-end database directly, reducing the
> interval in which kadmind must be offline.)
>
> Every place in the code that uses the master key needs to either
> have the key set available, have the correct key from the set
> available, or have the database accessible so the other keys can be
> fetched. Old keys may be cached for performance, but the code must
> be capable of going back to the database if a mkvno is mentioned
> that isn't in the cached set.
>
> krb5_dbekd_encrypt_key_data: Every caller needs to be updated to
> ensure that it uses the current master key version (which would be
> cached, along with all the keys).
>
> krb5_dbekd_decrypt_key_data: Every caller needs to be updated to
> ensure that it uses the master key version indicated by the TL data
> for the principal, or the default indicated in the K/M TL data.
> Same cache as above.
>
> krb5_def_verify_master_key: Already fetches the master principal
> record, needs to examine the TL data, perhaps do multiple
> decryption calls.
>
> kdb keytab: Gets a database handle, so it can look up K/M and
> extract the correct key. The K/M key data could be cached in ktkdb
> private data, which we don't use currently.
>
> kdb5_util: The v4 code is not currently used; ignore it or delete
> it. The dump code needs updating in the code that allows offline
> updating of the master key, unless we just rip it out and tell
> people to use the new approach. Since that code won't work well in
> an LDAP environment, removing it after this new code is working is
> probably the better choice.
>
>
> kdb5_util gets new commands:
> * update_stash (extracts current master key and updates stash file
> -- include old ones in keytab format?)
> * change_master_key (accepts new password or -random, -e to set
> etype)
> * use_new_master_key maybe (switches default-mkvno-to-use to
> latest or specified)
> * prune_old_master_key
> * list_master_keys (shows current+old kvno and etype)
> * possibly a separate step to re-encrypt either all keys not using
> current mkvno, or just those using the old one(s) to be pruned soon
>
> Q: Do we want anything like "mark as requiring immediate password
> change all principals with keys encrypted using mkvno <= N"?
>
> We should probably consider getting rid of global variables
> master_keyblock, master_princ, hist_princ, hist_key, hist_kvno,
> etc, exported by libkadm5srv. Just master_keyblock has >130
> references in the tree, though some are local variables in test
> programs.
>
> -------
>
> Secondary project: Change stash files to use keytab format, with
> backwards compatibility. Then we can store key data, etype, and
> kvno together. This will allow easier changing of master key type,
> and let us decrypt the current master key from the TL data more
> efficiently (decrypting one encrypted key, instead of trying each
> entry until we find one that can be decrypted successfully);
> however, the latter may require changing some internal interfaces
> to pass the kvno as well as the keyblock.
>
> Change the reader code to try parsing the file as a keytab, and if
> that fails, try the old format.
>
> Change "kdb5_util stash" to write a keytab unless given an option
> to tell it to use the old format.
>
More information about the krbdev
mailing list