Tải bản đầy đủ - 0 (trang)
17 Performing Block Cipher Setup (for CBC, CFB, OFB, and ECB Modes) in OpenSSL

17 Performing Block Cipher Setup (for CBC, CFB, OFB, and ECB Modes) in OpenSSL

Tải bản đầy đủ - 0trang

senting that mode. Note that OpenSSL provides only a CTR mode implementation for AES. See Recipe 5.9 for more on CTR mode.

3. Instantiate a cipher context (type EVP_CIPHER_CTX).

4. Pass a pointer to the cipher context to EVP_CIPHER_CTX_init( ) to initialize memory properly.

5. Choose an IV or nonce, if appropriate to the mode (all except ECB).

6. Initialize the mode by calling EVP_EncryptInit_ex( ) or EVP_DecryptInit_ex( ), as

appropriate:

int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER

*engine, unsigned char *key, unsigned

int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER

*engine, unsigned char *key, unsigned



*type, ENGINE

char *ivornonce);

*type, ENGINE

char *ivornonce);



7. If desired, perform any additional configuration the cipher may allow (see Recipe 5.20).



Discussion

Use the raw OpenSSL API only when absolutely necessary because

there is a huge potential for introducing a security vulnerability by

accident. For general-purpose use, we recommend a high-level

abstraction, such as that discussed in Recipe 5.16.



The OpenSSL EVP API is a reasonably high-level interface to a multitude of cryptographic primitives. It attempts to abstract out most algorithm dependencies, so that

algorithms are easy to swap.*

The EVP_EncryptInit_ex( ) and EVP_DecryptInit_ex( ) functions set up a cipher context object to be used for further operations. It takes four arguments that provide all

the information necessary before encryption or decryption can begin. Both take the

same arguments:

ctx



Pointer to an EVP_CIPHER_CTX object, which stores cipher state across calls.

type



Pointer to an EVP_CIPHER object, which represents the cipher configuration to use

(see the later discussion).

engine



Pointer to an ENGINE object representing the actual implementation to use. For

example, if you want to use hardware acceleration, you can pass in an ENGINE

object that represents your cryptographic accelerator.



* EVP stands for “envelope.”



222



|



Chapter 5: Symmetric Encryption

This is the Title of the Book, eMatter Edition

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.



key



Pointer to the encryption key to be used.

ivornonce



Pointer to an initialization vector or none, if appropriate (use NULL otherwise).

For CBC, CFB, and OFB modes, the initialization vector or nonce is always the

same size as the block size of the cipher, which is often different from the key

size of the cipher.

There are also deprecated versions of these calls, EVP_EncryptInit( ) and EVP_

DecryptInit( ), that are the same except that they do not take the engine argument,

and they use only the built-in software implementation.

Calling a function that returns an EVP_CIPHER object will cause the cipher’s implementation to load dynamically and place information about the algorithm into an

internal table if it has not yet done so. Alternatively, you can load all possible symmetric ciphers at once with a call to the function OpenSSL_add_all_ciphers( ), or all

ciphers and message digest algorithms with a call to the function OpenSSL_add_all_

algorithms( ) (neither function takes any arguments). For algorithms that have been

loaded, you can retrieve pointers to their objects by name using the EVP_get_

cipherbyname( ) function, which takes a single parameter of type char *, representing the desired cipher configuration.

Table 5-6 summarizes the possible functions that can load ciphers (if necessary) and

return EVP_CIPHER objects. The table also shows the strings that can be used to look

up loaded ciphers.

As noted in Recipe 5.2, we personally recommend AES-based solutions, or (of the ciphers OpenSSL offers) Triple-DES if AES is not

appropriate. If you use other algorithms, be sure to research them

thoroughly.

Table 5-6. Cipher instantiation reference



Cipher



Key strength /

actual size (if

different)



Cipher mode



Call for EVP_CIPHER object



Cipher lookup

string



AES



128 bits



ECB



EVP_aes_128_ecb( )



aes-128-ecb



