5.10 Using CWC Mode

5.10.1 Problem

You want to use CWC mode to get encryption and message integrity in a single mode.

5.10.2 Solution

Use the reference implementation available from http://www.zork.org/cwc/, or use Brian Gladman's implementation, available from http://fp.gladman.plus.com/AES/cwc.zip.

5.10.3 Discussion

CWC mode is a mode of operation for providing both encryption and message integrity. This mode is parallelizable, fast in both software and hardware (where it can achieve speeds of 10 gigabits per second), unencumbered by patents, and provably secure to good bounds with standard assumptions. (We compare CWC to other modes in Recipe 5.4.)

CWC mode is not simple to implement because it uses a universal hash function as a component that is conceptually straightforward but somewhat complex to implement well. We therefore recommend using an off-the-shelf implementation, such as the implementation on the official CWC web page (http://www.zork.org/cwc/).

Here, we'll discuss how to use the distribution available from the CWC web page. This implementation has a set of macros similar to the macros we develop in Recipe 5.5 allowing you to bind the library to any AES implementation. In particular, if you edit local_options.h, you need to do the following:

  1. Set AES_KS_T to whatever value you would set SPC_KEY_SCHED (see Recipe 5.5).

  2. Set CWC_AES_SETUP to whatever value you would set SPC_ENCRYPT_INIT (see Recipe 5.5).

  3. Set CWC_AES_ENCRYPT to whatever value you would set SPC_DO_ENCRYPT (see Recipe 5.5).

Once those bindings are made, the Zork CWC implementation has a simple API that accepts an entire message at once:

int cwc_init(cwc_t ctx[1], u_char key[  ], int keybits);
void cwc_encrypt_message(cwc_t ctx[1], u_char a[  ], u_int32 alen, u_char pt[  ],
                         u_int32 ptlen, u_char nonce[11], u_char output[  ]);
int cwc_decrypt_message(cwc_t ctx[1], u_char a[  ], u_int32 alen, u_char ct[  ],
                         u_int32 ctlen, u_char nonce[11], u_char output[  ]);
void cwc_cleanup(cwc_t ctx[1]);

If you have very large messages, this API insists that you buffer them before encrypting or decrypting. That's not a fundamental limitation of CWC mode, but only of this implementation. A future version of the implementation might change that, but do note that it would require partially decrypting a message before the library could determine whether the message is authentic. The API above does not decrypt if the message isn't authentic.

If you need to operate on very large messages, check out Brian Gladman's CWC implementation, which works incrementally.

This API looks slightly different from the all-in-one APIs we've presented for other modes in this chapter. It's actually closer to the incremental mode. The CWC mode has a notion of individual messages. It is intended that each message be sent individually. You're expected to use a single key for a large number of messages, but each message gets its own nonce. Generally, each message is expected to be short but can be multiple gigabytes.

Note that encrypting a message grows the message by 16 bytes. The extra 16 bytes at the end are used for ensuring the integrity of the message (it is effectively the result of a message authentication code; see Chapter 6).

The previous API assumes that you have the entire message to encrypt or decrypt at once. In the following discussion, we'll talk about the API that allows you to incrementally process a single message.

The cwc_init( ) function allows us to initialize a CWC context object of type cwc_t that can be reused across multiple messages. Generally, a single key will be used for an entire session. The first argument is a pointer to the cwc_t object (the declaration as an array of one is a specification saying that the pointer is only to a single object rather than to an array of objects). The second argument is the AES key, which must be a buffer of 16, 24, or 32 bytes. The third argument specifies the number of bits in the key (128, 192 or 256). The function fails if keybits is not a correct value.

The cwc_encrypt_message( ) function has the following arguments:

ctx

Pointer to the cwc_t context object.

a

Buffer containing optional data that you would like to authenticate, but that does not need to be encrypted, such as plaintext headers in the HTTP protocol.

alen

Length of extra authentication data buffer, specified in bytes. It may be zero if there is no such data.

pt

Buffer containing the plaintext you would like to encrypt and authenticate.

ptlen

Length of the plaintext buffer. It may be zero if there is no data to be encrypted.

nonce

Pointer to an 11-byte buffer, which must be unique for each message. (See Recipe 4.9 for hints on nonce selection.)

output

Buffer into which the ciphertext is written. This buffer must always be at least ptlen + 16 bytes in size because the message grows by 16 bytes when the authentication value is added.

This function always succeeds. The cwc_decrypt_message( ) function, on the other hand, returns 1 on success, and 0 on failure. Failure occurs only if the message integrity check fails, meaning the data has somehow changed since it was originally encrypted. This function has the following arguments:

ctx

Pointer to the cwc_t context object.

a

Buffer containing optional data that you would like to authenticate, but that was not encrypted, such as plaintext headers in the HTTP protocol.

alen

Length of extra authentication data buffer, specified in bytes. It may be zero if there is no such data.

ct

Buffer containing the ciphertext you would like to authenticate and decrypt if it is valid.

ctlen

Length of the ciphertext buffer. It may be zero if there is no data to be decrypted.

nonce

Pointer to an 11-byte buffer, which must be unique for each message. (See Recipe 4.9 for hints on nonce selection.)

output

Buffer into which the plaintext is written. This buffer must always be at least ctlen - 16 bytes in size because the message shrinks by 16 bytes when the authentication value is removed.

The cwc_cleanup( ) function simply wipes the contents of the cwc context object passed into it.

5.10.4 See Also

  • CWC implementation from Brian Gladman: http://fp.gladman.plus.com/AES/cwc.zip

  • CWC home page: http://www.zork.org/cwc

  • Recipe 5.4, Recipe 5.5