Commit 49528751 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

More EVP cipher revision.

Change EVP_SealInit() and EVP_OpenInit() to
handle cipher parameters.

Make it possible to set RC2 and RC5 params.

Make RC2 ASN1 code use the effective key bits
and not the key length.

TODO: document how new API works.
parent 547bf7f9
Loading
Loading
Loading
Loading
+18 −18
Original line number Original line Diff line number Diff line
@@ -4,11 +4,28 @@


 Changes between 0.9.5a and 0.9.6  [xx XXX 2000]
 Changes between 0.9.5a and 0.9.6  [xx XXX 2000]


  *) Remove lots of duplicated code from the EVP library. For example *every*
  *) In ssl/s2_clnt.c and ssl/s3_clnt.c, call ERR_clear_error() when
     the handshake is continued after ssl_verify_cert_chain();
     otherwise, if SSL_VERIFY_NONE is set, remaining error codes
     can lead to 'unexplainable' connection aborts later.
     [Bodo Moeller; problem tracked down by Lutz Jaenicke]

  *) Major EVP API cipher revision.
     Add hooks for extra EVP features. This allows various cipher
     parameters to be set in the EVP interface. Support added for variable
     key length ciphers via the EVP_CIPHER_CTX_set_key_length() function and
     setting of RC2 and RC5 parameters.

     Modify EVP_OpenInit() and EVP_SealInit() to cope with variable key length
     ciphers.

     Remove lots of duplicated code from the EVP library. For example *every*
     cipher init() function handles the 'iv' in the same way according to the
     cipher init() function handles the 'iv' in the same way according to the
     cipher mode. They also all do nothing if the 'key' parameter is NULL and
     cipher mode. They also all do nothing if the 'key' parameter is NULL and
     for CFB and OFB modes they zero ctx->num.
     for CFB and OFB modes they zero ctx->num.


     New functionality allows removal of S/MIME code RC2 hack.

     Most of the routines have the same form and so can be declared in terms
     Most of the routines have the same form and so can be declared in terms
     of macros.
     of macros.


@@ -16,23 +33,6 @@
     all individual ciphers. If the cipher wants to handle IVs or keys
     all individual ciphers. If the cipher wants to handle IVs or keys
     differently it can set the EVP_CIPH_CUSTOM_IV or EVP_CIPH_ALWAYS_CALL_INIT
     differently it can set the EVP_CIPH_CUSTOM_IV or EVP_CIPH_ALWAYS_CALL_INIT
     flags.
     flags.
     [Steve Henson]

  *) In ssl/s2_clnt.c and ssl/s3_clnt.c, call ERR_clear_error() when
     the handshake is continued after ssl_verify_cert_chain();
     otherwise, if SSL_VERIFY_NONE is set, remaining error codes
     can lead to 'unexplainable' connection aborts later.
     [Bodo Moeller; problem tracked down by Lutz Jaenicke]

  *) EVP cipher enhancement. Add hooks for extra EVP features. This will allow
     various cipher parameters to be set in the EVP interface. Initially
     support added for variable key length ciphers via the
     EVP_CIPHER_CTX_set_key_length() function. Other cipher specific
     parameters will be added later via the new catchall 'ctrl' function.
     New functionality allows removal of S/MIME code RC2 hack.

     Still needs support in other library functions, and allow parameter
     setting for algorithms like RC2, RC5.


     Change lots of functions like EVP_EncryptUpdate() to now return a
     Change lots of functions like EVP_EncryptUpdate() to now return a
     value: although software versions of the algorithms cannot fail
     value: although software versions of the algorithms cannot fail
+56 −32
Original line number Original line Diff line number Diff line
@@ -66,16 +66,19 @@


static int rc2_init_key(EVP_CIPHER_CTX *ctx, unsigned char *key,
static int rc2_init_key(EVP_CIPHER_CTX *ctx, unsigned char *key,
	unsigned char *iv,int enc);
	unsigned char *iv,int enc);
static int rc2_meth_to_magic(const EVP_CIPHER *e);
static int rc2_meth_to_magic(EVP_CIPHER_CTX *ctx);
static EVP_CIPHER *rc2_magic_to_meth(int i);
static int rc2_magic_to_meth(int i);
static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr);


IMPLEMENT_BLOCK_CIPHER(rc2, rc2.ks, RC2, rc2, NID_rc2,
IMPLEMENT_BLOCK_CIPHER(rc2, rc2.ks, RC2, rc2, NID_rc2,
			8,
			8,
			EVP_RC2_KEY_SIZE, 8,
			EVP_RC2_KEY_SIZE, 8,
			EVP_CIPH_VARIABLE_LENGTH, rc2_init_key, NULL,
			EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
			rc2_set_asn1_type_and_iv, rc2_get_asn1_type_and_iv, NULL)
			rc2_init_key, NULL,
			rc2_set_asn1_type_and_iv, rc2_get_asn1_type_and_iv, 
			rc2_ctrl)


