Projects/AEAD encryption API

From K5Wiki
< Projects
Revision as of 15:40, 11 November 2008 by SamHartman (talk | contribs) (Document stream chunk type; provide some API documentation)

Jump to: navigation, search
This is an early stage project for MIT Kerberos. It is being fleshed out by its proponents. Feel free to help flesh out the details of this project. After the project is ready, it will be presented for review and approval.

The Microsoft SSPI provides an interface for in-place encryption of messages (see MS-KILE section This interface also permits additional data to be included in the checksum generated to protect integrity. Such a facility is called authenticated encryption with additional data (AEAD). The SSPI works at the GSS-API layer, rather than the raw Kerberos layer.

This project proposes to extend the raw Kerberos cryptographic API (krb5_c_*) in order to make it possible to implement these SSPI facilities in an extension to the GSS-API. The ultimate consumer of these applications is typically DCE-style RPC, although the facilities could be used by other applications.

Functional Requirements

  • Support a scatter-gather interface. Encryption APIs take a series of regions to operate on, rather than a single krb5_data.
  • Support in-place encryption of data: the same buffer is used for input and output. (Why do we want this?)
  • Support plaintext chunks that are signed but not encrypted.
  • Coordinate with Heimdal to avoid introducing unnecessary incompatibilities with their API.
  • When no additional data is included, the resulting ciphertext needs to be the same as if the existing APIs are used after concatenating the plaintext.
  • When additional data is used, the ciphertext needs to be compatible with Windows.

Basic approach

A new structure is defined: krb5_crypto_iov to describe a region of text to be encrypted or decrypted. typedef struct _krb5_crypto_iov {

   krb5_cryptotype flags;
   krb5_data data;

} krb5_crypto_iov;

The flags member describes the type of the iov. The data member points to the memory that will be manipulated. All iov APIs take a pointer to an array of krb5_crypto_iovs along with the size of that array. Buffer contents are manipulated in-place; data is overwritten. Callers must allocate the right number of krb5_crypto_iov structures before calling into an iov API.

Several types of krb5_crypto_iov are supported:

  1. define KRB5_CRYPTO_TYPE_EMPTY 0 /* [in] ignored */
  2. define KRB5_CRYPTO_TYPE_HEADER 1 /* [out] header */
  3. define KRB5_CRYPTO_TYPE_DATA 2 /* [in, out] plaintext */
  4. define KRB5_CRYPTO_TYPE_SIGN_ONLY 3 /* [in] associated data */
  5. define KRB5_CRYPTO_TYPE_PADDING 4 /* [out] padding */
  6. define KRB5_CRYPTO_TYPE_TRAILER 5 /* [out] checksum for encrypt */
  7. define KRB5_CRYPTO_TYPE_CHECKSUM 6 /* [out] checksum for MIC */
  8. define KRB5_CRYPTO_TYPE_STREAM 7 /* [in, out] An entire encrypted message for decryption*/

Typically the iov array would contain the following on a call to encryption functions:

  1. A header buffer of the appropriate length
  2. One data buffer
  3. Zero or more sign_only buffers
  4. A padding buffer of the appropriate length
  5. A trailer buffer of the appropriate length

The function krb5_crypto_length can be used to determine the length for padding, trailer and header chunks.

On encryption, the data and sign-only buffers would be populated; other buffers would point to allocated but empty memory. When an encryption function returns success all buffers would be populated and filled.

On decryption, all buffers would be populated, and the data buffer would include plaintext on successful return from krb5_c_decrypt_iov. Checksum operations work similarly.

An alternate calling sequence is supported for decryption. The initial iov array may contain:

  1. A buffer of type KRB5_CRYPTO_TYPE_STREAM
  2. Zero or more buffers of type KRB5_CRYPTO_TYPE_SIGN_ONLY

This indicates that the caller does not know the decomposition of the encrypted data into header, trailer and data. On successful return, the array is updated to replace the buffer of type KRB5_CRYPTO_TYPE_STREAM with a buffer of KRB5_CRYPTO_TYPE_DATA pointing to a subset of the stream buffer. That buffer will be modified in place to contain the plaintext.


  • The API has undefined behavior if more than one data buffer is passed in using an iov array. Applications should not do this; even in cases where the data buffers are concatenated today, an error may be returned in the future.
  • relative ordering between sign_only and data chunks may or may not be preserved depending on the crypto system. Modern crypto systems (not currently specified for use in Kerberos) such as those described in RFC 5116 handle sign_only data in a separate pass from encrypted data. The existing Kerberos crypto systems have one pass, so an iov containing (data,sign_only,sign_only) will produce different results than one containing (sign_only,data,sign_only). Thus applications should use a consistent order on sender and receiver but must not depend on this for security.

Implementation notes

While the API supports in-place encryption the implementation does not significantly reduce the number of copies.

The implementation is parallel to the existing implementation. In particular, the existing APIs are not implemented in terms of the new APIs. New code is required (with significant copying) from the generic API layer down to the enc_provider layer, although of course raw crypto primitives are used.

Currently sanity checking buffers--for example making sure there is a trailer chunk--is left to the enc_provider implementations.

Public APIs

The following APIs are introduced by this project:

krb5_error_code KRB5_CALLCONV

   (krb5_context context, krb5_cksumtype cksumtype,
                   const krb5_keyblock *key, krb5_keyusage usage,
                   krb5_crypto_iov *data, size_t num_data);

Create a checksum in the KRB5_CRYPTO_TYPE_CHECKSUM element over the data and sign_only chunks. Only the KRB5_CRYPTO_TYPE_CHECKSUM region is modified.

krb5_error_code KRB5_CALLCONV

   (krb5_context context, 
                   krb5_cksumtype cksumtype,
                   const krb5_keyblock *key, krb5_keyusage usage,
                   const krb5_crypto_iov *data, size_t num_data,
                   krb5_boolean *valid);

Confirm that the checksum in the KRB5_CRYPTO_TYPE_CHECKSUM element is a valid checksum of the data and sign_only regions in the iov.

krb5_error_code KRB5_CALLCONV

   (krb5_context context, const krb5_keyblock *key,
                   krb5_keyusage usage, const krb5_data *cipher_state,
                   krb5_crypto_iov *data, size_t num_data);

krb5_error_code KRB5_CALLCONV

   (krb5_context context, const krb5_keyblock *key,
                   krb5_keyusage usage, const krb5_data *cipher_state,
                   krb5_crypto_iov *data, size_t num_data);

Encrypt or decrypt data in place supporting AEAD. The iov needs to contain entries as described in the basic overview. Data chunks are modified in-place.

krb5_error_code KRB5_CALLCONV

   (krb5_context context, krb5_enctype enctype,
                   krb5_cryptotype type, unsigned int *size);

Return the length needed for some data structure associated with an encryption system.

Testing plan