Import OpenSSL 0.9.8j.
[dragonfly.git] / crypto / openssl / crypto / evp / enc_min.c
1 /* crypto/evp/enc_min.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 #include <stdio.h>
60 #include "cryptlib.h"
61 #include <openssl/evp.h>
62 #include <openssl/err.h>
63 #include <openssl/rand.h>
64 #ifndef OPENSSL_NO_ENGINE
65 #include <openssl/engine.h>
66 #endif
67 #include "evp_locl.h"
68
69 void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx)
70         {
71 #ifdef OPENSSL_FIPS
72         FIPS_selftest_check();
73 #endif
74         memset(ctx,0,sizeof(EVP_CIPHER_CTX));
75         /* ctx->cipher=NULL; */
76         }
77
78 #ifdef OPENSSL_FIPS
79
80 /* The purpose of these is to trap programs that attempt to use non FIPS
81  * algorithms in FIPS mode and ignore the errors.
82  */
83
84 static int bad_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
85                     const unsigned char *iv, int enc)
86         { FIPS_ERROR_IGNORED("Cipher init"); return 0;}
87
88 static int bad_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
89                          const unsigned char *in, unsigned int inl)
90         { FIPS_ERROR_IGNORED("Cipher update"); return 0;}
91
92 /* NB: no cleanup because it is allowed after failed init */
93
94 static int bad_set_asn1(EVP_CIPHER_CTX *ctx, ASN1_TYPE *typ)
95         { FIPS_ERROR_IGNORED("Cipher set_asn1"); return 0;}
96 static int bad_get_asn1(EVP_CIPHER_CTX *ctx, ASN1_TYPE *typ)
97         { FIPS_ERROR_IGNORED("Cipher get_asn1"); return 0;}
98 static int bad_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
99         { FIPS_ERROR_IGNORED("Cipher ctrl"); return 0;}
100
101 static const EVP_CIPHER bad_cipher =
102         {
103         0,
104         0,
105         0,
106         0,
107         0,
108         bad_init,
109         bad_do_cipher,
110         NULL,
111         0,
112         bad_set_asn1,
113         bad_get_asn1,
114         bad_ctrl,
115         NULL
116         };
117
118 #endif
119
120 #ifndef OPENSSL_NO_ENGINE
121
122 #ifdef OPENSSL_FIPS
123
124 static int do_engine_null(ENGINE *impl) { return 0;}
125 static int do_evp_enc_engine_null(EVP_CIPHER_CTX *ctx,
126                                 const EVP_CIPHER **pciph, ENGINE *impl)
127         { return 1; }
128
129 static int (*do_engine_finish)(ENGINE *impl)
130                 = do_engine_null;
131
132 static int (*do_evp_enc_engine)
133         (EVP_CIPHER_CTX *ctx, const EVP_CIPHER **pciph, ENGINE *impl)
134                 = do_evp_enc_engine_null;
135
136 void int_EVP_CIPHER_set_engine_callbacks(
137         int (*eng_ciph_fin)(ENGINE *impl),
138         int (*eng_ciph_evp)
139                 (EVP_CIPHER_CTX *ctx, const EVP_CIPHER **pciph, ENGINE *impl))
140         {
141         do_engine_finish = eng_ciph_fin;
142         do_evp_enc_engine = eng_ciph_evp;
143         }
144
145 #else
146
147 #define do_engine_finish ENGINE_finish
148
149 static int do_evp_enc_engine(EVP_CIPHER_CTX *ctx, const EVP_CIPHER **pcipher, ENGINE *impl)
150         {
151         if(impl)
152                 {
153                 if (!ENGINE_init(impl))
154                         {
155                         EVPerr(EVP_F_DO_EVP_ENC_ENGINE, EVP_R_INITIALIZATION_ERROR);
156                         return 0;
157                         }
158                 }
159         else
160                 /* Ask if an ENGINE is reserved for this job */
161                 impl = ENGINE_get_cipher_engine((*pcipher)->nid);
162         if(impl)
163                 {
164                 /* There's an ENGINE for this job ... (apparently) */
165                 const EVP_CIPHER *c = ENGINE_get_cipher(impl, (*pcipher)->nid);
166                 if(!c)
167                         {
168                         /* One positive side-effect of US's export
169                          * control history, is that we should at least
170                          * be able to avoid using US mispellings of
171                          * "initialisation"? */
172                         EVPerr(EVP_F_DO_EVP_ENC_ENGINE, EVP_R_INITIALIZATION_ERROR);
173                         return 0;
174                         }
175                 /* We'll use the ENGINE's private cipher definition */
176                 *pcipher = c;
177                 /* Store the ENGINE functional reference so we know
178                  * 'cipher' came from an ENGINE and we need to release
179                  * it when done. */
180                 ctx->engine = impl;
181                 }
182         else
183                 ctx->engine = NULL;
184         return 1;
185         }
186
187 #endif
188
189 #endif
190
191 int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl,
192              const unsigned char *key, const unsigned char *iv, int enc)
193         {
194         if (enc == -1)
195                 enc = ctx->encrypt;
196         else
197                 {
198                 if (enc)
199                         enc = 1;
200                 ctx->encrypt = enc;
201                 }
202 #ifdef OPENSSL_NO_FIPS
203         if(FIPS_selftest_failed())
204                 {
205                 FIPSerr(FIPS_F_EVP_CIPHERINIT_EX,FIPS_R_FIPS_SELFTEST_FAILED);
206                 ctx->cipher = &bad_cipher;
207                 return 0;
208                 }
209 #endif
210 #ifndef OPENSSL_NO_ENGINE
211         /* Whether it's nice or not, "Inits" can be used on "Final"'d contexts
212          * so this context may already have an ENGINE! Try to avoid releasing
213          * the previous handle, re-querying for an ENGINE, and having a
214          * reinitialisation, when it may all be unecessary. */
215         if (ctx->engine && ctx->cipher && (!cipher ||
216                         (cipher && (cipher->nid == ctx->cipher->nid))))
217                 goto skip_to_init;
218 #endif
219         if (cipher)
220                 {
221                 /* Ensure a context left lying around from last time is cleared
222                  * (the previous check attempted to avoid this if the same
223                  * ENGINE and EVP_CIPHER could be used). */
224                 EVP_CIPHER_CTX_cleanup(ctx);
225
226                 /* Restore encrypt field: it is zeroed by cleanup */
227                 ctx->encrypt = enc;
228 #ifndef OPENSSL_NO_ENGINE
229                 if (!do_evp_enc_engine(ctx, &cipher, impl))
230                         return 0;
231 #endif
232
233                 ctx->cipher=cipher;
234                 if (ctx->cipher->ctx_size)
235                         {
236                         ctx->cipher_data=OPENSSL_malloc(ctx->cipher->ctx_size);
237                         if (!ctx->cipher_data)
238                                 {
239                                 EVPerr(EVP_F_EVP_CIPHERINIT_EX, ERR_R_MALLOC_FAILURE);
240                                 return 0;
241                                 }
242                         }
243                 else
244                         {
245                         ctx->cipher_data = NULL;
246                         }
247                 ctx->key_len = cipher->key_len;
248                 ctx->flags = 0;
249                 if(ctx->cipher->flags & EVP_CIPH_CTRL_INIT)
250                         {
251                         if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL))
252                                 {
253                                 EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR);
254                                 return 0;
255                                 }
256                         }
257                 }
258         else if(!ctx->cipher)
259                 {
260                 EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_NO_CIPHER_SET);
261                 return 0;
262                 }
263 #ifndef OPENSSL_NO_ENGINE
264 skip_to_init:
265 #endif
266         /* we assume block size is a power of 2 in *cryptUpdate */
267         OPENSSL_assert(ctx->cipher->block_size == 1
268             || ctx->cipher->block_size == 8
269             || ctx->cipher->block_size == 16);
270
271         if(!(EVP_CIPHER_CTX_flags(ctx) & EVP_CIPH_CUSTOM_IV)) {
272                 switch(EVP_CIPHER_CTX_mode(ctx)) {
273
274                         case EVP_CIPH_STREAM_CIPHER:
275                         case EVP_CIPH_ECB_MODE:
276                         break;
277
278                         case EVP_CIPH_CFB_MODE:
279                         case EVP_CIPH_OFB_MODE:
280
281                         ctx->num = 0;
282
283                         case EVP_CIPH_CBC_MODE:
284
285                         OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) <=
286                                         (int)sizeof(ctx->iv));
287                         if(iv) memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
288                         memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
289                         break;
290
291                         default:
292                         return 0;
293                         break;
294                 }
295         }
296
297 #ifdef OPENSSL_FIPS
298         /* After 'key' is set no further parameters changes are permissible.
299          * So only check for non FIPS enabling at this point.
300          */
301         if (key && FIPS_mode())
302                 {
303                 if (!(ctx->cipher->flags & EVP_CIPH_FLAG_FIPS)
304                         & !(ctx->flags & EVP_CIPH_FLAG_NON_FIPS_ALLOW))
305                         {
306                         EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_DISABLED_FOR_FIPS);
307 #if 0
308                         ERR_add_error_data(2, "cipher=",
309                                                 EVP_CIPHER_name(ctx->cipher));
310 #endif
311                         ctx->cipher = &bad_cipher;
312                         return 0;
313                         }
314                 }
315 #endif
316
317         if(key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) {
318                 if(!ctx->cipher->init(ctx,key,iv,enc)) return 0;
319         }
320         ctx->buf_len=0;
321         ctx->final_used=0;
322         ctx->block_mask=ctx->cipher->block_size-1;
323         return 1;
324         }
325
326 int EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *c)
327         {
328         if (c->cipher != NULL)
329                 {
330                 if(c->cipher->cleanup && !c->cipher->cleanup(c))
331                         return 0;
332                 /* Cleanse cipher context data */
333                 if (c->cipher_data)
334                         OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size);
335                 }
336         if (c->cipher_data)
337                 OPENSSL_free(c->cipher_data);
338 #ifndef OPENSSL_NO_ENGINE
339         if (c->engine)
340                 /* The EVP_CIPHER we used belongs to an ENGINE, release the
341                  * functional reference we held for this reason. */
342                 do_engine_finish(c->engine);
343 #endif
344         memset(c,0,sizeof(EVP_CIPHER_CTX));
345         return 1;
346         }
347
348 int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl)
349         {
350 #ifdef OPENSSL_FIPS
351         FIPS_selftest_check();
352 #endif
353         return ctx->cipher->do_cipher(ctx,out,in,inl);
354         }
355
356 int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
357 {
358         int ret;
359         if(!ctx->cipher) {
360                 EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_NO_CIPHER_SET);
361                 return 0;
362         }
363
364         if(!ctx->cipher->ctrl) {
365                 EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_NOT_IMPLEMENTED);
366                 return 0;
367         }
368
369         ret = ctx->cipher->ctrl(ctx, type, arg, ptr);
370         if(ret == -1) {
371                 EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED);
372                 return 0;
373         }
374         return ret;
375 }
376
377 unsigned long EVP_CIPHER_CTX_flags(const EVP_CIPHER_CTX *ctx)
378         {
379         return ctx->cipher->flags;
380         }
381
382 int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx)
383         {
384         return ctx->cipher->iv_len;
385         }
386
387 int EVP_CIPHER_nid(const EVP_CIPHER *cipher)
388         {
389         return cipher->nid;
390         }