This project follows after Projects/Crypto modularity and intends to improve encryption performance by allowing cached information to be added to keys. It also creates API concepts which can be later used for supporting cryptographic tokens.
The current API uses an exposed structure, krb5_keyblock, to convey key information to the encryption functions. Because the keyblock type is not opaque, we cannot add fields to it without breaking the ABI. If encryption is performed repeatedly with the same key and usage, the derived key must be re-computed each time. If the encryption back end library associates a handle with the key, the handle must be re-initialized each time the key is used.
Keyblocks are used within several other exposed krb5 structures, including credentials and keytab entries, which would make it difficult to revise the entire API to use a new type. However, in most cases where keyblocks are used within other API structures, the key contents alone are sufficient; such keys are generally either being readied for transmission over the network, or will be used for only a single encryption with a particular key usage. Keys used for repeated encryptions are stored within auth context structures--either krb5_auth_context or krb5_gss_ctx_id_rec--which are opaque and can be modified.
The keyblock structure retains its current meaning as the exposed data of a cryptographic key. For keys which may be used repeatedly or which may be an external reference, we define a new opaque type krb5_key:
struct krb5_key_st; typedef struct krb5_key_st *krb5_key;
The prefix krb5_k_ will distinguish functions operating on keys from similar functions operating on keyblocks. Opaque keys have the following initializers and accessors:
krb5_error_code krb5_k_create_key(krb5_context context, krb5_keyblock *key_data, krb5_key *out); krb5_error_code krb5_k_free_key(krb5_context context, krb5_key key); krb5_error_code krb5_k_key_keyblock(krb5_context context, krb5_key key, krb5_keyblock **key_data); krb5_enctype krb5_k_key_enctype(krb5_context context, krb5_key key);
The following new functions encrypt, decrypt, checksum, or verify data using opaque keys.
krb5_error_code krb5_k_encrypt(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data *cipher_state, const krb5_data *input, krb5_enc_data *output); krb5_error_code krb5_k_encrypt_iov(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data *cipher_state, krb5_crypto_iov *data, size_t num_data); krb5_error_code krb5_k_decrypt(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data *cipher_state, const krb5_enc_data *input, krb5_data *output); krb5_error_code krb5_k_decrypt_iov(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data *cipher_state, krb5_crypto_iov *data, size_t num_data); krb5_error_code krb5_k_make_checksum(krb5_context context, krb5_cksumtype cksumtype, krb5_key key, krb5_keyusage usage, const krb5_data *input, krb5_checksum *cksum); krb5_error_code krb5_k_make_checksum_iov(krb5_context context, krb5_cksumtype cksumtype, krb5_key key, krb5_keyusage usage, krb5_crypto_iov *data, size_t num_data); krb5_error_code krb5_k_verify_checksum(krb5_context context, krb5_key key, krb5_keyusage usage, const krb5_data *data, const krb5_checksum *cksum, krb5_boolean *valid); krb5_error_code krb5_k_verify_checksum_iov(krb5_context context, krb5_cksumtype cksumtype, krb5_key key, krb5_keyusage usage, const krb5_crypto_iov *data, size_t num_data, krb5_boolean *valid);
These functions do not define a new and complete crypto layer; there are other crypto functions which refer to keyblocks, such as krb5_c_prf and krb5_c_string_to_key, for which there will be no parallel function using krb5_key. Furthermore, the keyblock-using parallels to the above functions will not be deprecated, but they will be documented as being less efficient for repeated operations with the same key usage.
The existing krb5_c versions of the new functions will be reimplemented in terms of the krb5_k functions, using an internal non-copying keyblock-to-key_st converter. The enc_provider, hash_providers, and enctype SPIs will be redefined using krb5_key functions so that the back ends only need to implement one version of the interface.
The krb5_key_st structure will initially contain a linked list of derived keys, mapping a derivation constant (krb5_data) to a krb5_key. krb5_derive_key will cache derived keys in this list.
In krb5_auth_context and krb5_gss_ctx_id_rec, all keyblock fields will be replaced with krb5_keys, and all usages of those fields changed to use the krb5_k APIs.
(To be written.)
A follow-on project to support cryptographic tokens can define a new krb5_key initializer which creates an external reference, and a new error code for krb5_key_keyblock which indicates that the keyblock data is unavailable.