#define RC2_40_MAGIC	0xa0
#define RC2_40_MAGIC	0xa0
#define RC2_64_MAGIC	0x78
#define RC2_64_MAGIC	0x78
@@ -85,7 +88,7 @@ static EVP_CIPHER r2_64_cbc_cipher=
	{
	{
	NID_rc2_64_cbc,
	NID_rc2_64_cbc,
	8,8 /* 64 bit */,8,
	8,8 /* 64 bit */,8,
	EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH,
	EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
	rc2_init_key,
	rc2_init_key,
	rc2_cbc_cipher,
	rc2_cbc_cipher,
	NULL,
	NULL,
@@ -93,7 +96,7 @@ static EVP_CIPHER r2_64_cbc_cipher=
		sizeof((((EVP_CIPHER_CTX *)NULL)->c.rc2)),
		sizeof((((EVP_CIPHER_CTX *)NULL)->c.rc2)),
	rc2_set_asn1_type_and_iv,
	rc2_set_asn1_type_and_iv,
	rc2_get_asn1_type_and_iv,
	rc2_get_asn1_type_and_iv,
	NULL,
	rc2_ctrl,
	NULL
	NULL
	};
	};


@@ -101,7 +104,7 @@ static EVP_CIPHER r2_40_cbc_cipher=
	{
	{
	NID_rc2_40_cbc,
	NID_rc2_40_cbc,
	8,5 /* 40 bit */,8,
	8,5 /* 40 bit */,8,
	EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH,
	EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
	rc2_init_key,
	rc2_init_key,
	rc2_cbc_cipher,
	rc2_cbc_cipher,
	NULL,
	NULL,
@@ -109,7 +112,7 @@ static EVP_CIPHER r2_40_cbc_cipher=
		sizeof((((EVP_CIPHER_CTX *)NULL)->c.rc2)),
		sizeof((((EVP_CIPHER_CTX *)NULL)->c.rc2)),
	rc2_set_asn1_type_and_iv,
	rc2_set_asn1_type_and_iv,
	rc2_get_asn1_type_and_iv,
	rc2_get_asn1_type_and_iv,
	NULL,
	rc2_ctrl,
	NULL
	NULL
	};
	};


@@ -127,30 +130,30 @@ static int rc2_init_key(EVP_CIPHER_CTX *ctx, unsigned char *key,
	     unsigned char *iv, int enc)
	     unsigned char *iv, int enc)
	{
	{
	RC2_set_key(&(ctx->c.rc2.ks),EVP_CIPHER_CTX_key_length(ctx),
	RC2_set_key(&(ctx->c.rc2.ks),EVP_CIPHER_CTX_key_length(ctx),
			key,EVP_CIPHER_key_length(ctx->cipher)*8);
			key,ctx->c.rc2.key_bits);
	return 1;
	return 1;
	}
	}


static int rc2_meth_to_magic(const EVP_CIPHER *e)
static int rc2_meth_to_magic(EVP_CIPHER_CTX *e)
	{
	{
	int i;
	int i;


	i=EVP_CIPHER_key_length(e);
	EVP_CIPHER_CTX_ctrl(e, EVP_CTRL_GET_RC2_KEY_BITS, 0, &i);
	if 	(i == 16) return(RC2_128_MAGIC);
	if 	(i == 128) return(RC2_128_MAGIC);
	else if (i == 8)  return(RC2_64_MAGIC);
	else if (i == 64)  return(RC2_64_MAGIC);
	else if (i == 5)  return(RC2_40_MAGIC);
	else if (i == 40)  return(RC2_40_MAGIC);
	else return(0);
	else return(0);
	}
	}


static EVP_CIPHER *rc2_magic_to_meth(int i)
static int rc2_magic_to_meth(int i)
	{
	{
	if      (i == RC2_128_MAGIC) return(EVP_rc2_cbc());
	if      (i == RC2_128_MAGIC) return 128;
	else if (i == RC2_64_MAGIC)  return(EVP_rc2_64_cbc());
	else if (i == RC2_64_MAGIC)  return 64;
	else if (i == RC2_40_MAGIC)  return(EVP_rc2_40_cbc());
	else if (i == RC2_40_MAGIC)  return 40;
	else
	else
		{
		{
		EVPerr(EVP_F_RC2_MAGIC_TO_METH,EVP_R_UNSUPPORTED_KEY_SIZE);
		EVPerr(EVP_F_RC2_MAGIC_TO_METH,EVP_R_UNSUPPORTED_KEY_SIZE);
		return(NULL);
		return(0);
		}
		}
	}
	}


