EVP_des_ecb() -- SSLeay 0.9.0b -- January 1999

NAME

EVP_enc_null, EVP_des_ecb, EVP_des_ede, EVP_des_ede3,
EVP_des_cfb, EVP_des_ede_cfb, EVP_des_ede3_cfb, EVP_des_ofb, EVP_des_ede_ofb,
EVP_des_ede3_ofb, EVP_des_cbc, EVP_des_ede_cbc, EVP_des_ede3_cbc,
EVP_desx_cbc, EVP_rc4, EVP_rc4_40, EVP_idea_ecb, EVP_idea_cfb, EVP_idea_ofb,
EVP_idea_cbc, EVP_rc2_ecb, EVP_rc2_cbc, EVP_rc2_40_cbc, EVP_rc2_cfb,
EVP_rc2_ofb, EVP_bf_ecb, EVP_bf_cbc, EVP_bf_cfb, EVP_bf_ofb, EVP_cast5_ecb
, EVP_cast5_cbc, EVP_cast5_cfb, EVP_cast5_ofb, EVP_rc5_32_12_16_cbc,
EVP_rc5_32_12_16_ecb, EVP_rc5_32_12_16_cfb, EVP_rc5_32_12_16_ofb,
EVP_EncryptInit, EVP_DecryptInit, EVP_CipherInit, EVP_BytesToKey,
EVP_EncryptUpdate, EVP_DecryptUpdate, EVP_CipherUpdate, EVP_EncryptFinal,
EVP_DecryptFinal, EVP_CipherFinal, EVP_CIPHER_CTX_init,
EVP_CIPHER_CTX_cleanup, -- EVP handling for symmetric ciphers

SYNOPSIS

#include "envelope.h"

EVP_type();

where type is one of:

enc_null      des_ecb      des_ede      des_ede3      des_cfb    des_ede_cfb 
des_ede3_cfb  des_ofb      des_ede_ofb  des_ede3_ofb  des_cbc    des_ede_cbc
des_ede3_cbc  desx_cbc     rc4          rc4_40        idea_ecb   idea_cfb
idea_ofb      idea_cbc     rc2_ecb      rc2_cbc       rc2_40_cbc rc2_cfb
rc2_ofb       bf_ecb       bf_cbc       bf_cfb        bf_ofb     cast5_ecb
cast5_cbc     cast5_cfb    cast5_ofb    rc5_32_12_16_cbc         rc5_32_12_16_ecb
rc5_32_12_16_cfb           rc5_32_12_16_ofb

void EVP_EncryptInit(ctx,cipher,key,iv)
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher;
unsigned char *key, *iv;

void EVP_DecryptInit(ctx,cipher,key,iv)
EVP_CIPHER_CTX *ctx;
EVP_CIPHER *cipher;
unsigned char *key, *iv;

void EVP_CIPHER_CTX_init(a)
EVP_CIPHER_CTX *a;

void EVP_CIPHER_CTX_cleanup(a)
EVP_CIPHER_CTX *a;

DESCRIPTION

These are high-level routines that allow the user to use a uniform interface to manage encryption and decryption with symmetric algorithms.

All of these routines point to a static structure of type EVP_CIPHER which contains the following:

typedef struct evp_cipher_st { int nid; int block_size; int key_len; int iv_len; void (*init)(); /* init for encryption */ void (*do_cipher)(); /* encrypt data */ void (*cleanup)(); /* used by cipher method */ int ctx_size; /* how big the ctx needs to be */ /* int set_asn1_parameters(EVP_CIPHER_CTX,ASN1_TYPE *); */ int (*set_asn1_parameters)(); /* Populate a ASN1_TYPE with parameters */ /* int get_asn1_parameters(EVP_CIPHER_CTX,ASN1_TYPE *); */ int (*get_asn1_parameters)(); /* Get parameters from a ASN1_TYPE */ } EVP_CIPHER;

nid is the NID corresponding to the particular cipher.

block_size is the block size in bytes that the cipher operates on (1 for stream ciphers).

key_len is the length of the key in bytes.