AES



128 bits



CBC



EVP_aes_128_cbc( )



aes-128-cbc



AES



128 bits



CFB



EVP_aes_128_cfb( )



aes-128-cfb



AES



128 bits



OFB



EVP_aes_128_ofb( )



aes-128-ofb



AES



192 bits



ECB



EVP_aes_192_ecb( )



aes-192-ecb



AES



192 bits



CBC



EVP_aes_192_cbc( )



aes-192-cbc



AES



192 bits



CFB



EVP_aes_192_cfb( )



aes-192-cfb



AES



192 bits



OFB



EVP_aes_192_ofb( )



aes-192-ofb



AES



256 bits



ECB



EVP_aes_256_ecb( )



aes-256-ecb



Performing Block Cipher Setup (for CBC, CFB, OFB, and ECB Modes) in OpenSSL | 223

This is the Title of the Book, eMatter Edition

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.



Table 5-6. Cipher instantiation reference (continued)



Cipher



Key strength /

actual size (if

different)



Cipher mode



Call for EVP_CIPHER object



Cipher lookup

string



AES



256 bits



CBC



EVP_aes_256_cbc( )



aes-256-cbc



AES



256 bits



CFB



EVP_aes_256_cfb( )



aes-256-cfb



AES



256 bits



OFB



EVP_aes_256_ofb( )



aes-256-ofb



Blowfish



128 bits



ECB



EVP_bf_ecb( )



bf-ecb



Blowfish



128 bits



CBC



EVP_bf_cbc( )



bf-cbc



Blowfish



128 bits



CFB



EVP_bf_cfb( )



bf-cfb



Blowfish



128 bits



OFB



EVP_bf_ofb( )



bf-ofb



CAST5



128 bits



ECB



EVP_cast_ecb( )



cast-ecb



CAST5



128 bits



CBC



EVP_cast_cbc( )



cast-cbc



CAST5



128 bits



CFB



EVP_cast_cfb( )



cast-cfb



CAST5



128 bits



OFB



EVP_cast_ofb( )



cast-ofb



DES



Effective: 56 bits

Actual: 64 bits



ECB



EVP_des_ecb( )



des-ecb



DES



Effective: 56 bits

Actual: 64 bits



CBC



EVP_des_cbc( )



des-cbc



DES



Effective: 56 bits

Actual: 64 bits



CFB



EVP_des_cfb( )



des-cfb



DES



Effective: 56 bits

Actual: 64 bits



OFB



EVP_des_ofb( )



des-ofb



DESX



Effectivea: 120 bits

Actual: 128 bits



CBC



EVP_desx_cbc( )



desx



3-key Triple-DES



Effective: 112 bits

Actual: 192 bits



ECB



EVP_des_ede3( )



des-ede3



3-key Triple-DES



Effective: 112 bits

Actual: 192 bits



CBC



EVP_des_ede3_cbc( )



des-ede3-cbc



3-key Triple-DES



Effective: 112 bits

Actual: 192 bits



CFB



EVP_des_ede3_cfb( )



des-ede3-cfb



3-key Triple-DES



Effective: 112 bits

Actual: 192 bits



OFB



EVP_des_ede3_ofb( )



des-ede3-ofb



2-key Triple-DES



Effective: 112 bits

Actual: 128 bits



ECB



EVP_des_ede( )



des-ede



2-key Triple-DES



Effective: 112 bits

Actual: 128 bits



CBC



EVP_des_ede_cbc( )



des-ede-cbc



2-key Triple-DES



Effective: 112 bits

Actual: 128 bits



CFB



EVP_des_ede_cfb( )



des-ede-cfb



2-key Triple-DES



Effective: 112 bits

Actual: 128 bits



OFB



EVP_des_ede_ofb( )



des-ede-ofb



IDEA



128 bits



ECB



EVP_idea_ecb( )



idea-ecb



IDEA



128 bits



CBC



EVP_idea_cbc( )



idea-cbc



224



|



Chapter 5: Symmetric Encryption