@@ -158,25 +161,21 @@ static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
	{
	{
	long num=0;
	long num=0;
	int i=0,l;
	int i=0,l;
	EVP_CIPHER *e;
	int key_bits;
	unsigned char iv[EVP_MAX_IV_LENGTH];


	if (type != NULL)
	if (type != NULL)
		{
		{
		l=EVP_CIPHER_CTX_iv_length(c);
		l=EVP_CIPHER_CTX_iv_length(c);
		i=ASN1_TYPE_get_int_octetstring(type,&num,c->oiv,l);
		i=ASN1_TYPE_get_int_octetstring(type,&num,iv,l);
		if (i != l)
		if (i != l)
			return(-1);
			return(-1);
		else if (i > 0)
		key_bits =rc2_magic_to_meth((int)num);
			memcpy(c->iv,c->oiv,l);
		if (!key_bits)
		e=rc2_magic_to_meth((int)num);
		if (e == NULL)
			return(-1);
			return(-1);
		if (e != EVP_CIPHER_CTX_cipher(c))
		if(i > 0) EVP_CipherInit(c, NULL, NULL, iv, -1);
			{
		EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_RC2_KEY_BITS, key_bits, NULL);
			EVP_CIPHER_CTX_cipher(c)=e;
		EVP_CIPHER_CTX_set_key_length(c, key_bits / 8);
			EVP_CIPHER_CTX_set_key_length(c, EVP_CIPHER_key_length(c));
			rc2_init_key(c,NULL,NULL,1);
			}
		}
		}
	return(i);
	return(i);
	}
	}
@@ -188,11 +187,36 @@ static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type)


	if (type != NULL)
	if (type != NULL)
		{
		{
		num=rc2_meth_to_magic(EVP_CIPHER_CTX_cipher(c));
		num=rc2_meth_to_magic(c);
		j=EVP_CIPHER_CTX_iv_length(c);
		j=EVP_CIPHER_CTX_iv_length(c);
		i=ASN1_TYPE_set_int_octetstring(type,num,c->oiv,j);
		i=ASN1_TYPE_set_int_octetstring(type,num,c->oiv,j);
		}
		}
	return(i);
	return(i);
	}
	}


static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
	{
		switch(type) {

			case EVP_CTRL_INIT:
			c->c.rc2.key_bits = EVP_CIPHER_CTX_key_length(c) * 8;
			return 1;

			case EVP_CTRL_GET_RC2_KEY_BITS:
			*(int *)ptr = c->c.rc2.key_bits;
			return 1;
			
			
			case EVP_CTRL_SET_RC2_KEY_BITS:
			if(arg > 0) {
				c->c.rc2.key_bits = arg;
				return 1;
			}
			return 0;

			default:
			return -1;
		}
	}

#endif
#endif
+36 −36
Original line number Original line Diff line number Diff line
@@ -66,53 +66,53 @@


static int r_32_12_16_init_key(EVP_CIPHER_CTX *ctx, unsigned char *key,
static int r_32_12_16_init_key(EVP_CIPHER_CTX *ctx, unsigned char *key,
	unsigned char *iv,int enc);
	unsigned char *iv,int enc);
static int rc5_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr);


IMPLEMENT_BLOCK_CIPHER(rc5_32_12_16, rc5.ks, RC5_32, rc5, NID_rc5,
IMPLEMENT_BLOCK_CIPHER(rc5_32_12_16, rc5.ks, RC5_32, rc5, NID_rc5,
			8, EVP_RC5_32_12_16_KEY_SIZE, 8, 
			8, EVP_RC5_32_12_16_KEY_SIZE, 8, 
			0, r_32_12_16_init_key, NULL,
			EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT,
			NULL, NULL, NULL)
			r_32_12_16_init_key, NULL,
			NULL, NULL, rc5_ctrl)



#if 0
static int r_32_12_16_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
	unsigned char *in, unsigned int inl);
static EVP_CIPHER rc5_32_12_16_cbc_cipher=
	{
	NID_rc5_cbc,
	8,EVP_RC5_32_12_16_KEY_SIZE,8,
	EVP_CIPH_CBC_MODE,
	r_32_12_16_cbc_init_key,
	r_32_12_16_cbc_cipher,
	NULL,
	sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+
		sizeof((((EVP_CIPHER_CTX *)NULL)->c.rc5)),
	NULL,
	NULL,
	NULL
	};