iv_len is the length of the ivec in bytes (see DES modes of operation for explanation of the use of an ivec).

init points to the encryption init function. For example, for rc4, it points to the internal function rc4_init_key, which is called as

static void rc4_init_key(EVP_CIPHER_CTX *ctx, unsigned char *key,
        unsigned char *iv,int enc);

do_cipher points to the function that does the actual encryption. For example, for rc4, it points to the internal function rc4_cipher, which is called as

static void rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
        unsigned char *in, unsigned int inl);

cleanup points to a function to be called after encryption is completed. For example, for rc4, it is NULL.

ctx_size is the size of the context, it says in the comments. I admit that I don't know how this field is used. However, for rc4 it is set to

        sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+
                sizeof((((EVP_CIPHER_CTX *)NULL)->c.rc4))

set_asn1_parameters points to a routine that will retrieve any relevant parameters from a particular ASN1 structure. For example, some ciphers have this set to EVP_CIPHER_get_asn1_iv, which retrieves an ivec from the passed ASN1 structure.

get_asn1_parameters points to a routine that will set any relevant parameters into an ASN1 structure. For example, some ciphers have this set to EVP_CIPHER_set_asn1_iv, which sets the passed ASN1 structure to contain the passed ivec value.

Now, what do we do with all of these routines??

They are passed as arguments to EVP_EncryptInit; see below.

EVP_EncryptInit expects the user to pass an allocated ctx, type which is a pointer to the particular cipher as described above, the key, and an initialized iv.

The ctx is of type EVP_CIPHER_CTX which contains the following:

typedef struct evp_cipher_ctx_st
{
  EVP_CIPHER *cipher;
  int encrypt;            /* encrypt or decrypt */
  int buf_len;            /* number we have left */

  unsigned char  oiv[EVP_MAX_IV_LENGTH];  /* original iv */
  unsigned char  iv[EVP_MAX_IV_LENGTH];   /* working iv */
  unsigned char buf[EVP_MAX_IV_LENGTH];   /* saved partial block */
  int num;                                /* used by cfb/ofb mode */

  char *app_data;         /* aplication stuff */
  union   {
#ifndef NO_RC4
          struct
               {
                  unsigned char key[EVP_RC4_KEY_SIZE];
                  RC4_KEY ks;     /* working key */
               } rc4;
#endif
#ifndef NO_DES
          des_key_schedule des_ks;/* key schedule */
          struct
               {
                  des_key_schedule ks;/* key schedule */
                  C_Block inw;
                  C_Block outw;
               } desx_cbc;
          struct
               {
                  des_key_schedule ks1;/* key schedule */
                  des_key_schedule ks2;/* key schedule (for ede) */
                  des_key_schedule ks3;/* key schedule (for ede3) */
               } des_ede;
#endif
#ifndef NO_IDEA
          IDEA_KEY_SCHEDULE idea_ks;/* key schedule */
#endif
#ifndef NO_RC2
          RC2_KEY rc2_ks;/* key schedule */
#endif
#ifndef NO_RC5
          RC5_32_KEY rc5_ks;/* key schedule */
#endif
#ifndef NO_BLOWFISH
          BF_KEY bf_ks;/* key schedule */
#endif
#ifndef NO_CAST
          CAST_KEY cast_ks;/* key schedule */
#endif
        } c;
} EVP_CIPHER_CTX;

The function sets ctx->cipher from the argument type, calls ctx->cipher->init with arguments ctx, key, iv, and 1 (indicating encryption), sets the ctx->encrypt flag and initializes some other fields to reasonable values.

Once you have called this function with a particular ctx, you can reuse the b>ctx when encrypting with the same cipher, and possibly same key and/or iv; pass NULL in place of type, key, and/or iv and the value from the ctx will be reused.

EVP_DecryptInit operates just like EVP_EncryptInit above, except that it clears the ctx->encrypt flag and calls ctx->cipher->init with arguments ctx, key, iv, and 0 (indicating decryption).

EVP_CipherInit takes the same arguments as EVP_EncryptInit with the addition that a flag enc is passed; if this flag is set, then EVP_EncryptInit will be called, else EVP_DecryptInit will be called.

