EVP_ -- SSLeay 0.9.0b -- January 1999


EVP_md_null, EVP_md2, EVP_md5, EVP_sha, EVP_sha1, EVP_dss, EVP_dss1,
EVP_mdc2, EVP_ripemd160, EVP_DigestInit, EVP_DigestUpdate, EVP_DigestFinal
EVP_SignInit, EVP_SignUpdate, EVP_SignFinal, EVP_VerifyInit,
EVP_VerifyUpdate, EVP_VerifyFinal -- EVP digest handling, signing, verification


#include "envelope.h"


where type is one of:

md_null    md2    md5    sha    sha1    dss    dss1   mdc2   ripemd160

void EVP_DigestInit(ctx, type)
EVP_MD_CTX *ctx;
EVP_MD *type;

void EVP_DigestUpdate(ctx, data, cnt)
EVP_MD_CTX *ctx;
unsigned char *data;
unsigned int cnt;

void EVP_DigestFinal(ctx, md, s)
EVP_MD_CTX *ctx;
unsigned char *md;
unsigned int *len;

int EVP_SignFinal(ctx, md, s, pkey) EVP_MD_CTX *ctx; unsigned char *md; unsigned int *s; EVP_PKEY *pkey;

int EVP_VerifyFinal(ctx, sigbuf, siglen, pkey; EVP_MD_CTX *ctx; unsigned char *sigbuf; unsigned int siglen; EVP_PKEY *pkey;


These functions are a higher level interface to the various message digest routines found in this library. As such, they allow the same code to be used to digest via different algorithms with only a change in an initial parameter. They are basically just a front-end to the MD2, MD5, SHA, and other digest routines.

These routines all take a pointer to a structuire of type EVP_MD which conatins the following:

typedef struct evp_md_st
  int type;
  int pkey_type;
  int md_size;
  void (*init)();
  void (*update)();
  void (*final)();
  int (*sign)();
  int (*verify)();

  int required_pkey_type; /*EVP_PKEY_xxx */
  int block_size;
  int ctx_size; /* how big does the ctx need to be */

type is the NID corresponding to the particular digest.

pkey_type is the NID corresponding to the algorithm used for digest-and-sign, for example NID_shaWithRSAEncryption.

md_size is the size of the digest that the algorithm generates; for example, for sha it is SHA_DIGEST_LENGTH (20).

init points to the digest init function. For example, for sha, it points to the function SHA_Init.

update points to the function that computes the actual digest, except possibly the first block. For example, for sha, it points to the function SHA_Update.

final points to the function that is called after the digest is computed or possibly to finish the last block of data. For example, for sha, it points to the function SHA_Final.

See Hash Algorithms for a description of the SHA_* and similar functions.

sign points to a function that is called to... well, what a good question. It appears that neither this nor verify are actually set to anything in these static structures. Which in turn means that they get the entries for the next few values. How did this ever work? In any case...

required_pkey_type points to the type of EVP_PKEY you want to use for signing. For example, for sha it points to


block_size is the number of bytes a block of input to the digest must be. For example, for sha it is SHA_CBLOCK.

ctx_size is the size of the ctx. I am not sure what this is/does, but for sha it is set to

sizeof(EVP_MD *)+sizeof(SHA_CTX)

If additional message digest algorithms are to be supported, a structure of this type needs to be declared and populated and then the Digest routines can be used with that algorithm. by parts. One reason for specifying the message digest to use via this mechanism is that if you only use md5, only the md5 routines will be included in your linked program. If you passed an integer that specified which message digest to use, the routine that mapped that integer to a set of message digest functions would cause all the message digests functions to be link into the code. This setup also allows new message digest functions to be added by the application.

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

They are passed as arguments to EVP_DigestInit; see below.

EVP_DigestInit expects the user to pass an allocated ctx, and a type which is a pointer to the particular digest as described above.

The ctx is of type EVP_DIGEST_CTX which contains the following:

typedef struct env_md_ctx_st
  EVP_MD *digest;
  union   {
          unsigned char base[4];
#ifndef NO_MD2
          MD2_CTX md2;
#ifndef NO_MD5
          MD5_CTX md5;
#ifndef NO_MD5
          RIPEMD160_CTX ripemd160;
#if !defined(NO_SHA) || !defined(NO_SHA1)
          SHA_CTX sha;
#ifndef NO_MDC2
          MDC2_CTX mdc2;
          } md;

The function sets ctx->digest from the argument type, and calls ctx->digest->init with arguments ctx->md (this sets up the context for the particular digest).

EVP_DigestUpdate() is used to pass more data to the message digest function. cnt bytes are digested from data.

EVP_DigestFinal() finishes the digestion and puts the message digest into md. The length of the message digest is put into len; EVP_MAX_MD_SIZE is the size of the largest message digest that can be returned from this function. The user may pass a NULL value for len if the size of the digest is not required.

Signing and Verification

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

#define EVP_SignInit(a,b)               EVP_DigestInit(a,b)
#define EVP_SignUpdate(a,b,c)           EVP_DigestUpdate(a,b,c)
#define EVP_VerifyInit(a,b)             EVP_DigestInit(a,b)
#define EVP_VerifyUpdate(a,b,c)         EVP_DigestUpdate(a,b,c)

Signing is done by generating a message digest (see the two relevant maccros above) and then encrypting the digest with a specified key.

Verification is done by generating a message digest (see the two relevant macros above) and then comparing the new digest with one supplied by the user.

EVP_SignFinal finishes the generation of the message digest and then encrypts the digest (with the correct message digest object identifier) using the private key pkey, wich must be one of type EVP_PKEY_RSA or EVP_PKEY_DSA. ctx is the message digest context. md will end up containing the encrypted message digest. This array needs to be EVP_PKEY_size(pkey) bytes long. s will actually contain the exact length. It is If there is an error, 0 is returned, otherwise 1.

EVP_VerifyFinal finishes the generation of the message digest and then compares it with the supplied encrypted message digest md of s bytes in length. pkey is used to public key decrypt md; this is then compared with the message digest just generated. If they match, 1 is returned, else 0.