EVP_CIPHER *EVP_rc5_32_12_16_cbc(void)
static int rc5_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
	{
	{
	return(&rc5_32_12_16_cbc_cipher);
		switch(type) {

			case EVP_CTRL_INIT:
			c->c.rc5.rounds = RC5_12_ROUNDS;
			return 1;

			case EVP_CTRL_GET_RC5_ROUNDS:
			*(int *)ptr = c->c.rc5.rounds;
			return 1;
			
			
			case EVP_CTRL_SET_RC5_ROUNDS:
			switch(arg) {
				case RC5_8_ROUNDS:
				case RC5_12_ROUNDS:
				case RC5_16_ROUNDS:
				c->c.rc5.rounds = arg;
				return 1;

				default:
				EVPerr(EVP_F_RC5_CTRL, EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS);
				return 0;
			}

			default:
			return -1;
		}
	}
	}
#endif


static int r_32_12_16_init_key(EVP_CIPHER_CTX *ctx, unsigned char *key,
static int r_32_12_16_init_key(EVP_CIPHER_CTX *ctx, unsigned char *key,
	     unsigned char *iv, int enc)
	     unsigned char *iv, int enc)
	{
	{
	RC5_32_set_key(&(ctx->c.rc5.ks),EVP_RC5_32_12_16_KEY_SIZE,
	RC5_32_set_key(&(ctx->c.rc5.ks),EVP_CIPHER_CTX_key_length(ctx),
			key,RC5_12_ROUNDS);
			key,ctx->c.rc5.rounds);
	return 1;
	return 1;
	}
	}
#if 0
static int r_32_12_16_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
	     unsigned char *in, unsigned int inl)
	{
	RC5_32_cbc_encrypt(
		in,out,(long)inl,
		&(ctx->c.rc5.ks),&(ctx->iv[0]),
		ctx->encrypt);
	return 1;
	}
#endif


#endif
#endif
+7 −0
Original line number Original line Diff line number Diff line
@@ -589,6 +589,7 @@ void ERR_load_EVP_strings(void );
void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);
void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);
int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);


#ifdef HEADER_BIO_H
#ifdef HEADER_BIO_H
BIO_METHOD *BIO_f_md(void);
BIO_METHOD *BIO_f_md(void);
@@ -738,6 +739,7 @@ void EVP_PBE_cleanup(void);
/* Function codes. */
/* Function codes. */
#define EVP_F_D2I_PKEY					 100
#define EVP_F_D2I_PKEY					 100
#define EVP_F_EVP_CIPHERINIT				 123
#define EVP_F_EVP_CIPHERINIT				 123
#define EVP_F_EVP_CIPHER_CTX_CTRL			 124
#define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH		 122
#define EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH		 122
#define EVP_F_EVP_DECRYPTFINAL				 101
#define EVP_F_EVP_DECRYPTFINAL				 101
#define EVP_F_EVP_MD_CTX_COPY				 110
#define EVP_F_EVP_MD_CTX_COPY				 110
@@ -759,12 +761,15 @@ void EVP_PBE_cleanup(void);
#define EVP_F_PKCS5_PBE_KEYIVGEN			 117
#define EVP_F_PKCS5_PBE_KEYIVGEN			 117
#define EVP_F_PKCS5_V2_PBE_KEYIVGEN			 118
#define EVP_F_PKCS5_V2_PBE_KEYIVGEN			 118
#define EVP_F_RC2_MAGIC_TO_METH				 109
#define EVP_F_RC2_MAGIC_TO_METH				 109
#define EVP_F_RC5_CTRL					 125