These functions are a higher level interface to the various cipher routines found in this library. As such, they allow the same code to be used to encrypt and decrypt via different ciphers with only a change in an initial parameter. These routines also provide buffering for block ciphers.

One reason for specifying the cipher via a pointer to a structure is that if you only use des-cbc, only the des-cbc routines will be included when you link the program. If you passed an integer that specified which cipher to use, the routine that mapped that integer to a set of cipher functions would cause all the ciphers to be link into the code. This setup also allows new ciphers to be added by the application (with some restrictions).

EVP_BytesToKey() is used to generate a key and an ivec for a specified cipher from a key string and a salt. type specifies the cipher, as described above, that key is being generated for. md is the message digest algorithm to use to generate the key and ivec. The salt is an optional 8 byte object that is used to help seed the key generator.

If the salt value is NULL, it is just not used. datal is the number of bytes to use from data in the key generation. This function returns the key size for the specified cipher; if data is NULL this value is returned and no other computation is performed. count is the number of times to loop around the key generator. I would suggest leaving its value as 1. The newly generated key and ivec are returned in key and iv. If either of these pointers is NULL, then no value is returned for that argument.

The algorithm used is as follows

	
	/* M[] is an array of message digests
	 * MD() is the message digest function */
	M[0]=MD(data . salt);
	for (i=1; i<count; i++) M[0]=MD(M[0]);

	i=1
	while (data still needed for key and iv)
		{
		M[i]=MD(M[i-1] . data . salt);
		for (i=1; i<count; i++) M[i]=MD(M[i]);
		i++;
		}

	If the salt is NULL, it is not used.
	The digests are concatenated together.
	M = M[0] . M[1] . M[2] .......

	For key= 8, iv=8 => key=M[0.. 8], iv=M[ 9 .. 16].
	For key=16, iv=0 => key=M[0..16].
	For key=16, iv=8 => key=M[0..16], iv=M[17 .. 24].
	For key=24, iv=8 => key=M[0..24], iv=M[25 .. 32].

This routine will produce DES-CBC keys and ivecs that are compatible with the PKCS-5 standard when md2 or md5 are used. If md5 is used, the salt is NULL and count is 1, this routine will produce the password to key mapping normally used with RC4. I have attempted to logically extend the PKCS-#5 standard to generate keys and iv for ciphers that require more than 16 bytes. If anyone knows what the correct standard is, please inform me. When using sha or sha1, things are a bit different under this scheme, since sha produces a 20 byte digest. So for ciphers requiring 24 bits of data, 20 will come from the first MD and 4 will come from the second.

I have considered having a separate function so this 'routine' can be used without the requirement of passing a EVP_CIPHER *, but I have decided to not bother. If you wish to use the function without official structures, just declare a local one and set the key_len and iv_len fields to the length you desire.