This is the Title of the Book, eMatter Edition

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.



Table 5-6. Cipher instantiation reference (continued)



a



Cipher



Key strength /

actual size (if

different)



Cipher mode



Call for EVP_CIPHER object



Cipher lookup

string



IDEA



128 bits



CFB



EVP_idea_cfb( )



idea-cfb



IDEA



128 bits



OFB



EVP_idea_ofb( )



idea-ofb



RC2™



128 bits



ECB



EVP_rc2_ecb( )



rc2-ecb



RC2™



128 bits



CBC



EVP_rc2_cbc( )



rc2-cbc



RC2™



128 bits



CFB



EVP_rc2_cfb( )



rc2-cfb



RC2™



128 bits



OFB



EVP_rc2_ofb( )



rc2-ofb



RC4™



40 bits



n/a



EVP_rc4_40( )



rc4-40



RC4™



128 bits



n/a



EVP_rc4( )



rc4



RC5™



128 bits



ECB



EVP_rc5_32_16_12_ecb( )



rc5-ecb



RC5™



128 bits



CBC



EVP_rc5_32_16_12_cbc( )



rc5-cbc



RC5™



128 bits



CFB



EVP_rc5_32_16_12_cfb( )



rc5-cfb



RC5™



128 bits



OFB



EVP_rc5_32_16_12_ofb( )



rc5-ofb



There are known plaintext attacks against DESX that reduce the effective strength to 60 bits, but these are generally considered infeasible.



For stream-based modes (CFB and OFB), encryption and decryption are identical

operations. Therefore, EVP_EncryptInit_ex( ) and EVP_DecryptInit_ex( ) are interchangeable in these cases.

While RC4 can be set up using these instructions, you must be very

careful to set it up securely. We discuss how to do so in Recipe 5.23.



Here is an example of setting up an encryption context using 128-bit AES in CBC

mode:

#include

#include

/* key must be of size EVP_MAX_KEY_LENGTH.

* iv must be of size EVP_MAX_IV_LENGTH.

*/

EVP_CIPHER_CTX *sample_setup(unsigned char *key, unsigned char *iv) {

EVP_CIPHER_CTX *ctx;

/* This uses the OpenSSL PRNG . See Recipe 11.9 */

RAND_bytes(key, EVP_MAX_KEY_LENGTH);

RAND_bytes(iv, EVP_MAX_IV_LENGTH);

if (!(ctx = (EVP_CIPHER_CTX *)malloc(sizeof(EVP_CIPHER_CTX)))) return 0;

EVP_CIPHER_CTX_init(ctx);

EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc( ), 0, key, iv);

return ctx;

}



Performing Block Cipher Setup (for CBC, CFB, OFB, and ECB Modes) in OpenSSL | 225

This is the Title of the Book, eMatter Edition

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.



This example selects a key and initialization vector at random. Both of these items

need to be communicated to any party that needs to decrypt the data. The caller

therefore needs to be able to recover this information. In this example, we handle

this by having the caller pass in allocated memory, which we fill with the new key

and IV. The caller can then communicate them to the other party in whatever manner is appropriate.

Note that to make replacing algorithms easier, we always create keys and initialization vectors of the maximum possible length, using macros defined in the openssl/

evp.h header file.



See Also

Recipes 5.2, 5.9, 5.16, 5.18, 5.20, 5.23



5.18 Using Variable Key-Length Ciphers in

OpenSSL

Problem

You’re using a cipher with an adjustable key length, yet OpenSSL provides no

default cipher configuration for your desired key length.



Solution

Initialize the cipher without a key, call EVP_CIPHER_CTX_set_key_length( ) to set the

appropriate key length, then set the key.



Discussion

Many of the ciphers supported by OpenSSL support variable key lengths. Whereas

some, such as AES, have an available call for each possible key length, others (in particular, RC4) allow for nearly arbitrary byte-aligned keys. Table 5-7 lists ciphers supported by OpenSSL, and the varying key lengths those ciphers can support.