/* Reason codes. */
/* Reason codes. */
#define EVP_R_BAD_DECRYPT				 100
#define EVP_R_BAD_DECRYPT				 100
#define EVP_R_BN_DECODE_ERROR				 112
#define EVP_R_BN_DECODE_ERROR				 112
#define EVP_R_BN_PUBKEY_ERROR				 113
#define EVP_R_BN_PUBKEY_ERROR				 113
#define EVP_R_CIPHER_PARAMETER_ERROR			 122
#define EVP_R_CIPHER_PARAMETER_ERROR			 122
#define EVP_R_CTRL_NOT_IMPLEMENTED			 132
#define EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED		 133
#define EVP_R_DECODE_ERROR				 114
#define EVP_R_DECODE_ERROR				 114
#define EVP_R_DIFFERENT_KEY_TYPES			 101
#define EVP_R_DIFFERENT_KEY_TYPES			 101
#define EVP_R_ENCODE_ERROR				 115
#define EVP_R_ENCODE_ERROR				 115
@@ -772,6 +777,7 @@ void EVP_PBE_cleanup(void);
#define EVP_R_EXPECTING_AN_RSA_KEY			 127
#define EVP_R_EXPECTING_AN_RSA_KEY			 127
#define EVP_R_EXPECTING_A_DH_KEY			 128
#define EVP_R_EXPECTING_A_DH_KEY			 128
#define EVP_R_EXPECTING_A_DSA_KEY			 129
#define EVP_R_EXPECTING_A_DSA_KEY			 129
#define EVP_R_INITIALIZATION_ERROR			 134
#define EVP_R_INPUT_NOT_INITIALIZED			 111
#define EVP_R_INPUT_NOT_INITIALIZED			 111
#define EVP_R_INVALID_KEY_LENGTH			 130
#define EVP_R_INVALID_KEY_LENGTH			 130
#define EVP_R_IV_TOO_LARGE				 102
#define EVP_R_IV_TOO_LARGE				 102
@@ -784,6 +790,7 @@ void EVP_PBE_cleanup(void);
#define EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE			 117
#define EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE			 117
#define EVP_R_PUBLIC_KEY_NOT_RSA			 106
#define EVP_R_PUBLIC_KEY_NOT_RSA			 106
#define EVP_R_UNKNOWN_PBE_ALGORITHM			 121
#define EVP_R_UNKNOWN_PBE_ALGORITHM			 121
#define EVP_R_UNSUPORTED_NUMBER_OF_ROUNDS		 135
#define EVP_R_UNSUPPORTED_CIPHER			 107
#define EVP_R_UNSUPPORTED_CIPHER			 107
#define EVP_R_UNSUPPORTED_KEYLENGTH			 123
#define EVP_R_UNSUPPORTED_KEYLENGTH			 123
#define EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION	 124
#define EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION	 124
+31 −2
Original line number Original line Diff line number Diff line
@@ -73,10 +73,16 @@ void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx)
int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
	     unsigned char *key, unsigned char *iv, int enc)
	     unsigned char *key, unsigned char *iv, int enc)
	{
	{
	if(enc) enc = 1;
	if(enc && (enc != -1)) enc = 1;
	if (cipher) {
	if (cipher) {
		ctx->cipher=cipher;
		ctx->cipher=cipher;
		ctx->key_len = cipher->key_len;
		ctx->key_len = cipher->key_len;
		if(ctx->cipher->flags & EVP_CIPH_CTRL_INIT) {
			if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) {
				EVPerr(EVP_F_EVP_CIPHERINIT, EVP_R_INITIALIZATION_ERROR);
				return 0;
			}
		}
	} else if(!ctx->cipher) {
	} else if(!ctx->cipher) {
		EVPerr(EVP_F_EVP_CIPHERINIT, EVP_R_NO_CIPHER_SET);
		EVPerr(EVP_F_EVP_CIPHERINIT, EVP_R_NO_CIPHER_SET);
		return 0;
		return 0;
@@ -108,7 +114,7 @@ int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
	if(key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) {
	if(key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) {
		if(!ctx->cipher->init(ctx,key,iv,enc)) return 0;
		if(!ctx->cipher->init(ctx,key,iv,enc)) return 0;
	}
	}
	ctx->encrypt=enc;
	if(enc != -1) ctx->encrypt=enc;
	ctx->buf_len=0;
	ctx->buf_len=0;
	return 1;
	return 1;
	}
	}
@@ -301,6 +307,8 @@ int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c)


int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
	{
	{
	if(c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH) 
		return EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_KEY_LENGTH, keylen, NULL);
	if(c->key_len == keylen) return 1;
	if(c->key_len == keylen) return 1;
	if((keylen > 0) && (c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH))
	if((keylen > 0) && (c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH))
		{
		{
@@ -310,3 +318,24 @@ int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
	EVPerr(EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH,EVP_R_INVALID_KEY_LENGTH);
	EVPerr(EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH,EVP_R_INVALID_KEY_LENGTH);
	return 0;
	return 0;
	}
	}

int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
{
	int ret;
	if(!ctx->cipher) {
		EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_NO_CIPHER_SET);
		return 0;
	}

	if(!ctx->cipher->ctrl) {
		EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_NOT_IMPLEMENTED);
		return 0;
	}

	ret = ctx->cipher->ctrl(ctx, type, arg, ptr);
	if(ret == -1) {
		EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED);
		return 0;
	}
	return ret;
}
Loading