Initializing Symmetric Ciphers Encrypting with the EVP API

149 RC4 is a stream cipher and is blazingly fast compared to the available block ciphers in OpenSSL. Its certainly the fastest algorithm currently implemented in OpenSSL. RC4 is also well-regarded as an algorithm. For this reason, and due to its widespread use in SSL, its vastly popular, though it is widely used with insecure 40-bit keys. RC4 is difficult to use well. The encryption algorithm itself is good, but some problems with the way it sets up keys require care in using it. In particular, RSA Security recommends you take one of the following two steps when using this algorithm: 1. Make sure that all key material is cryptographically hashed before use. The problem necessitating this solution is most prominent when frequently rekeying RC4. A common approach to frequent rekeying is to use a base key, and then concatenate with a counter. In RC4, that turns out to be a bad thing to do. If you take the key material and the counter and hash them together to get the actual key, the weakness goes away. The general recommendation of hashing all key material before use is a good one, no matter which cipher you use in your applications. 2. Discard the first 256 bytes of the generated key stream before using it. The easy way to do this is to encrypt 256 bytes of random data and discard the results. Additionally, as previously noted, it is particularly important to supplement use of RC4 with a MAC to ensure data integrity. See Table 6-9 for more information. Table 6-9. Referencing RC4 Key length EVP call for cipher object String for cipher lookup 40 bits EVP_rc4_40 rc4-40 128 bits EVP_rc4 rc4

6.2.1.10 RC5™

RC5 is another block cipher from RSA Security. Its name is trademarked, and its algorithm is covered by an issued patent. You should certainly contact RSA Security before using this algorithm in any application. RC5 is interesting because it is fast, well-regarded, and highly customizable. According to the RC5 specification, you can choose 64- or 128-bit blocks, use keys up to 255 bytes in size, and can use any number of cipher rounds, up to 255. However, OpenSSLs implementation uses 64-bit blocks and limits rounds to 8, 12, or 16, defaulting to 12. See Table 6-10 . Table 6-10. Referencing RC5 Cipher mode Key bits Rounds EVP call for cipher object String for cipher lookup ECB 128 12 EVP_rc5_32_16_12_ecb rc5-ecb CBC 128 12 EVP_rc5_32_16_12_cbc rc5-cbc CFB 128 12 EVP_rc5_32_16_12_cfb rc5-cfb OFB 128 12 EVP_rc5_32_16_12_ofb rc5-ofb Note that nondefault parameters to RC5 cannot currently be accessed through EVP calls or through cipher lookup by name. Instead, you must first reference the default RC5 cipher object in the correct mode, and then use other calls to set parameters, as described below.

6.2.2 Initializing Symmetric Ciphers

