xref: /onnv-gate/usr/src/common/openssl/crypto/evp/evp_enc.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /* crypto/evp/evp_enc.c */
2*0Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3*0Sstevel@tonic-gate  * All rights reserved.
4*0Sstevel@tonic-gate  *
5*0Sstevel@tonic-gate  * This package is an SSL implementation written
6*0Sstevel@tonic-gate  * by Eric Young (eay@cryptsoft.com).
7*0Sstevel@tonic-gate  * The implementation was written so as to conform with Netscapes SSL.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * This library is free for commercial and non-commercial use as long as
10*0Sstevel@tonic-gate  * the following conditions are aheared to.  The following conditions
11*0Sstevel@tonic-gate  * apply to all code found in this distribution, be it the RC4, RSA,
12*0Sstevel@tonic-gate  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13*0Sstevel@tonic-gate  * included with this distribution is covered by the same copyright terms
14*0Sstevel@tonic-gate  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15*0Sstevel@tonic-gate  *
16*0Sstevel@tonic-gate  * Copyright remains Eric Young's, and as such any Copyright notices in
17*0Sstevel@tonic-gate  * the code are not to be removed.
18*0Sstevel@tonic-gate  * If this package is used in a product, Eric Young should be given attribution
19*0Sstevel@tonic-gate  * as the author of the parts of the library used.
20*0Sstevel@tonic-gate  * This can be in the form of a textual message at program startup or
21*0Sstevel@tonic-gate  * in documentation (online or textual) provided with the package.
22*0Sstevel@tonic-gate  *
23*0Sstevel@tonic-gate  * Redistribution and use in source and binary forms, with or without
24*0Sstevel@tonic-gate  * modification, are permitted provided that the following conditions
25*0Sstevel@tonic-gate  * are met:
26*0Sstevel@tonic-gate  * 1. Redistributions of source code must retain the copyright
27*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer.
28*0Sstevel@tonic-gate  * 2. Redistributions in binary form must reproduce the above copyright
29*0Sstevel@tonic-gate  *    notice, this list of conditions and the following disclaimer in the
30*0Sstevel@tonic-gate  *    documentation and/or other materials provided with the distribution.
31*0Sstevel@tonic-gate  * 3. All advertising materials mentioning features or use of this software
32*0Sstevel@tonic-gate  *    must display the following acknowledgement:
33*0Sstevel@tonic-gate  *    "This product includes cryptographic software written by
34*0Sstevel@tonic-gate  *     Eric Young (eay@cryptsoft.com)"
35*0Sstevel@tonic-gate  *    The word 'cryptographic' can be left out if the rouines from the library
36*0Sstevel@tonic-gate  *    being used are not cryptographic related :-).
37*0Sstevel@tonic-gate  * 4. If you include any Windows specific code (or a derivative thereof) from
38*0Sstevel@tonic-gate  *    the apps directory (application code) you must include an acknowledgement:
39*0Sstevel@tonic-gate  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40*0Sstevel@tonic-gate  *
41*0Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42*0Sstevel@tonic-gate  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43*0Sstevel@tonic-gate  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44*0Sstevel@tonic-gate  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45*0Sstevel@tonic-gate  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46*0Sstevel@tonic-gate  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47*0Sstevel@tonic-gate  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48*0Sstevel@tonic-gate  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49*0Sstevel@tonic-gate  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50*0Sstevel@tonic-gate  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51*0Sstevel@tonic-gate  * SUCH DAMAGE.
52*0Sstevel@tonic-gate  *
53*0Sstevel@tonic-gate  * The licence and distribution terms for any publically available version or
54*0Sstevel@tonic-gate  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55*0Sstevel@tonic-gate  * copied and put under another distribution licence
56*0Sstevel@tonic-gate  * [including the GNU Public Licence.]
57*0Sstevel@tonic-gate  */
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate #include <stdio.h>
60*0Sstevel@tonic-gate #include "cryptlib.h"
61*0Sstevel@tonic-gate #include <openssl/evp.h>
62*0Sstevel@tonic-gate #include <openssl/err.h>
63*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
64*0Sstevel@tonic-gate #include <openssl/engine.h>
65*0Sstevel@tonic-gate #endif
66*0Sstevel@tonic-gate #include "evp_locl.h"
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate const char *EVP_version="EVP" OPENSSL_VERSION_PTEXT;
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx)
71*0Sstevel@tonic-gate 	{
72*0Sstevel@tonic-gate 	memset(ctx,0,sizeof(EVP_CIPHER_CTX));
73*0Sstevel@tonic-gate 	/* ctx->cipher=NULL; */
74*0Sstevel@tonic-gate 	}
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
78*0Sstevel@tonic-gate 	     const unsigned char *key, const unsigned char *iv, int enc)
79*0Sstevel@tonic-gate 	{
80*0Sstevel@tonic-gate 	if (cipher)
81*0Sstevel@tonic-gate 		EVP_CIPHER_CTX_init(ctx);
82*0Sstevel@tonic-gate 	return EVP_CipherInit_ex(ctx,cipher,NULL,key,iv,enc);
83*0Sstevel@tonic-gate 	}
84*0Sstevel@tonic-gate 
85*0Sstevel@tonic-gate int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl,
86*0Sstevel@tonic-gate 	     const unsigned char *key, const unsigned char *iv, int enc)
87*0Sstevel@tonic-gate 	{
88*0Sstevel@tonic-gate 	if (enc == -1)
89*0Sstevel@tonic-gate 		enc = ctx->encrypt;
90*0Sstevel@tonic-gate 	else
91*0Sstevel@tonic-gate 		{
92*0Sstevel@tonic-gate 		if (enc)
93*0Sstevel@tonic-gate 			enc = 1;
94*0Sstevel@tonic-gate 		ctx->encrypt = enc;
95*0Sstevel@tonic-gate 		}
96*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
97*0Sstevel@tonic-gate 	/* Whether it's nice or not, "Inits" can be used on "Final"'d contexts
98*0Sstevel@tonic-gate 	 * so this context may already have an ENGINE! Try to avoid releasing
99*0Sstevel@tonic-gate 	 * the previous handle, re-querying for an ENGINE, and having a
100*0Sstevel@tonic-gate 	 * reinitialisation, when it may all be unecessary. */
101*0Sstevel@tonic-gate 	if (ctx->engine && ctx->cipher && (!cipher ||
102*0Sstevel@tonic-gate 			(cipher && (cipher->nid == ctx->cipher->nid))))
103*0Sstevel@tonic-gate 		goto skip_to_init;
104*0Sstevel@tonic-gate #endif
105*0Sstevel@tonic-gate 	if (cipher)
106*0Sstevel@tonic-gate 		{
107*0Sstevel@tonic-gate 		/* Ensure a context left lying around from last time is cleared
108*0Sstevel@tonic-gate 		 * (the previous check attempted to avoid this if the same
109*0Sstevel@tonic-gate 		 * ENGINE and EVP_CIPHER could be used). */
110*0Sstevel@tonic-gate 		EVP_CIPHER_CTX_cleanup(ctx);
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate 		/* Restore encrypt field: it is zeroed by cleanup */
113*0Sstevel@tonic-gate 		ctx->encrypt = enc;
114*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
115*0Sstevel@tonic-gate 		if(impl)
116*0Sstevel@tonic-gate 			{
117*0Sstevel@tonic-gate 			if (!ENGINE_init(impl))
118*0Sstevel@tonic-gate 				{
119*0Sstevel@tonic-gate 				EVPerr(EVP_F_EVP_CIPHERINIT, EVP_R_INITIALIZATION_ERROR);
120*0Sstevel@tonic-gate 				return 0;
121*0Sstevel@tonic-gate 				}
122*0Sstevel@tonic-gate 			}
123*0Sstevel@tonic-gate 		else
124*0Sstevel@tonic-gate 			/* Ask if an ENGINE is reserved for this job */
125*0Sstevel@tonic-gate 			impl = ENGINE_get_cipher_engine(cipher->nid);
126*0Sstevel@tonic-gate 		if(impl)
127*0Sstevel@tonic-gate 			{
128*0Sstevel@tonic-gate 			/* There's an ENGINE for this job ... (apparently) */
129*0Sstevel@tonic-gate 			const EVP_CIPHER *c = ENGINE_get_cipher(impl, cipher->nid);
130*0Sstevel@tonic-gate 			if(!c)
131*0Sstevel@tonic-gate 				{
132*0Sstevel@tonic-gate 				/* One positive side-effect of US's export
133*0Sstevel@tonic-gate 				 * control history, is that we should at least
134*0Sstevel@tonic-gate 				 * be able to avoid using US mispellings of
135*0Sstevel@tonic-gate 				 * "initialisation"? */
136*0Sstevel@tonic-gate 				EVPerr(EVP_F_EVP_CIPHERINIT, EVP_R_INITIALIZATION_ERROR);
137*0Sstevel@tonic-gate 				return 0;
138*0Sstevel@tonic-gate 				}
139*0Sstevel@tonic-gate 			/* We'll use the ENGINE's private cipher definition */
140*0Sstevel@tonic-gate 			cipher = c;
141*0Sstevel@tonic-gate 			/* Store the ENGINE functional reference so we know
142*0Sstevel@tonic-gate 			 * 'cipher' came from an ENGINE and we need to release
143*0Sstevel@tonic-gate 			 * it when done. */
144*0Sstevel@tonic-gate 			ctx->engine = impl;
145*0Sstevel@tonic-gate 			}
146*0Sstevel@tonic-gate 		else
147*0Sstevel@tonic-gate 			ctx->engine = NULL;
148*0Sstevel@tonic-gate #endif
149*0Sstevel@tonic-gate 
150*0Sstevel@tonic-gate 		ctx->cipher=cipher;
151*0Sstevel@tonic-gate 		if (ctx->cipher->ctx_size)
152*0Sstevel@tonic-gate 			{
153*0Sstevel@tonic-gate 			ctx->cipher_data=OPENSSL_malloc(ctx->cipher->ctx_size);
154*0Sstevel@tonic-gate 			if (!ctx->cipher_data)
155*0Sstevel@tonic-gate 				{
156*0Sstevel@tonic-gate 				EVPerr(EVP_F_EVP_CIPHERINIT, ERR_R_MALLOC_FAILURE);
157*0Sstevel@tonic-gate 				return 0;
158*0Sstevel@tonic-gate 				}
159*0Sstevel@tonic-gate 			}
160*0Sstevel@tonic-gate 		else
161*0Sstevel@tonic-gate 			{
162*0Sstevel@tonic-gate 			ctx->cipher_data = NULL;
163*0Sstevel@tonic-gate 			}
164*0Sstevel@tonic-gate 		ctx->key_len = cipher->key_len;
165*0Sstevel@tonic-gate 		ctx->flags = 0;
166*0Sstevel@tonic-gate 		if(ctx->cipher->flags & EVP_CIPH_CTRL_INIT)
167*0Sstevel@tonic-gate 			{
168*0Sstevel@tonic-gate 			if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL))
169*0Sstevel@tonic-gate 				{
170*0Sstevel@tonic-gate 				EVPerr(EVP_F_EVP_CIPHERINIT, EVP_R_INITIALIZATION_ERROR);
171*0Sstevel@tonic-gate 				return 0;
172*0Sstevel@tonic-gate 				}
173*0Sstevel@tonic-gate 			}
174*0Sstevel@tonic-gate 		}
175*0Sstevel@tonic-gate 	else if(!ctx->cipher)
176*0Sstevel@tonic-gate 		{
177*0Sstevel@tonic-gate 		EVPerr(EVP_F_EVP_CIPHERINIT, EVP_R_NO_CIPHER_SET);
178*0Sstevel@tonic-gate 		return 0;
179*0Sstevel@tonic-gate 		}
180*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
181*0Sstevel@tonic-gate skip_to_init:
182*0Sstevel@tonic-gate #endif
183*0Sstevel@tonic-gate 	/* we assume block size is a power of 2 in *cryptUpdate */
184*0Sstevel@tonic-gate 	OPENSSL_assert(ctx->cipher->block_size == 1
185*0Sstevel@tonic-gate 	    || ctx->cipher->block_size == 8
186*0Sstevel@tonic-gate 	    || ctx->cipher->block_size == 16);
187*0Sstevel@tonic-gate 
188*0Sstevel@tonic-gate 	if(!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) {
189*0Sstevel@tonic-gate 		switch(EVP_CIPHER_CTX_mode(ctx)) {
190*0Sstevel@tonic-gate 
191*0Sstevel@tonic-gate 			case EVP_CIPH_STREAM_CIPHER:
192*0Sstevel@tonic-gate 			case EVP_CIPH_ECB_MODE:
193*0Sstevel@tonic-gate 			break;
194*0Sstevel@tonic-gate 
195*0Sstevel@tonic-gate 			case EVP_CIPH_CFB_MODE:
196*0Sstevel@tonic-gate 			case EVP_CIPH_OFB_MODE:
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate 			ctx->num = 0;
199*0Sstevel@tonic-gate 
200*0Sstevel@tonic-gate 			case EVP_CIPH_CBC_MODE:
201*0Sstevel@tonic-gate 
202*0Sstevel@tonic-gate 			OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) <= sizeof ctx->iv);
203*0Sstevel@tonic-gate 			if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
204*0Sstevel@tonic-gate 			memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
205*0Sstevel@tonic-gate 			break;
206*0Sstevel@tonic-gate 
207*0Sstevel@tonic-gate 			default:
208*0Sstevel@tonic-gate 			return 0;
209*0Sstevel@tonic-gate 			break;
210*0Sstevel@tonic-gate 		}
211*0Sstevel@tonic-gate 	}
212*0Sstevel@tonic-gate 
213*0Sstevel@tonic-gate 	if(key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) {
214*0Sstevel@tonic-gate 		if(!ctx->cipher->init(ctx,key,iv,enc)) return 0;
215*0Sstevel@tonic-gate 	}
216*0Sstevel@tonic-gate 	ctx->buf_len=0;
217*0Sstevel@tonic-gate 	ctx->final_used=0;
218*0Sstevel@tonic-gate 	ctx->block_mask=ctx->cipher->block_size-1;
219*0Sstevel@tonic-gate 	return 1;
220*0Sstevel@tonic-gate 	}
221*0Sstevel@tonic-gate 
222*0Sstevel@tonic-gate int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
223*0Sstevel@tonic-gate 	     const unsigned char *in, int inl)
224*0Sstevel@tonic-gate 	{
225*0Sstevel@tonic-gate 	if (ctx->encrypt)
226*0Sstevel@tonic-gate 		return EVP_EncryptUpdate(ctx,out,outl,in,inl);
227*0Sstevel@tonic-gate 	else	return EVP_DecryptUpdate(ctx,out,outl,in,inl);
228*0Sstevel@tonic-gate 	}
229*0Sstevel@tonic-gate 
230*0Sstevel@tonic-gate int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
231*0Sstevel@tonic-gate 	{
232*0Sstevel@tonic-gate 	if (ctx->encrypt)
233*0Sstevel@tonic-gate 		return EVP_EncryptFinal_ex(ctx,out,outl);
234*0Sstevel@tonic-gate 	else	return EVP_DecryptFinal_ex(ctx,out,outl);
235*0Sstevel@tonic-gate 	}
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
238*0Sstevel@tonic-gate 	{
239*0Sstevel@tonic-gate 	if (ctx->encrypt)
240*0Sstevel@tonic-gate 		return EVP_EncryptFinal(ctx,out,outl);
241*0Sstevel@tonic-gate 	else	return EVP_DecryptFinal(ctx,out,outl);
242*0Sstevel@tonic-gate 	}
243*0Sstevel@tonic-gate 
244*0Sstevel@tonic-gate int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
245*0Sstevel@tonic-gate 	     const unsigned char *key, const unsigned char *iv)
246*0Sstevel@tonic-gate 	{
247*0Sstevel@tonic-gate 	return EVP_CipherInit(ctx, cipher, key, iv, 1);
248*0Sstevel@tonic-gate 	}
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,const EVP_CIPHER *cipher, ENGINE *impl,
251*0Sstevel@tonic-gate 		const unsigned char *key, const unsigned char *iv)
252*0Sstevel@tonic-gate 	{
253*0Sstevel@tonic-gate 	return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 1);
254*0Sstevel@tonic-gate 	}
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
257*0Sstevel@tonic-gate 	     const unsigned char *key, const unsigned char *iv)
258*0Sstevel@tonic-gate 	{
259*0Sstevel@tonic-gate 	return EVP_CipherInit(ctx, cipher, key, iv, 0);
260*0Sstevel@tonic-gate 	}
261*0Sstevel@tonic-gate 
262*0Sstevel@tonic-gate int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl,
263*0Sstevel@tonic-gate 	     const unsigned char *key, const unsigned char *iv)
264*0Sstevel@tonic-gate 	{
265*0Sstevel@tonic-gate 	return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 0);
266*0Sstevel@tonic-gate 	}
267*0Sstevel@tonic-gate 
268*0Sstevel@tonic-gate int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
269*0Sstevel@tonic-gate 	     const unsigned char *in, int inl)
270*0Sstevel@tonic-gate 	{
271*0Sstevel@tonic-gate 	int i,j,bl;
272*0Sstevel@tonic-gate 
273*0Sstevel@tonic-gate 	OPENSSL_assert(inl > 0);
274*0Sstevel@tonic-gate 	if(ctx->buf_len == 0 && (inl&(ctx->block_mask)) == 0)
275*0Sstevel@tonic-gate 		{
276*0Sstevel@tonic-gate 		if(ctx->cipher->do_cipher(ctx,out,in,inl))
277*0Sstevel@tonic-gate 			{
278*0Sstevel@tonic-gate 			*outl=inl;
279*0Sstevel@tonic-gate 			return 1;
280*0Sstevel@tonic-gate 			}
281*0Sstevel@tonic-gate 		else
282*0Sstevel@tonic-gate 			{
283*0Sstevel@tonic-gate 			*outl=0;
284*0Sstevel@tonic-gate 			return 0;
285*0Sstevel@tonic-gate 			}
286*0Sstevel@tonic-gate 		}
287*0Sstevel@tonic-gate 	i=ctx->buf_len;
288*0Sstevel@tonic-gate 	bl=ctx->cipher->block_size;
289*0Sstevel@tonic-gate 	OPENSSL_assert(bl <= sizeof ctx->buf);
290*0Sstevel@tonic-gate 	if (i != 0)
291*0Sstevel@tonic-gate 		{
292*0Sstevel@tonic-gate 		if (i+inl < bl)
293*0Sstevel@tonic-gate 			{
294*0Sstevel@tonic-gate 			memcpy(&(ctx->buf[i]),in,inl);
295*0Sstevel@tonic-gate 			ctx->buf_len+=inl;
296*0Sstevel@tonic-gate 			*outl=0;
297*0Sstevel@tonic-gate 			return 1;
298*0Sstevel@tonic-gate 			}
299*0Sstevel@tonic-gate 		else
300*0Sstevel@tonic-gate 			{
301*0Sstevel@tonic-gate 			j=bl-i;
302*0Sstevel@tonic-gate 			memcpy(&(ctx->buf[i]),in,j);
303*0Sstevel@tonic-gate 			if(!ctx->cipher->do_cipher(ctx,out,ctx->buf,bl)) return 0;
304*0Sstevel@tonic-gate 			inl-=j;
305*0Sstevel@tonic-gate 			in+=j;
306*0Sstevel@tonic-gate 			out+=bl;
307*0Sstevel@tonic-gate 			*outl=bl;
308*0Sstevel@tonic-gate 			}
309*0Sstevel@tonic-gate 		}
310*0Sstevel@tonic-gate 	else
311*0Sstevel@tonic-gate 		*outl = 0;
312*0Sstevel@tonic-gate 	i=inl&(bl-1);
313*0Sstevel@tonic-gate 	inl-=i;
314*0Sstevel@tonic-gate 	if (inl > 0)
315*0Sstevel@tonic-gate 		{
316*0Sstevel@tonic-gate 		if(!ctx->cipher->do_cipher(ctx,out,in,inl)) return 0;
317*0Sstevel@tonic-gate 		*outl+=inl;
318*0Sstevel@tonic-gate 		}
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate 	if (i != 0)
321*0Sstevel@tonic-gate 		memcpy(ctx->buf,&(in[inl]),i);
322*0Sstevel@tonic-gate 	ctx->buf_len=i;
323*0Sstevel@tonic-gate 	return 1;
324*0Sstevel@tonic-gate 	}
325*0Sstevel@tonic-gate 
326*0Sstevel@tonic-gate int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
327*0Sstevel@tonic-gate 	{
328*0Sstevel@tonic-gate 	int ret;
329*0Sstevel@tonic-gate 	ret = EVP_EncryptFinal_ex(ctx, out, outl);
330*0Sstevel@tonic-gate 	return ret;
331*0Sstevel@tonic-gate 	}
332*0Sstevel@tonic-gate 
333*0Sstevel@tonic-gate int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
334*0Sstevel@tonic-gate 	{
335*0Sstevel@tonic-gate 	int i,n,b,bl,ret;
336*0Sstevel@tonic-gate 
337*0Sstevel@tonic-gate 	b=ctx->cipher->block_size;
338*0Sstevel@tonic-gate 	OPENSSL_assert(b <= sizeof ctx->buf);
339*0Sstevel@tonic-gate 	if (b == 1)
340*0Sstevel@tonic-gate 		{
341*0Sstevel@tonic-gate 		*outl=0;
342*0Sstevel@tonic-gate 		return 1;
343*0Sstevel@tonic-gate 		}
344*0Sstevel@tonic-gate 	bl=ctx->buf_len;
345*0Sstevel@tonic-gate 	if (ctx->flags & EVP_CIPH_NO_PADDING)
346*0Sstevel@tonic-gate 		{
347*0Sstevel@tonic-gate 		if(bl)
348*0Sstevel@tonic-gate 			{
349*0Sstevel@tonic-gate 			EVPerr(EVP_F_EVP_ENCRYPTFINAL,EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
350*0Sstevel@tonic-gate 			return 0;
351*0Sstevel@tonic-gate 			}
352*0Sstevel@tonic-gate 		*outl = 0;
353*0Sstevel@tonic-gate 		return 1;
354*0Sstevel@tonic-gate 		}
355*0Sstevel@tonic-gate 
356*0Sstevel@tonic-gate 	n=b-bl;
357*0Sstevel@tonic-gate 	for (i=bl; i<b; i++)
358*0Sstevel@tonic-gate 		ctx->buf[i]=n;
359*0Sstevel@tonic-gate 	ret=ctx->cipher->do_cipher(ctx,out,ctx->buf,b);
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate 
362*0Sstevel@tonic-gate 	if(ret)
363*0Sstevel@tonic-gate 		*outl=b;
364*0Sstevel@tonic-gate 
365*0Sstevel@tonic-gate 	return ret;
366*0Sstevel@tonic-gate 	}
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
369*0Sstevel@tonic-gate 	     const unsigned char *in, int inl)
370*0Sstevel@tonic-gate 	{
371*0Sstevel@tonic-gate 	int b, fix_len;
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate 	if (inl == 0)
374*0Sstevel@tonic-gate 		{
375*0Sstevel@tonic-gate 		*outl=0;
376*0Sstevel@tonic-gate 		return 1;
377*0Sstevel@tonic-gate 		}
378*0Sstevel@tonic-gate 
379*0Sstevel@tonic-gate 	if (ctx->flags & EVP_CIPH_NO_PADDING)
380*0Sstevel@tonic-gate 		return EVP_EncryptUpdate(ctx, out, outl, in, inl);
381*0Sstevel@tonic-gate 
382*0Sstevel@tonic-gate 	b=ctx->cipher->block_size;
383*0Sstevel@tonic-gate 	OPENSSL_assert(b <= sizeof ctx->final);
384*0Sstevel@tonic-gate 
385*0Sstevel@tonic-gate 	if(ctx->final_used)
386*0Sstevel@tonic-gate 		{
387*0Sstevel@tonic-gate 		memcpy(out,ctx->final,b);
388*0Sstevel@tonic-gate 		out+=b;
389*0Sstevel@tonic-gate 		fix_len = 1;
390*0Sstevel@tonic-gate 		}
391*0Sstevel@tonic-gate 	else
392*0Sstevel@tonic-gate 		fix_len = 0;
393*0Sstevel@tonic-gate 
394*0Sstevel@tonic-gate 
395*0Sstevel@tonic-gate 	if(!EVP_EncryptUpdate(ctx,out,outl,in,inl))
396*0Sstevel@tonic-gate 		return 0;
397*0Sstevel@tonic-gate 
398*0Sstevel@tonic-gate 	/* if we have 'decrypted' a multiple of block size, make sure
399*0Sstevel@tonic-gate 	 * we have a copy of this last block */
400*0Sstevel@tonic-gate 	if (b > 1 && !ctx->buf_len)
401*0Sstevel@tonic-gate 		{
402*0Sstevel@tonic-gate 		*outl-=b;
403*0Sstevel@tonic-gate 		ctx->final_used=1;
404*0Sstevel@tonic-gate 		memcpy(ctx->final,&out[*outl],b);
405*0Sstevel@tonic-gate 		}
406*0Sstevel@tonic-gate 	else
407*0Sstevel@tonic-gate 		ctx->final_used = 0;
408*0Sstevel@tonic-gate 
409*0Sstevel@tonic-gate 	if (fix_len)
410*0Sstevel@tonic-gate 		*outl += b;
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate 	return 1;
413*0Sstevel@tonic-gate 	}
414*0Sstevel@tonic-gate 
415*0Sstevel@tonic-gate int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
416*0Sstevel@tonic-gate 	{
417*0Sstevel@tonic-gate 	int ret;
418*0Sstevel@tonic-gate 	ret = EVP_DecryptFinal_ex(ctx, out, outl);
419*0Sstevel@tonic-gate 	return ret;
420*0Sstevel@tonic-gate 	}
421*0Sstevel@tonic-gate 
422*0Sstevel@tonic-gate int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
423*0Sstevel@tonic-gate 	{
424*0Sstevel@tonic-gate 	int i,b;
425*0Sstevel@tonic-gate 	int n;
426*0Sstevel@tonic-gate 
427*0Sstevel@tonic-gate 	*outl=0;
428*0Sstevel@tonic-gate 	b=ctx->cipher->block_size;
429*0Sstevel@tonic-gate 	if (ctx->flags & EVP_CIPH_NO_PADDING)
430*0Sstevel@tonic-gate 		{
431*0Sstevel@tonic-gate 		if(ctx->buf_len)
432*0Sstevel@tonic-gate 			{
433*0Sstevel@tonic-gate 			EVPerr(EVP_F_EVP_DECRYPTFINAL,EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
434*0Sstevel@tonic-gate 			return 0;
435*0Sstevel@tonic-gate 			}
436*0Sstevel@tonic-gate 		*outl = 0;
437*0Sstevel@tonic-gate 		return 1;
438*0Sstevel@tonic-gate 		}
439*0Sstevel@tonic-gate 	if (b > 1)
440*0Sstevel@tonic-gate 		{
441*0Sstevel@tonic-gate 		if (ctx->buf_len || !ctx->final_used)
442*0Sstevel@tonic-gate 			{
443*0Sstevel@tonic-gate 			EVPerr(EVP_F_EVP_DECRYPTFINAL,EVP_R_WRONG_FINAL_BLOCK_LENGTH);
444*0Sstevel@tonic-gate 			return(0);
445*0Sstevel@tonic-gate 			}
446*0Sstevel@tonic-gate 		OPENSSL_assert(b <= sizeof ctx->final);
447*0Sstevel@tonic-gate 		n=ctx->final[b-1];
448*0Sstevel@tonic-gate 		if (n > b)
449*0Sstevel@tonic-gate 			{
450*0Sstevel@tonic-gate 			EVPerr(EVP_F_EVP_DECRYPTFINAL,EVP_R_BAD_DECRYPT);
451*0Sstevel@tonic-gate 			return(0);
452*0Sstevel@tonic-gate 			}
453*0Sstevel@tonic-gate 		for (i=0; i<n; i++)
454*0Sstevel@tonic-gate 			{
455*0Sstevel@tonic-gate 			if (ctx->final[--b] != n)
456*0Sstevel@tonic-gate 				{
457*0Sstevel@tonic-gate 				EVPerr(EVP_F_EVP_DECRYPTFINAL,EVP_R_BAD_DECRYPT);
458*0Sstevel@tonic-gate 				return(0);
459*0Sstevel@tonic-gate 				}
460*0Sstevel@tonic-gate 			}
461*0Sstevel@tonic-gate 		n=ctx->cipher->block_size-n;
462*0Sstevel@tonic-gate 		for (i=0; i<n; i++)
463*0Sstevel@tonic-gate 			out[i]=ctx->final[i];
464*0Sstevel@tonic-gate 		*outl=n;
465*0Sstevel@tonic-gate 		}
466*0Sstevel@tonic-gate 	else
467*0Sstevel@tonic-gate 		*outl=0;
468*0Sstevel@tonic-gate 	return(1);
469*0Sstevel@tonic-gate 	}
470*0Sstevel@tonic-gate 
471*0Sstevel@tonic-gate int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c)
472*0Sstevel@tonic-gate 	{
473*0Sstevel@tonic-gate 	if (c->cipher != NULL)
474*0Sstevel@tonic-gate 		{
475*0Sstevel@tonic-gate 		if(c->cipher->cleanup && !c->cipher->cleanup(c))
476*0Sstevel@tonic-gate 			return 0;
477*0Sstevel@tonic-gate 		/* Cleanse cipher context data */
478*0Sstevel@tonic-gate 		if (c->cipher_data)
479*0Sstevel@tonic-gate 			OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size);
480*0Sstevel@tonic-gate 		}
481*0Sstevel@tonic-gate 	if (c->cipher_data)
482*0Sstevel@tonic-gate 		OPENSSL_free(c->cipher_data);
483*0Sstevel@tonic-gate #ifndef OPENSSL_NO_ENGINE
484*0Sstevel@tonic-gate 	if (c->engine)
485*0Sstevel@tonic-gate 		/* The EVP_CIPHER we used belongs to an ENGINE, release the
486*0Sstevel@tonic-gate 		 * functional reference we held for this reason. */
487*0Sstevel@tonic-gate 		ENGINE_finish(c->engine);
488*0Sstevel@tonic-gate #endif
489*0Sstevel@tonic-gate 	memset(c,0,sizeof(EVP_CIPHER_CTX));
490*0Sstevel@tonic-gate 	return 1;
491*0Sstevel@tonic-gate 	}
492*0Sstevel@tonic-gate 
493*0Sstevel@tonic-gate int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen)
494*0Sstevel@tonic-gate 	{
495*0Sstevel@tonic-gate 	if(c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH)
496*0Sstevel@tonic-gate 		return EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_KEY_LENGTH, keylen, NULL);
497*0Sstevel@tonic-gate 	if(c->key_len == keylen) return 1;
498*0Sstevel@tonic-gate 	if((keylen > 0) && (c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH))
499*0Sstevel@tonic-gate 		{
500*0Sstevel@tonic-gate 		c->key_len = keylen;
501*0Sstevel@tonic-gate 		return 1;
502*0Sstevel@tonic-gate 		}
503*0Sstevel@tonic-gate 	EVPerr(EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH,EVP_R_INVALID_KEY_LENGTH);
504*0Sstevel@tonic-gate 	return 0;
505*0Sstevel@tonic-gate 	}
506*0Sstevel@tonic-gate 
507*0Sstevel@tonic-gate int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad)
508*0Sstevel@tonic-gate 	{
509*0Sstevel@tonic-gate 	if (pad) ctx->flags &= ~EVP_CIPH_NO_PADDING;
510*0Sstevel@tonic-gate 	else ctx->flags |= EVP_CIPH_NO_PADDING;
511*0Sstevel@tonic-gate 	return 1;
512*0Sstevel@tonic-gate 	}
513*0Sstevel@tonic-gate 
514*0Sstevel@tonic-gate int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
515*0Sstevel@tonic-gate {
516*0Sstevel@tonic-gate 	int ret;
517*0Sstevel@tonic-gate 	if(!ctx->cipher) {
518*0Sstevel@tonic-gate 		EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_NO_CIPHER_SET);
519*0Sstevel@tonic-gate 		return 0;
520*0Sstevel@tonic-gate 	}
521*0Sstevel@tonic-gate 
522*0Sstevel@tonic-gate 	if(!ctx->cipher->ctrl) {
523*0Sstevel@tonic-gate 		EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_NOT_IMPLEMENTED);
524*0Sstevel@tonic-gate 		return 0;
525*0Sstevel@tonic-gate 	}
526*0Sstevel@tonic-gate 
527*0Sstevel@tonic-gate 	ret = ctx->cipher->ctrl(ctx, type, arg, ptr);
528*0Sstevel@tonic-gate 	if(ret == -1) {
529*0Sstevel@tonic-gate 		EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED);
530*0Sstevel@tonic-gate 		return 0;
531*0Sstevel@tonic-gate 	}
532*0Sstevel@tonic-gate 	return ret;
533*0Sstevel@tonic-gate }
534