Table 5-7. Variable key sizes

Cipher



OpenSSL-supported key sizes



Algorithm’s possible key sizes



AES



128, 192, and 256 bits



128, 192, and 256 bits



Blowfish



Up to 256 bits



Up to 448 bits



CAST5



40–128 bits



40–128 bits



RC2



Up to 256 bits



Up to 1,024 bits



RC4



Up to 256 bits



Up to 2,048 bits



RC5



Up to 256 bits



Up to 2,040 bits



226



|



Chapter 5: Symmetric Encryption

This is the Title of the Book, eMatter Edition

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.



While RC2, RC4, and RC5 support absurdly high key lengths, it really is overkill to

use more than a 256-bit symmetric key. There is not likely to be any greater security,

only less efficiency. Therefore, OpenSSL puts a hard limit of 256 bits on key sizes.

When calling the OpenSSL cipher initialization functions, you can set to NULL any

value you do not want to provide immediately. If the cipher requires data you have

not yet provided, clearly encryption will not work properly.

Therefore, we can choose a cipher using EVP_EncryptInit_ex( ) without specifying a

key, then set the key size using EVP_CIPHER_CTX_set_key_length( ), which takes two

arguments: the first is the context initialized by the call to EVP_EncryptInit_ex( ), and

the second is the new key length in bytes.

Finally, we can set the key by calling EVP_EncryptInit_ex( ) again, passing in the context and any new data, along with NULL for any parameters we’ve already set. For

example, the following code would set up a 256-bit version of Blowfish in CBC

mode:

#include

EVP_CIPHER_CTX *blowfish_256_cbc_setup(char *key, char *iv) {

EVP_CIPHER_CTX *ctx;

if (!(ctx = (EVP_CIPHER_CTX *)malloc(sizeof(EVP_CIPHER_CTX)))) return 0;

EVP_CIPHER_CTX_init(ctx);

/* Uses 128-bit keys by default. We pass in NULLs for the parameters that we'll

* fill in after properly setting the key length.

*/

EVP_EncryptInit_ex(ctx, EVP_bf_cbc( ), 0, 0, 0);

EVP_CIPHER_CTX_set_key_length(ctx, 32);

EVP_EncryptInit_ex(ctx, 0, 0, key, iv);

return ctx;

}



5.19 Disabling Cipher Padding in OpenSSL in CBC

Mode

Problem

You’re encrypting in CBC or ECB mode, and the length of your data to encrypt is

always a multiple of the block size. You would like to avoid padding because it adds

an extra, unnecessary block of output.



Solution

OpenSSL has a function that can turn padding on and off for a context object:

int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad);



Disabling Cipher Padding in OpenSSL in CBC Mode | 227

This is the Title of the Book, eMatter Edition

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.



Discussion

Particularly when you are implementing another encryption mode, you may always

be operating on block-sized chunks, and it can be inconvenient to deal with padding. Alternatively, some odd protocol may require a nonstandard padding scheme

that causes you to pad the data manually before encryption (and to remove the pad

manually after encryption).

The second argument of this function should be zero to turn padding off, and nonzero to turn it on.



5.20 Performing Additional Cipher Setup in

OpenSSL

Problem

Using OpenSSL, you want to adjust a configurable parameter of a cipher other than

the key length.



Solution

OpenSSL provides an obtuse, ioctl()-style API for setting uncommon cipher parameters on a context object:

int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);



Discussion

OpenSSL doesn’t provide much flexibility in adjusting cipher characteristics. For

example, the three AES configurations are three specific instantiations of a cipher

called Rijndael, which has nine different configurations. However, OpenSSL supports only the three standard ones.

Nevertheless, there are two cases in which OpenSSL does allow for configurability.

In the first case, it allows for setting the “effective key bits” in RC2. As a result, the

RC2 key is crippled so that it is only as strong as the effective size set. We feel that

this functionality is completely useless.

In the second case, OpenSSL allows you to set the number of rounds used internally

