Projects/Master Key Migration
Contents
Desired changes
This project will provide the ability to add a new master key (with an enctype differing from the current master key) to the master key principal and stash file and then migrate the encryption of existing principals long term keys to use the new master key. In addition deletion of master keys will be provided.
Functional Requirements
The KDC must be able to deal with multiple master keys and determine which key to use when decrypting a principal's long term secret key. The KDC must be able to access any of the master key (K/M) principal's keys as long as it has access to a master key that is in use.
The administrator must be able re-encrypt principal keys using a specified mkey and be able to specifying the set of principals is to be re-encrypted. The command doing this must be able to determine if a principal's keys are protected by the current master key or not. This implies that some set of principals may be protected with a non-current master key.
Slave KDC's must be able to access all master keys currently protecting principal entries and therefore have access to the principal's secret keys regardless of which master key is used to encrypt the key.
The administrator will be able to:
- Add a new master key to master key principal and optionally to the masterkey keytab stash.
- Enable a new master key (make it the current master key used to protect newly created principals or principal rekeys).
- List all master keys associated with the master key principal.
- Delete a particular master key from the master key principal and optionally from the masterkey keytab stash.
- Purge unused master keys (keys not used to protect any principal).
Design of implementation
Fundamentally the current implementation must be changed to support multiple master keys. And possession of any master key stored with the K/M principal allows access to all master keys. In addition, a principal's secret key may be encrypted by any of the master keys in use and the KDC must be able to decrypt that principal's key.
In order to accommodate this, these changes will be made:
- A new TL-data type, KRB5_TL_MKVNO, would apply to all principals except the 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, the LDAP back end has a slot for it.
- A new TL-data type, KRB5_TL_ACTKVNO, would apply to all principals and will be a set of {actkvno, start_time} tuples where actkvno is the "active" KVNO and start_time indicates when actkvno is valid for use.
- When set for the K/M principal this indicates the master key to be used when encrypting principal's long term keys. If this TL-data type is not found in the K/M record then the default value for this will be 1 which is the default MKVNO.
- When set for service principals this indicates the key to be used when the KDC issues service tickets.
- Trailing stuff is ignored for now, making the structure extensible.
- The krb5_key_data array in the krb5_db_entry for the K/M principal will hold all master keys in use. All the keys in this array will be encrypted using the most recently created master key.
- A new TL-data type, KRB5_TL_MKEY_AUX, would apply only to the K/M principal. This new TL data would contain:
- A set of copies of the latest master key, each encrypted by one of the other supported mkeys, in {old-mkvno, keydata} tuples. Thus the "master key" used in DAL (DB abstraction layer) need only be any one of these keys.
- Trailing stuff is ignored for now, making the structure extensible.
- kdc_realm_t will be modified to hold all master keys (including KVNO and enctype) associated with a realm. It will also hold the current mkey KVNO that should be used when encrypting a principal's keys. To facilitate this, a new struct will be defined:
typedef struct _krb5_keylist_node { krb5_keyblock *keyblock; krb5_kvno kvno; struct _krb5_keylist_node *next; } krb5_keyblock_node;
This will be used to create a list of mkeys. kdc_realm_t will also have a current_realm_mkey which will point to the krb5_keyblock_node that contains the current mkey (used when encrypting a principal's keys, does not apply the K/M mkeys).
The initialization of the list of mkeys will occur in init_realm().
Any code needing to decrypt principal keys will need to determine which mkey to use. A function will be created to return the mkey to use for decrypting a principal's keys given the principal's krb5_db_entry and realm_mkeys list as input args. If the principals krb5_db_entry does not contain KRB5_TL_MKVNO TL-data the function will default to choosing the mkey with KVNO 1. If the princ krb5_db_entry does have KRB5_TL_MKVNO data and no matching mkey is found the function will get the K/M princ KDB entry, update the list of mkeys if new mkeys are found and return a matching mkey if found. An error will be returned if a matching mkey is not found.
This function would be called prior to calling krb5_dbekd_decrypt_key_data() to determine which mkey to pass in.
Similarly, any code calling krb5_dbekd_encrypt_key_data() will be modified to pass in the current_realm_mkey (mentioned above).
kdb5_util will be modified to support these new commands:
- add_mkey [-s]
- Add a new master key to K/M. The optional -s will add the mkey to the stash file.
- use_mkey <KVNO> [startdate]
- Set the current mkey KVNO. This controls which master key is used when encrypting principal keys. The kadmind and krb5kdc should be restarted after this command successfully completes.
- list_mkeys
- Shows all master keys from most recent to earliest in K/M principal. The output will show the KVNO, enctype and salt for each mkey similar to kadmin getprinc output. A * following an mkey denotes the current mkey.
- purge_mkeys [-f]
- Delete mkeys from K/M princ that are not used to protect any principals. With -f, does not prompt user. The prompt will be "Delete version 3 master key for the FOO.COM realm? [y/n] ".
- sync_stash [-f]
- Sync up the set of keys in the keytab stash with those in the K/M princ entry in the KDB. Keys in keytab stash not found in K/M will be removed. With -f, does not prompt user. (NOTE: During implementation, this was changed to just use the preexisting "stash" command when a stash file is already present.)
- update_princ_encryption [-f] [expression]
- Use current mkey to encrypt principals (other than K/M) secret keys if not already encrypted by that mkey. Should support either doing all princs if no argument given or a subset specified by expression (supports shell-style globbing, similar to kadmin). Both the principal's secret keys and key history will first be decrypted with the original encrypting mkey then encrypted with the current mkey. If the current mkey kvno is that of the mkey that originally encrypted the principal's keys the code will stop processing that principal and go on to the next. With -f, does not prompt user.
The kdb5_util dump -mkey_convert will be modified to update the KRB5_TL_MKVNO of all principals except the K/M principal with the KVNO of the mkey used for the conversion. The K/M KRB5_TL_MKEY_AUX TL data will be updated to include the new mkey used for the conversion.
Tasks/milestones
- project start. Aug 29, 2008
- project review. ~2 week
- Implementation. ~6 weeks
- test. ~4 week
- code review. ~2 week
- documentation. ~3 day
Desired integration and release goals
Testing plan
Unit testing of all new and modified commands will be done to verify they work as specified. This will be done for both the db2 and LDAP KDB plugins. Unit tests will include testing that the various of setting a new key (kpasswd, kadmin commands like cpw or ktadd, as well as the new/modified commands) when applied to the master key principal will either be rejected without changing the database or retain all the old keys, even if that list is larger than the normal key history size in order to make sure the normal key history mechanisms won't accidentally throw away any still-used master keys.
The kadmind and krb5kdc daemons will be tested to verify they work properly when accessing a KDB some set of principals is protected by one mkey and the other set is protected by another set. Slave KDCs will also be tested after the KDB is propagated both with kprop and kiprop.
Bounds testing will verify the krb utils and daemons work properly when the MKVNO wraps back to 1 (0 is not a valid value).
The existing MIT Kerberos test suites will be run to make sure there are no regressions introduced by this project.
Review
This section documents the review of the project according to Project policy. It is divided into multiple sections. First, approvals should be listed. To list an approval type
- #~~~~
on its own line. The next section is for discussion. Use standard talk page conventions. In particular, sign comments with
- --~~~~
and indent replies.
Members of Krbcore raising Blocking objections should preface their comment with {{project-block}}. The member who raised the objection should remove this markup when their objection is handled.