Before we can begin encrypting or decrypting, we must allocate and initialize a cipher context. The cipher context is a data structure that keeps track of all relevant state for the purposes of TE AM FL Y Team-Fly ® 150 encrypting or decrypting data over a period of time. For example, we can have multiple streams of data encrypted in CBC mode. The cipher context will keep track of the key associated with each stream and the internal state that needs to be kept between messages for CBC mode. Additionally, when encrypting with a block-based cipher mode, the context object buffers data that doesnt exactly align to the block size until more data arrives, or until the buffer is explicitly flushed, at which point the data is usually padded as appropriate. [1] [1] This happens only if padding is turned on, of course. The generic cipher context type is EVP_CIPHER_CTX . We can initialize one, whether it was allocated dynamically or statically, by calling EVP_CIPHER_CTX_init , like so: EVP_CIPHER_CTX x = EVP_CIPHER_CTX mallocsizeofEVP_CIPHER_CTX; EVP_CIPHER_CTX_initx; After allocating the context object and initializing it, we must set up the cipher context. At this point, we generally determine whether the particular context will be used for encrypting or decrypting. It is possible to set up a context to do both, but its a bad idea in any mode other than ECB mode, because race conditions can easily occur that will desynchronize communication. Essentially, the internal cipher state of the two communicating parties needs to remain synchronized at all times. If both parties send data at the same time, they will likely end up trying to decrypt the data they receive using an incorrect state. When we set up a cipher context, we not only choose whether were encrypting or decrypting, but also do the following: 1. Choose the type of cipher we will be using, including the mode in which to use that cipher. We will be passing an EVP_CIPHER object to an initialization routine. 2. Set the key to be used for operations by passing it to the initialization routine as an array of bytes. 3. Specify an initialization vector for the cipher, if appropriate for the mode. A default IV will be used if not otherwise specified. 4. If using the engine release, we can specify whether we want to use hardware acceleration, if available. If we do, we must have previously specified an engine to use that supports our hardware. Specifying NULL as an engine tells OpenSSL to use its default software implementations. In 0.9.7, this functionality will be part of the library proper. EVP_EncryptInit is the preferred method for setting up a cipher context for encryption. For decryption, it is EVP_DecryptInit . Both of these methods have the same signature, which includes four parameters. int EVP_EncryptInitEVP_CIPHER_CTX ctx, const EVP_CIPHER type, unsigned char key, unsigned char iv; int EVP_DecryptInitEVP_CIPHER_CTX ctx, const EVP_CIPHER type, unsigned char key, unsigned char iv; ctx The EVP cipher context object to use. type The cipher to use. key 151 The key to use for encrypting or decrypting. iv The initialization vector to use. Notice that the engine package prefers an extended API, EVP_EncryptInit_ex and EVP_DecryptInit_ex , which inserts a fifth argument before the key that is a pointer to the engine to use; it should be NULL when no hardware acceleration is being used. When Version 0.9.7 of OpenSSL is released, these versions of the calls will be the preferred API. When using engines, many calls can fail, so check error codes. We dont do this because we dont use the ENGINE API in our examples. Lets consider an example in which we try to encrypt using Blowfish with 128-bit keys in CBC mode. CBC mode can use an initialization vector, which is always the size of one block in this case, 8 bytes. We will use the OpenSSL pseudorandom number generator to provide a randomly generated key; however, distributing that key is not really covered in this example. For now, well assume that you will do it offline, perhaps by exchanging a disk, or reading the key over the phone key exchange protocols are discussed in Chapter 8 . To that end, we do print out the key to stdout in hexadecimal format. Note that doing this is not really the best idea for real applications. Example 6-1 shows how to do this. The following are the declarations for these functions. int RAND_bytesunsigned char buf, int num; int RAND_pseudo_bytesunsigned char buf, int num; The first of these functions writes num bytes of cryptographically strong random bytes into the memory at buf . The second function does precisely the same thing except that the random bytes provided are not necessarily unpredictable. The latter function is not suitable for cryptographic needs it is no more secure than functions like rand . For more information on these functions, see the man page for RAND_bytes here. Example 6-1. Preparing to use Blowfish in CBC mode for encryption include opensslevp.h void select_random_keychar key, int b { int i; RAND_byteskey, b; for i = 0; i b - 1; i++ printf02X:, key[i]; printf02X\n, key[b - 1]; } void select_random_ivchar iv, int b { RAND_pseudo_bytesiv, b; } int setup_for_encryptionvoid { 152 EVP_CIPHER_CTX ctx; char key[EVP_MAX_KEY_LENGTH]; char iv[EVP_MAX_IV_LENGTH]; if seed_prng return 0; select_random_keykey, EVP_MAX_KEY_LENGTH; select_random_iviv, EVP_MAX_IV_LENGTH; EVP_EncryptInitctx, EVP_bf_cbc, key, iv; return 1; } Note that multiple implementations of the seed_prng function are provided in Chapter 4 . It returns 0 if the pseudorandom number generator cannot be seeded securely. We return an error status from our setup function in this case, so we dont need to check the return value of RAND_pseudo_bytes when we call it. Also, you may want to use raw entropy. See Chapter 4 for more information. Another thing to note is that the party decrypting the data will need to initialize its cipher context with the same initialization vector created here. Passing the initialization vector in the clear is OK, but it should probably be MACd so that the receiver can detect tampering. If NULL is passed in for an IV, an array filled with zeros is used. Note that IVs can be used in all modes except ECB. In ECB mode, you can still pass in an IV, but block ciphers will ignore it. Setting up for decryption is generally easier, because we already know the key and the IV used. Example 6-2 shows how to set up for decryption under the same configuration. Example 6-2. Preparing to use Blowfish in CBC mode for decryption include opensslevp.h void setup_for_decryptionchar key, char iv { EVP_CIPHER_CTX ctx; EVP_DecryptInitctx, EVP_bf_cbc, key, iv; } Subsequent calls to EVP_EncryptInit or EVP_DecryptInit will change the value of any non-null parameter as long as the cipher type parameter is set to NULL . Otherwise, the context is completely reinitialized. Additionally, the key and the IV can both be set to NULL on the first call to these functions, and set separately later. This is necessary when you specify a cipher and then change the key length from the default. Of course, you will need to at least provide a valid key before encryption begins.

6.2.3 Specifying Key Length and Other Options