by the RC5 algorithm. By default, RC5 uses 12 rounds. And while the algorithm

should take absolutely variable-length rounds, OpenSSL allows you to set the number only to 8, 12, or 16.



228



|



Chapter 5: Symmetric Encryption

This is the Title of the Book, eMatter Edition

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.



The function EVP_CIPHER_CTX_ctrl( ) can be used to set or query either of these values, given a cipher of the appropriate type. This function has the following arguments:

ctx



Pointer to the cipher context to be modified.

type



Value indicating which operation to perform (more on this a little later).

arg



Numerical value to set, if appropriate (it is otherwise ignored).

ptr



Pointer to an integer for querying the numerical value of a property, if appropriate (the result is placed in the integer being pointed to).

The type argument can be one of the four macros defined in openssl/evp.h:

EVP_CTRL_GET_RC2_KEY_BITS

EVP_CTRL_SET_RC2_KEY_BITS

EVP_CTRL_GET_RC5_ROUNDS

EVP_CTRL_SET_RC5_ROUNDS



For example, to set an RC5 context to use 16 rounds:

EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC5_ROUNDS, 16, NULL);



To query the number of rounds, putting the result into an integer named r:

EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GET_RC5_ROUNDS, 0, &r);



5.21 Querying Cipher Configuration Properties

in OpenSSL

Problem

You want to get information about a particular cipher context in OpenSSL.



Solution

For most properties, OpenSSL provides macros for accessing them. For other things,

we can access the members of the cipher context structure directly.

To get the actual object representing the cipher:

EVP_CIPHER *EVP_CIPHER_CTX_cipher(EVP_CIPHER_CTX *ctx);



To get the block size of the cipher:

int EVP_CIPHER_CTX_block_size(EVP_CIPHER_CTX *ctx);



To get the key length of the cipher:

int EVP_CIPHER_CTX_key_length(EVP_CIPHER_CTX *ctx);



Querying Cipher Configuration Properties in OpenSSL | 229

This is the Title of the Book, eMatter Edition

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.



To get the length of the initialization vector:

int EVP_CIPHER_CTX_iv_length(EVP_CIPHER_CTX *ctx);



To get the cipher mode being used:

int EVP_CIPHER_CTX_mode(EVP_CIPHER_CTX *ctx);



To see if automatic padding is disabled:

int pad = (ctx->flags & EVP_CIPH_NO_PADDING);



To see if we are encrypting or decrypting:

int encr = (ctx->encrypt);



To retrieve the original initialization vector:

char *iv = (ctx->oiv);



Discussion

The EVP_CIPHER_CTX_cipher( ) function is actually implemented as a macro that

returns an object of type EVP_CIPHER. The cipher itself can be queried, but interesting

queries can also be made on the context object through appropriate macros.

All functions returning lengths return them in bytes.

The EVP_CIPHER_CTX_mode( ) function returns one of the following predefined values:

EVP_CIPH_ECB_MODE

EVP_CIPH_CBC_MODE

EVP_CIPH_CFB_MODE

EVP_CIPH_OFB_MODE



5.22 Performing Low-Level Encryption and

Decryption with OpenSSL

Problem

You have set up your cipher and want to perform encryption and decryption.



Solution

Use the following suite of functions:

int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,

unsigned char *in, int inl);

int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);

int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,

unsigned char *in, int inl);

int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);



230



|



Chapter 5: Symmetric Encryption

This is the Title of the Book, eMatter Edition

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.



Discussion

As a reminder, use a raw mode only if you really know what you’re

doing. For general-purpose use, we recommend a high-level abstraction, such as that discussed in Recipe 5.16. Additionally, be sure to

include some sort of integrity validation whenever encrypting, as we

discuss throughout Chapter 6.



The signatures for the encryption and decryption routines are identical, and the

actual routines are completely symmetric. Therefore, we’ll only discuss the behavior

of the encryption functions, and you can infer the behavior of the decryption functions from that.

EVP_EncryptUpdate( ) has the following arguments:

ctx