EVP_EncryptUpdate() gets inl bytes from in and outputs bytes encrypted by the cipher ctx was initialised with into out. The number of bytes written to out is put into outl. If a particular cipher encrypts in blocks, more or less than were input may be output. Currently the largest block size used by supported ciphers is 8 bytes, so out should have room for inl+7 bytes. Normally EVP_EncryptInit() is called once, followed by lots and lots of calls to EVP_EncryptUpdate, followed by a single EVP_EncryptFinal call. EVP_DecryptUpdate() is basically the same as EVP_EncryptUpdate() except that it performs decryption. There is one fundamental difference though. out can not be the same as in for any ciphers with a block size greater than 1 if more than one call to EVP_DecryptUpdate() will be made. This is because this routine can hold a 'partial' block between calls. When a partial block is decrypted (due to more bytes being passed via this function, they will be written to out overwriting the input bytes in in that have not been read yet. From this it should also be noted that out should be at least one 'block size' larger than inl. This problem only occurs on the second and subsequent call to EVP_DecryptUpdate() when using a block cipher.

EVP_CipherUpdate() calls either EVP_EncryptUpdate() or EVP_DecryptUpdate() depending on state in the ctx structure. As noted for EVP_DecryptUpdate(), when this routine is used for decryption with block ciphers, out should not be the same as ina.

EVP_EncryptFinal() Because quite a large number of ciphers are block ciphers, there is often an incomplete block to write out at the end of the encryption. EVP_EncryptFinal() performs processing on this last block. The last block in encoded in such a way that it is possible to determine how many bytes in the last block are valid. For 8 byte block size ciphers, if only 5 bytes in the last block are valid, the last three bytes will be filled with the value 3. If only 2 were valid, the other 6 would be filled with sixes. If all 8 bytes are valid, a extra 8 bytes are appended to the cipher stream containing nothing but 8 eights. These last bytes are output into out and the number of bytes written is put into outl. This form of block cipher finalization is compatible with PKCS-#5. Please remember that even if you are using ciphers like RC4 that have no blocking so that the function will not write anything into out, it would still be a good idea to pass a variable for out that can hold 8 bytes just in case the cipher is changed some time in the future. It should also be remembered that the EVP_CIPHER_CTX contains the password and so when one has finished encryption with a particular EVP_CIPHER_CTX, it is good practice to zero the structure (ie. memset(ctx,0,sizeof(EVP_CIPHER_CTX)). In fact, you can call EVP_CIPHER_CTX_Init to do this very thing (see below).

EVP_DecryptFinal() is different from EVP_EncryptFinal in that it 'removes' any padding bytes appended when the data was encrypted. Due to the way in which 1 to 8 bytes may have been appended when encryption using a block cipher, out can end up with 0 to 7 bytes being put into it. When decoding the padding bytes, it is possible to detect an incorrect decryption. If the decryption appears to be wrong, 0 is returned. If everything seems ok, 1 is returned. For ciphers with a block size of 1 (RC4), this function would normally not return any bytes and would always return 1. Just because this function returns 1 does not mean the decryption was correct. It would normally be wrong due to either the wrong key/iv or corruption of the cipher data fed to EVP_DecryptUpdate(). As for EVP_EncryptFinal, it is a good idea to zero the EVP_CIPHER_CTX after use since the structure contains the key used to decrypt the data. In fact, you can call EVP_CIPHER_CTX_Init to do this very thing (see below). EVP_CipherFinal() calls EVP_EncryptFinal() or EVP_DecryptFinal() depending on the state information in 'ctx'. 1 is always returned if the mode is encryption, otherwise the return value is the return value of EVP_DecryptFinal().

EVP_CIPHER_CTX_init clears the ctx a passed to it. After that one of EVP_EncryptInit or EVP_DecryptInit can be called with the ctx to set initial values.

EVP_CIPHER_CTX_cleanup is called only by the internal function enc_free specific to the methods_enc BIO_METHOD (see BIO_f_cipher for detaails); it calls the cleanup function for the particular cipher as provided in the cipher's EVP_CIPHER_CTX. See EVP handling for symmetric ciphers for a description of the EVP_CIPHER_CTX structure.

The following macros are provided for the convenience of the user:

#define EVP_CIPHER_iv_length(e)         ((e)->iv_len)
#define EVP_CIPHER_CTX_cipher(e)        ((e)->cipher)
#define EVP_CIPHER_CTX_nid(e)           ((e)->cipher->nid)
#define EVP_CIPHER_CTX_block_size(e)    ((e)->cipher->block_size)
#define EVP_CIPHER_CTX_key_length(e)    ((e)->cipher->key_len)
#define EVP_CIPHER_CTX_iv_length(e)     ((e)->cipher->iv_len)
#define EVP_CIPHER_CTX_get_app_data(e)  ((e)->app_data)
#define EVP_CIPHER_CTX_set_app_data(e,d) ((e)->app_data=(char *)(d))

Their use should be self-explanatory.

One additioal structure is used in the EVP library, defined as follows:

typedef struct evp_cipher_info_st
        {
        EVP_CIPHER *cipher;
        unsigned char iv[EVP_MAX_IV_LENGTH];
        } EVP_CIPHER_INFO;

This is used by the PEM library when decoding a PEM-encoded object.