]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/evp/bio_enc.c
Adjust unixly mk1mf after introduction of tkey
[thirdparty/openssl.git] / crypto / evp / bio_enc.c
CommitLineData
d02b48c6 1/* crypto/evp/bio_enc.c */
58964a49 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
d02b48c6
RE
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.
0f113f3e 8 *
d02b48c6
RE
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).
0f113f3e 15 *
d02b48c6
RE
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.
0f113f3e 22 *
d02b48c6
RE
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 :-).
0f113f3e 37 * 4. If you include any Windows specific code (or a derivative thereof) from
d02b48c6
RE
38 * the apps directory (application code) you must include an acknowledgement:
39 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
0f113f3e 40 *
d02b48c6
RE
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.
0f113f3e 52 *
d02b48c6
RE
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 <errno.h>
61#include "cryptlib.h"
ec577822
BM
62#include <openssl/buffer.h>
63#include <openssl/evp.h>
d02b48c6 64
0e1c0612
UM
65static int enc_write(BIO *h, const char *buf, int num);
66static int enc_read(BIO *h, char *buf, int size);
0f113f3e
MC
67/*
68 * static int enc_puts(BIO *h, const char *str);
69 */
70/*
71 * static int enc_gets(BIO *h, char *str, int size);
72 */
0e1c0612 73static long enc_ctrl(BIO *h, int cmd, long arg1, void *arg2);
d02b48c6
RE
74static int enc_new(BIO *h);
75static int enc_free(BIO *data);
13083215 76static long enc_callback_ctrl(BIO *h, int cmd, bio_info_cb *fps);
0f113f3e
MC
77#define ENC_BLOCK_SIZE (1024*4)
78#define BUF_OFFSET (EVP_MAX_BLOCK_LENGTH*2)
79
80typedef struct enc_struct {
81 int buf_len;
82 int buf_off;
83 int cont; /* <= 0 when finished */
84 int finished;
85 int ok; /* bad decrypt */
86 EVP_CIPHER_CTX cipher;
87 /*
88 * buf is larger than ENC_BLOCK_SIZE because EVP_DecryptUpdate can return
89 * up to a block more data than is presented to it
90 */
91 char buf[ENC_BLOCK_SIZE + BUF_OFFSET + 2];
92} BIO_ENC_CTX;
93
94static BIO_METHOD methods_enc = {
95 BIO_TYPE_CIPHER, "cipher",
96 enc_write,
97 enc_read,
98 NULL, /* enc_puts, */
99 NULL, /* enc_gets, */
100 enc_ctrl,
101 enc_new,
102 enc_free,
103 enc_callback_ctrl,
104};
d02b48c6 105
6b691a5c 106BIO_METHOD *BIO_f_cipher(void)
0f113f3e
MC
107{
108 return (&methods_enc);
109}
d02b48c6 110
6b691a5c 111static int enc_new(BIO *bi)
0f113f3e
MC
112{
113 BIO_ENC_CTX *ctx;
114
b4faea50 115 ctx = OPENSSL_malloc(sizeof(*ctx));
0f113f3e
MC
116 if (ctx == NULL)
117 return (0);
118 EVP_CIPHER_CTX_init(&ctx->cipher);
119
120 ctx->buf_len = 0;
121 ctx->buf_off = 0;
122 ctx->cont = 1;
123 ctx->finished = 0;
124 ctx->ok = 1;
125
126 bi->init = 0;
127 bi->ptr = (char *)ctx;
128 bi->flags = 0;
129 return (1);
130}
d02b48c6 131
6b691a5c 132static int enc_free(BIO *a)
0f113f3e
MC
133{
134 BIO_ENC_CTX *b;
135
136 if (a == NULL)
137 return (0);
138 b = (BIO_ENC_CTX *)a->ptr;
139 EVP_CIPHER_CTX_cleanup(&(b->cipher));
4b45c6e5 140 OPENSSL_clear_free(a->ptr, sizeof(BIO_ENC_CTX));
0f113f3e
MC
141 a->ptr = NULL;
142 a->init = 0;
143 a->flags = 0;
144 return (1);
145}
146
6b691a5c 147static int enc_read(BIO *b, char *out, int outl)
0f113f3e
MC
148{
149 int ret = 0, i;
150 BIO_ENC_CTX *ctx;
151
152 if (out == NULL)
153 return (0);
154 ctx = (BIO_ENC_CTX *)b->ptr;
155
156 if ((ctx == NULL) || (b->next_bio == NULL))
157 return (0);
158
159 /* First check if there are bytes decoded/encoded */
160 if (ctx->buf_len > 0) {
161 i = ctx->buf_len - ctx->buf_off;
162 if (i > outl)
163 i = outl;
164 memcpy(out, &(ctx->buf[ctx->buf_off]), i);
165 ret = i;
166 out += i;
167 outl -= i;
168 ctx->buf_off += i;
169 if (ctx->buf_len == ctx->buf_off) {
170 ctx->buf_len = 0;
171 ctx->buf_off = 0;
172 }
173 }
174
175 /*
176 * At this point, we have room of outl bytes and an empty buffer, so we
177 * should read in some more.
178 */
179
180 while (outl > 0) {
181 if (ctx->cont <= 0)
182 break;
183
184 /*
185 * read in at IV offset, read the EVP_Cipher documentation about why
186 */
187 i = BIO_read(b->next_bio, &(ctx->buf[BUF_OFFSET]), ENC_BLOCK_SIZE);
188
189 if (i <= 0) {
190 /* Should be continue next time we are called? */
191 if (!BIO_should_retry(b->next_bio)) {
192 ctx->cont = i;
193 i = EVP_CipherFinal_ex(&(ctx->cipher),
194 (unsigned char *)ctx->buf,
195 &(ctx->buf_len));
196 ctx->ok = i;
197 ctx->buf_off = 0;
198 } else {
199 ret = (ret == 0) ? i : ret;
200 break;
201 }
202 } else {
203 if (!EVP_CipherUpdate(&(ctx->cipher),
204 (unsigned char *)ctx->buf, &ctx->buf_len,
205 (unsigned char *)&(ctx->buf[BUF_OFFSET]),
206 i)) {
207 BIO_clear_retry_flags(b);
208 return 0;
209 }
210 ctx->cont = 1;
211 /*
212 * Note: it is possible for EVP_CipherUpdate to decrypt zero
213 * bytes because this is or looks like the final block: if this
214 * happens we should retry and either read more data or decrypt
215 * the final block
216 */
217 if (ctx->buf_len == 0)
218 continue;
219 }
220
221 if (ctx->buf_len <= outl)
222 i = ctx->buf_len;
223 else
224 i = outl;
225 if (i <= 0)
226 break;
227 memcpy(out, ctx->buf, i);
228 ret += i;
229 ctx->buf_off = i;
230 outl -= i;
231 out += i;
232 }
233
234 BIO_clear_retry_flags(b);
235 BIO_copy_next_retry(b);
236 return ((ret == 0) ? ctx->cont : ret);
237}
d02b48c6 238
0e1c0612 239static int enc_write(BIO *b, const char *in, int inl)
0f113f3e
MC
240{
241 int ret = 0, n, i;
242 BIO_ENC_CTX *ctx;
243
244 ctx = (BIO_ENC_CTX *)b->ptr;
245 ret = inl;
246
247 BIO_clear_retry_flags(b);
248 n = ctx->buf_len - ctx->buf_off;
249 while (n > 0) {
250 i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n);
251 if (i <= 0) {
252 BIO_copy_next_retry(b);
253 return (i);
254 }
255 ctx->buf_off += i;
256 n -= i;
257 }
258 /* at this point all pending data has been written */
259
260 if ((in == NULL) || (inl <= 0))
261 return (0);
262
263 ctx->buf_off = 0;
264 while (inl > 0) {
265 n = (inl > ENC_BLOCK_SIZE) ? ENC_BLOCK_SIZE : inl;
266 if (!EVP_CipherUpdate(&(ctx->cipher),
267 (unsigned char *)ctx->buf, &ctx->buf_len,
268 (unsigned char *)in, n)) {
269 BIO_clear_retry_flags(b);
270 return 0;
271 }
272 inl -= n;
273 in += n;
274
275 ctx->buf_off = 0;
276 n = ctx->buf_len;
277 while (n > 0) {
278 i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n);
279 if (i <= 0) {
280 BIO_copy_next_retry(b);
281 return (ret == inl) ? i : ret - inl;
282 }
283 n -= i;
284 ctx->buf_off += i;
285 }
286 ctx->buf_len = 0;
287 ctx->buf_off = 0;
288 }
289 BIO_copy_next_retry(b);
290 return (ret);
291}
d02b48c6 292
0e1c0612 293static long enc_ctrl(BIO *b, int cmd, long num, void *ptr)
0f113f3e
MC
294{
295 BIO *dbio;
296 BIO_ENC_CTX *ctx, *dctx;
297 long ret = 1;
298 int i;
299 EVP_CIPHER_CTX **c_ctx;
300
301 ctx = (BIO_ENC_CTX *)b->ptr;
302
303 switch (cmd) {
304 case BIO_CTRL_RESET:
305 ctx->ok = 1;
306 ctx->finished = 0;
307 if (!EVP_CipherInit_ex(&(ctx->cipher), NULL, NULL, NULL, NULL,
308 ctx->cipher.encrypt))
309 return 0;
310 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
311 break;
312 case BIO_CTRL_EOF: /* More to read */
313 if (ctx->cont <= 0)
314 ret = 1;
315 else
316 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
317 break;
318 case BIO_CTRL_WPENDING:
319 ret = ctx->buf_len - ctx->buf_off;
320 if (ret <= 0)
321 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
322 break;
323 case BIO_CTRL_PENDING: /* More to read in buffer */
324 ret = ctx->buf_len - ctx->buf_off;
325 if (ret <= 0)
326 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
327 break;
328 case BIO_CTRL_FLUSH:
329 /* do a final write */
330 again:
331 while (ctx->buf_len != ctx->buf_off) {
332 i = enc_write(b, NULL, 0);
333 if (i < 0)
334 return i;
335 }
336
337 if (!ctx->finished) {
338 ctx->finished = 1;
339 ctx->buf_off = 0;
340 ret = EVP_CipherFinal_ex(&(ctx->cipher),
341 (unsigned char *)ctx->buf,
342 &(ctx->buf_len));
343 ctx->ok = (int)ret;
344 if (ret <= 0)
345 break;
346
347 /* push out the bytes */
348 goto again;
349 }
350
351 /* Finally flush the underlying BIO */
352 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
353 break;
354 case BIO_C_GET_CIPHER_STATUS:
355 ret = (long)ctx->ok;
356 break;
357 case BIO_C_DO_STATE_MACHINE:
358 BIO_clear_retry_flags(b);
359 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
360 BIO_copy_next_retry(b);
361 break;
362 case BIO_C_GET_CIPHER_CTX:
363 c_ctx = (EVP_CIPHER_CTX **)ptr;
364 (*c_ctx) = &(ctx->cipher);
365 b->init = 1;
366 break;
367 case BIO_CTRL_DUP:
368 dbio = (BIO *)ptr;
369 dctx = (BIO_ENC_CTX *)dbio->ptr;
370 EVP_CIPHER_CTX_init(&dctx->cipher);
371 ret = EVP_CIPHER_CTX_copy(&dctx->cipher, &ctx->cipher);
372 if (ret)
373 dbio->init = 1;
374 break;
375 default:
376 ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
377 break;
378 }
379 return (ret);
380}
d02b48c6 381
13083215 382static long enc_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
0f113f3e
MC
383{
384 long ret = 1;
385
386 if (b->next_bio == NULL)
387 return (0);
388 switch (cmd) {
389 default:
390 ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
391 break;
392 }
393 return (ret);
394}
d3442bc7 395
1d97c843 396/*-
58964a49
RE
397void BIO_set_cipher_ctx(b,c)
398BIO *b;
399EVP_CIPHER_ctx *c;
0f113f3e
MC
400 {
401 if (b == NULL) return;
402
403 if ((b->callback != NULL) &&
404 (b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,0L) <= 0))
405 return;
406
407 b->init=1;
408 ctx=(BIO_ENC_CTX *)b->ptr;
409 memcpy(ctx->cipher,c,sizeof(EVP_CIPHER_CTX));
410
411 if (b->callback != NULL)
412 b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,1L);
413 }
58964a49
RE
414*/
415
b6dcdbfc 416int BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k,
0f113f3e
MC
417 const unsigned char *i, int e)
418{
419 BIO_ENC_CTX *ctx;
420
421 if (b == NULL)
422 return 0;
423
424 if ((b->callback != NULL) &&
425 (b->callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 0L) <=
426 0))
427 return 0;
428
429 b->init = 1;
430 ctx = (BIO_ENC_CTX *)b->ptr;
431 if (!EVP_CipherInit_ex(&(ctx->cipher), c, NULL, k, i, e))
432 return 0;
433
434 if (b->callback != NULL)
435 return b->callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e,
436 1L);
437 return 1;
438}