Pointer to the cipher context previously initialized with EVP_EncryptInit_ex( ).

out



Buffer into which any output is placed.

outl



Pointer to an integer, into which the number of bytes written to the output

buffer is placed.

in



Buffer containing the data to be encrypted.

inl



Number of bytes contained in the input buffer.

EVP_EncryptFinal_ex( ) takes the following arguments:

ctx



Pointer to the cipher context previously initialized with EVP_EncryptInit_ex( ).

out



Buffer into which any output is placed.

outl



Pointer to an integer, into which the number of bytes written to the output

buffer is placed.

There are two phases to encryption in OpenSSL: update, and finalization. The basic

idea behind update mode is that you’re feeding in data to encrypt, and if there’s

incremental output, you get it. Calling the finalization routine lets OpenSSL know

that all the data to be encrypted with this current context has already been given to

the library. OpenSSL then does any cleanup work necessary, and it will sometimes

produce additional output. After a cipher is finalized, you need to reinitialize it if you

plan to reuse it, as described in Recipe 5.17.



Performing Low-Level Encryption and Decryption with OpenSSL | 231

This is the Title of the Book, eMatter Edition

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.



In CBC and ECB modes, the cipher cannot always encrypt all the plaintext you give

it as that plaintext arrives, because it requires block-aligned data to operate. In the

finalization phase, those algorithms add padding if appropriate, then yield the

remaining output. Note that, because of the internal buffering that can happen in

these modes, the output to any single call of EVP_EncryptUpdate( ) or EVP_

EncryptFinal_ex( ) can be about a full block larger or smaller than the actual input. If

you’re encrypting data into a single buffer, you can always avoid overflow if you

make the output buffer an entire block bigger than the input buffer. Remember,

however, that if padding is turned off (as described in Recipe 5.19), the library will

be expecting block-aligned data, and the output will always be the same size as the

input.

In OFB and CFB modes, the call to EVP_EncryptUpdate( ) will always return the

amount of data you passed in, and EVP_EncryptFinal_ex( ) will never return any data.

This is because these modes are stream-based modes that don’t require aligned data

to operate. Therefore, it is sufficient to call only EVP_EncryptUpdate( ), skipping finalization entirely. Nonetheless, you should always call the finalization function so that

the library has the chance to do any internal cleanup that may be necessary. For

example, if you’re using a cryptographic accelerator, the finalization call essentially

gives the hardware license to free up resources for other operations.

These functions all return 1 on success, and 0 on failure. EVP_EncryptFinal_ex( ) will

fail if padding is turned off and the data is not block-aligned. EVP_DecryptFinal_ex( )

will fail if the decrypted padding is not in the proper format. Additionally, any of

these functions may fail if they are using hardware acceleration and the underlying

hardware throws an error. Beyond those problems, they should not fail. Note again

that when decrypting, this API has no way of determining whether the data

decrypted properly. That is, the data may have been modified in transit; other means

are necessary to ensure integrity (i.e., use a MAC, as we discuss throughout

Chapter 6).

Here’s an example function that, when given an already instantiated cipher context,

encrypts an entire plaintext message 100 bytes at a time into a single heap-allocated

buffer, which is returned at the end of the function. This example demonstrates how

you can perform multiple encryption operations over time and keep encrypting into

a single buffer. This code will work properly with any of the OpenSSL-supported

cipher modes.

#include

#include

/* The integer pointed to by rb receives the number of bytes in the output.

* Note that the malloced buffer can be realloced right before the return.

*/

char *encrypt_example(EVP_CIPHER_CTX *ctx, char *data, int inl, int *rb) {

int i, ol, tmp;

char *ret;



232



|



Chapter 5: Symmetric Encryption

This is the Title of the Book, eMatter Edition

Copyright © 2007 O’Reilly & Associates, Inc. All rights reserved.



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

17 Performing Block Cipher Setup (for CBC, CFB, OFB, and ECB Modes) in OpenSSL

Tải bản đầy đủ ngay(0 tr)

×