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