]>
Commit | Line | Data |
---|---|---|
1745a3fb BL |
1 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
2 | * All rights reserved. | |
3 | * | |
4 | * This package is an SSL implementation written | |
5 | * by Eric Young (eay@cryptsoft.com). | |
6 | * The implementation was written so as to conform with Netscapes SSL. | |
0f113f3e | 7 | * |
1745a3fb BL |
8 | * This library is free for commercial and non-commercial use as long as |
9 | * the following conditions are aheared to. The following conditions | |
10 | * apply to all code found in this distribution, be it the RC4, RSA, | |
11 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation | |
12 | * included with this distribution is covered by the same copyright terms | |
13 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). | |
0f113f3e | 14 | * |
1745a3fb BL |
15 | * Copyright remains Eric Young's, and as such any Copyright notices in |
16 | * the code are not to be removed. | |
17 | * If this package is used in a product, Eric Young should be given attribution | |
18 | * as the author of the parts of the library used. | |
19 | * This can be in the form of a textual message at program startup or | |
20 | * in documentation (online or textual) provided with the package. | |
0f113f3e | 21 | * |
1745a3fb BL |
22 | * Redistribution and use in source and binary forms, with or without |
23 | * modification, are permitted provided that the following conditions | |
24 | * are met: | |
25 | * 1. Redistributions of source code must retain the copyright | |
26 | * notice, this list of conditions and the following disclaimer. | |
27 | * 2. Redistributions in binary form must reproduce the above copyright | |
28 | * notice, this list of conditions and the following disclaimer in the | |
29 | * documentation and/or other materials provided with the distribution. | |
30 | * 3. All advertising materials mentioning features or use of this software | |
31 | * must display the following acknowledgement: | |
32 | * "This product includes cryptographic software written by | |
33 | * Eric Young (eay@cryptsoft.com)" | |
34 | * The word 'cryptographic' can be left out if the rouines from the library | |
35 | * being used are not cryptographic related :-). | |
0f113f3e | 36 | * 4. If you include any Windows specific code (or a derivative thereof) from |
1745a3fb BL |
37 | * the apps directory (application code) you must include an acknowledgement: |
38 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" | |
0f113f3e | 39 | * |
1745a3fb BL |
40 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND |
41 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
43 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
44 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
45 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
46 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
47 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
48 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
49 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
50 | * SUCH DAMAGE. | |
0f113f3e | 51 | * |
1745a3fb BL |
52 | * The licence and distribution terms for any publically available version or |
53 | * derivative of this code cannot be changed. i.e. this code cannot simply be | |
54 | * copied and put under another distribution licence | |
55 | * [including the GNU Public Licence.] | |
56 | */ | |
57 | ||
1d97c843 | 58 | /*- |
0f113f3e MC |
59 | From: Arne Ansper <arne@cyber.ee> |
60 | ||
61 | Why BIO_f_reliable? | |
62 | ||
63 | I wrote function which took BIO* as argument, read data from it | |
64 | and processed it. Then I wanted to store the input file in | |
65 | encrypted form. OK I pushed BIO_f_cipher to the BIO stack | |
66 | and everything was OK. BUT if user types wrong password | |
67 | BIO_f_cipher outputs only garbage and my function crashes. Yes | |
68 | I can and I should fix my function, but BIO_f_cipher is | |
69 | easy way to add encryption support to many existing applications | |
70 | and it's hard to debug and fix them all. | |
71 | ||
72 | So I wanted another BIO which would catch the incorrect passwords and | |
73 | file damages which cause garbage on BIO_f_cipher's output. | |
74 | ||
75 | The easy way is to push the BIO_f_md and save the checksum at | |
76 | the end of the file. However there are several problems with this | |
77 | approach: | |
78 | ||
79 | 1) you must somehow separate checksum from actual data. | |
80 | 2) you need lot's of memory when reading the file, because you | |
81 | must read to the end of the file and verify the checksum before | |
82 | letting the application to read the data. | |
83 | ||
84 | BIO_f_reliable tries to solve both problems, so that you can | |
85 | read and write arbitrary long streams using only fixed amount | |
86 | of memory. | |
87 | ||
88 | BIO_f_reliable splits data stream into blocks. Each block is prefixed | |
89 | with it's length and suffixed with it's digest. So you need only | |
90 | several Kbytes of memory to buffer single block before verifying | |
91 | it's digest. | |
92 | ||
93 | BIO_f_reliable goes further and adds several important capabilities: | |
94 | ||
95 | 1) the digest of the block is computed over the whole stream | |
96 | -- so nobody can rearrange the blocks or remove or replace them. | |
97 | ||
98 | 2) to detect invalid passwords right at the start BIO_f_reliable | |
99 | adds special prefix to the stream. In order to avoid known plain-text | |
100 | attacks this prefix is generated as follows: | |
101 | ||
102 | *) digest is initialized with random seed instead of | |
103 | standardized one. | |
104 | *) same seed is written to output | |
105 | *) well-known text is then hashed and the output | |
106 | of the digest is also written to output. | |
107 | ||
108 | reader can now read the seed from stream, hash the same string | |
109 | and then compare the digest output. | |
110 | ||
111 | Bad things: BIO_f_reliable knows what's going on in EVP_Digest. I | |
112 | initially wrote and tested this code on x86 machine and wrote the | |
113 | digests out in machine-dependent order :( There are people using | |
114 | this code and I cannot change this easily without making existing | |
115 | data files unreadable. | |
1745a3fb BL |
116 | |
117 | */ | |
118 | ||
119 | #include <stdio.h> | |
120 | #include <errno.h> | |
3205db2b | 121 | #include <assert.h> |
b39fc560 | 122 | #include "internal/cryptlib.h" |
ec577822 BM |
123 | #include <openssl/buffer.h> |
124 | #include <openssl/bio.h> | |
125 | #include <openssl/evp.h> | |
126 | #include <openssl/rand.h> | |
ab0a14bb | 127 | #include "internal/evp_int.h" |
1745a3fb | 128 | |
0e1c0612 UM |
129 | static int ok_write(BIO *h, const char *buf, int num); |
130 | static int ok_read(BIO *h, char *buf, int size); | |
131 | static long ok_ctrl(BIO *h, int cmd, long arg1, void *arg2); | |
1745a3fb BL |
132 | static int ok_new(BIO *h); |
133 | static int ok_free(BIO *data); | |
13083215 | 134 | static long ok_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); |
d3442bc7 | 135 | |
0f113f3e MC |
136 | static __owur int sig_out(BIO *b); |
137 | static __owur int sig_in(BIO *b); | |
138 | static __owur int block_out(BIO *b); | |
139 | static __owur int block_in(BIO *b); | |
140 | #define OK_BLOCK_SIZE (1024*4) | |
141 | #define OK_BLOCK_BLOCK 4 | |
142 | #define IOBS (OK_BLOCK_SIZE+ OK_BLOCK_BLOCK+ 3*EVP_MAX_MD_SIZE) | |
1745a3fb BL |
143 | #define WELLKNOWN "The quick brown fox jumped over the lazy dog's back." |
144 | ||
0f113f3e MC |
145 | typedef struct ok_struct { |
146 | size_t buf_len; | |
147 | size_t buf_off; | |
148 | size_t buf_len_save; | |
149 | size_t buf_off_save; | |
150 | int cont; /* <= 0 when finished */ | |
151 | int finished; | |
77a01145 | 152 | EVP_MD_CTX *md; |
0f113f3e MC |
153 | int blockout; /* output block is ready */ |
154 | int sigio; /* must process signature */ | |
155 | unsigned char buf[IOBS]; | |
156 | } BIO_OK_CTX; | |
157 | ||
158 | static BIO_METHOD methods_ok = { | |
159 | BIO_TYPE_CIPHER, "reliable", | |
160 | ok_write, | |
161 | ok_read, | |
162 | NULL, /* ok_puts, */ | |
163 | NULL, /* ok_gets, */ | |
164 | ok_ctrl, | |
165 | ok_new, | |
166 | ok_free, | |
167 | ok_callback_ctrl, | |
168 | }; | |
1745a3fb | 169 | |
6b691a5c | 170 | BIO_METHOD *BIO_f_reliable(void) |
0f113f3e MC |
171 | { |
172 | return (&methods_ok); | |
173 | } | |
1745a3fb | 174 | |
6b691a5c | 175 | static int ok_new(BIO *bi) |
0f113f3e MC |
176 | { |
177 | BIO_OK_CTX *ctx; | |
178 | ||
64b25758 | 179 | ctx = OPENSSL_zalloc(sizeof(*ctx)); |
0f113f3e MC |
180 | if (ctx == NULL) |
181 | return (0); | |
182 | ||
0f113f3e | 183 | ctx->cont = 1; |
0f113f3e | 184 | ctx->sigio = 1; |
bfb0641f | 185 | ctx->md = EVP_MD_CTX_new(); |
0f113f3e MC |
186 | bi->init = 0; |
187 | bi->ptr = (char *)ctx; | |
188 | bi->flags = 0; | |
189 | return (1); | |
190 | } | |
1745a3fb | 191 | |
6b691a5c | 192 | static int ok_free(BIO *a) |
0f113f3e MC |
193 | { |
194 | if (a == NULL) | |
195 | return (0); | |
bfb0641f | 196 | EVP_MD_CTX_free(((BIO_OK_CTX *)a->ptr)->md); |
4b45c6e5 | 197 | OPENSSL_clear_free(a->ptr, sizeof(BIO_OK_CTX)); |
0f113f3e MC |
198 | a->ptr = NULL; |
199 | a->init = 0; | |
200 | a->flags = 0; | |
201 | return (1); | |
202 | } | |
203 | ||
6b691a5c | 204 | static int ok_read(BIO *b, char *out, int outl) |
0f113f3e MC |
205 | { |
206 | int ret = 0, i, n; | |
207 | BIO_OK_CTX *ctx; | |
208 | ||
209 | if (out == NULL) | |
210 | return (0); | |
211 | ctx = (BIO_OK_CTX *)b->ptr; | |
212 | ||
213 | if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0)) | |
214 | return (0); | |
215 | ||
216 | while (outl > 0) { | |
217 | ||
218 | /* copy clean bytes to output buffer */ | |
219 | if (ctx->blockout) { | |
220 | i = ctx->buf_len - ctx->buf_off; | |
221 | if (i > outl) | |
222 | i = outl; | |
223 | memcpy(out, &(ctx->buf[ctx->buf_off]), i); | |
224 | ret += i; | |
225 | out += i; | |
226 | outl -= i; | |
227 | ctx->buf_off += i; | |
228 | ||
229 | /* all clean bytes are out */ | |
230 | if (ctx->buf_len == ctx->buf_off) { | |
231 | ctx->buf_off = 0; | |
232 | ||
233 | /* | |
234 | * copy start of the next block into proper place | |
235 | */ | |
236 | if (ctx->buf_len_save - ctx->buf_off_save > 0) { | |
237 | ctx->buf_len = ctx->buf_len_save - ctx->buf_off_save; | |
238 | memmove(ctx->buf, &(ctx->buf[ctx->buf_off_save]), | |
239 | ctx->buf_len); | |
240 | } else { | |
241 | ctx->buf_len = 0; | |
242 | } | |
243 | ctx->blockout = 0; | |
244 | } | |
245 | } | |
246 | ||
247 | /* output buffer full -- cancel */ | |
248 | if (outl == 0) | |
249 | break; | |
250 | ||
251 | /* no clean bytes in buffer -- fill it */ | |
252 | n = IOBS - ctx->buf_len; | |
253 | i = BIO_read(b->next_bio, &(ctx->buf[ctx->buf_len]), n); | |
254 | ||
255 | if (i <= 0) | |
256 | break; /* nothing new */ | |
257 | ||
258 | ctx->buf_len += i; | |
259 | ||
260 | /* no signature yet -- check if we got one */ | |
261 | if (ctx->sigio == 1) { | |
262 | if (!sig_in(b)) { | |
263 | BIO_clear_retry_flags(b); | |
264 | return 0; | |
265 | } | |
266 | } | |
267 | ||
268 | /* signature ok -- check if we got block */ | |
269 | if (ctx->sigio == 0) { | |
270 | if (!block_in(b)) { | |
271 | BIO_clear_retry_flags(b); | |
272 | return 0; | |
273 | } | |
274 | } | |
275 | ||
276 | /* invalid block -- cancel */ | |
277 | if (ctx->cont <= 0) | |
278 | break; | |
279 | ||
280 | } | |
281 | ||
282 | BIO_clear_retry_flags(b); | |
283 | BIO_copy_next_retry(b); | |
284 | return (ret); | |
285 | } | |
1745a3fb | 286 | |
0e1c0612 | 287 | static int ok_write(BIO *b, const char *in, int inl) |
0f113f3e MC |
288 | { |
289 | int ret = 0, n, i; | |
290 | BIO_OK_CTX *ctx; | |
291 | ||
292 | if (inl <= 0) | |
293 | return inl; | |
294 | ||
295 | ctx = (BIO_OK_CTX *)b->ptr; | |
296 | ret = inl; | |
297 | ||
298 | if ((ctx == NULL) || (b->next_bio == NULL) || (b->init == 0)) | |
299 | return (0); | |
300 | ||
301 | if (ctx->sigio && !sig_out(b)) | |
302 | return 0; | |
303 | ||
304 | do { | |
305 | BIO_clear_retry_flags(b); | |
306 | n = ctx->buf_len - ctx->buf_off; | |
307 | while (ctx->blockout && n > 0) { | |
308 | i = BIO_write(b->next_bio, &(ctx->buf[ctx->buf_off]), n); | |
309 | if (i <= 0) { | |
310 | BIO_copy_next_retry(b); | |
311 | if (!BIO_should_retry(b)) | |
312 | ctx->cont = 0; | |
313 | return (i); | |
314 | } | |
315 | ctx->buf_off += i; | |
316 | n -= i; | |
317 | } | |
318 | ||
319 | /* at this point all pending data has been written */ | |
320 | ctx->blockout = 0; | |
321 | if (ctx->buf_len == ctx->buf_off) { | |
322 | ctx->buf_len = OK_BLOCK_BLOCK; | |
323 | ctx->buf_off = 0; | |
324 | } | |
325 | ||
326 | if ((in == NULL) || (inl <= 0)) | |
327 | return (0); | |
328 | ||
329 | n = (inl + ctx->buf_len > OK_BLOCK_SIZE + OK_BLOCK_BLOCK) ? | |
330 | (int)(OK_BLOCK_SIZE + OK_BLOCK_BLOCK - ctx->buf_len) : inl; | |
331 | ||
16f8d4eb | 332 | memcpy(&ctx->buf[ctx->buf_len], in, n); |
0f113f3e MC |
333 | ctx->buf_len += n; |
334 | inl -= n; | |
335 | in += n; | |
336 | ||
337 | if (ctx->buf_len >= OK_BLOCK_SIZE + OK_BLOCK_BLOCK) { | |
338 | if (!block_out(b)) { | |
339 | BIO_clear_retry_flags(b); | |
340 | return 0; | |
341 | } | |
342 | } | |
343 | } while (inl > 0); | |
344 | ||
345 | BIO_clear_retry_flags(b); | |
346 | BIO_copy_next_retry(b); | |
347 | return (ret); | |
348 | } | |
1745a3fb | 349 | |
0e1c0612 | 350 | static long ok_ctrl(BIO *b, int cmd, long num, void *ptr) |
0f113f3e MC |
351 | { |
352 | BIO_OK_CTX *ctx; | |
353 | EVP_MD *md; | |
354 | const EVP_MD **ppmd; | |
355 | long ret = 1; | |
356 | int i; | |
357 | ||
358 | ctx = b->ptr; | |
359 | ||
360 | switch (cmd) { | |
361 | case BIO_CTRL_RESET: | |
362 | ctx->buf_len = 0; | |
363 | ctx->buf_off = 0; | |
364 | ctx->buf_len_save = 0; | |
365 | ctx->buf_off_save = 0; | |
366 | ctx->cont = 1; | |
367 | ctx->finished = 0; | |
368 | ctx->blockout = 0; | |
369 | ctx->sigio = 1; | |
370 | ret = BIO_ctrl(b->next_bio, cmd, num, ptr); | |
371 | break; | |
372 | case BIO_CTRL_EOF: /* More to read */ | |
373 | if (ctx->cont <= 0) | |
374 | ret = 1; | |
375 | else | |
376 | ret = BIO_ctrl(b->next_bio, cmd, num, ptr); | |
377 | break; | |
378 | case BIO_CTRL_PENDING: /* More to read in buffer */ | |
379 | case BIO_CTRL_WPENDING: /* More to read in buffer */ | |
380 | ret = ctx->blockout ? ctx->buf_len - ctx->buf_off : 0; | |
381 | if (ret <= 0) | |
382 | ret = BIO_ctrl(b->next_bio, cmd, num, ptr); | |
383 | break; | |
384 | case BIO_CTRL_FLUSH: | |
385 | /* do a final write */ | |
386 | if (ctx->blockout == 0) | |
387 | if (!block_out(b)) | |
388 | return 0; | |
389 | ||
390 | while (ctx->blockout) { | |
391 | i = ok_write(b, NULL, 0); | |
392 | if (i < 0) { | |
393 | ret = i; | |
394 | break; | |
395 | } | |
396 | } | |
397 | ||
398 | ctx->finished = 1; | |
399 | ctx->buf_off = ctx->buf_len = 0; | |
400 | ctx->cont = (int)ret; | |
401 | ||
402 | /* Finally flush the underlying BIO */ | |
403 | ret = BIO_ctrl(b->next_bio, cmd, num, ptr); | |
404 | break; | |
405 | case BIO_C_DO_STATE_MACHINE: | |
406 | BIO_clear_retry_flags(b); | |
407 | ret = BIO_ctrl(b->next_bio, cmd, num, ptr); | |
408 | BIO_copy_next_retry(b); | |
409 | break; | |
410 | case BIO_CTRL_INFO: | |
411 | ret = (long)ctx->cont; | |
412 | break; | |
413 | case BIO_C_SET_MD: | |
414 | md = ptr; | |
77a01145 | 415 | if (!EVP_DigestInit_ex(ctx->md, md, NULL)) |
0f113f3e MC |
416 | return 0; |
417 | b->init = 1; | |
418 | break; | |
419 | case BIO_C_GET_MD: | |
420 | if (b->init) { | |
421 | ppmd = ptr; | |
77a01145 | 422 | *ppmd = EVP_MD_CTX_md(ctx->md); |
0f113f3e MC |
423 | } else |
424 | ret = 0; | |
425 | break; | |
426 | default: | |
427 | ret = BIO_ctrl(b->next_bio, cmd, num, ptr); | |
428 | break; | |
429 | } | |
430 | return (ret); | |
431 | } | |
1745a3fb | 432 | |
13083215 | 433 | static long ok_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) |
0f113f3e MC |
434 | { |
435 | long ret = 1; | |
436 | ||
437 | if (b->next_bio == NULL) | |
438 | return (0); | |
439 | switch (cmd) { | |
440 | default: | |
441 | ret = BIO_callback_ctrl(b->next_bio, cmd, fp); | |
442 | break; | |
443 | } | |
444 | return (ret); | |
445 | } | |
d3442bc7 | 446 | |
3205db2b | 447 | static void longswap(void *_ptr, size_t len) |
0f113f3e MC |
448 | { |
449 | const union { | |
450 | long one; | |
451 | char little; | |
452 | } is_endian = { | |
453 | 1 | |
454 | }; | |
455 | ||
456 | if (is_endian.little) { | |
457 | size_t i; | |
458 | unsigned char *p = _ptr, c; | |
459 | ||
460 | for (i = 0; i < len; i += 4) { | |
461 | c = p[0], p[0] = p[3], p[3] = c; | |
462 | c = p[1], p[1] = p[2], p[2] = c; | |
463 | } | |
464 | } | |
465 | } | |
3205db2b | 466 | |
0f113f3e MC |
467 | static int sig_out(BIO *b) |
468 | { | |
469 | BIO_OK_CTX *ctx; | |
470 | EVP_MD_CTX *md; | |
77a01145 RL |
471 | const EVP_MD *digest; |
472 | int md_size; | |
473 | void *md_data; | |
0f113f3e MC |
474 | |
475 | ctx = b->ptr; | |
77a01145 RL |
476 | md = ctx->md; |
477 | digest = EVP_MD_CTX_md(md); | |
478 | md_size = EVP_MD_size(digest); | |
479 | md_data = EVP_MD_CTX_md_data(md); | |
0f113f3e | 480 | |
77a01145 | 481 | if (ctx->buf_len + 2 * md_size > OK_BLOCK_SIZE) |
0f113f3e MC |
482 | return 1; |
483 | ||
77a01145 | 484 | if (!EVP_DigestInit_ex(md, digest, NULL)) |
0f113f3e MC |
485 | goto berr; |
486 | /* | |
487 | * FIXME: there's absolutely no guarantee this makes any sense at all, | |
488 | * particularly now EVP_MD_CTX has been restructured. | |
489 | */ | |
77a01145 | 490 | if (RAND_bytes(md_data, md_size) <= 0) |
266483d2 | 491 | goto berr; |
77a01145 RL |
492 | memcpy(&(ctx->buf[ctx->buf_len]), md_data, md_size); |
493 | longswap(&(ctx->buf[ctx->buf_len]), md_size); | |
494 | ctx->buf_len += md_size; | |
0f113f3e MC |
495 | |
496 | if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN))) | |
497 | goto berr; | |
498 | if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL)) | |
499 | goto berr; | |
77a01145 | 500 | ctx->buf_len += md_size; |
0f113f3e MC |
501 | ctx->blockout = 1; |
502 | ctx->sigio = 0; | |
503 | return 1; | |
504 | berr: | |
505 | BIO_clear_retry_flags(b); | |
506 | return 0; | |
507 | } | |
1745a3fb | 508 | |
0f113f3e MC |
509 | static int sig_in(BIO *b) |
510 | { | |
511 | BIO_OK_CTX *ctx; | |
512 | EVP_MD_CTX *md; | |
513 | unsigned char tmp[EVP_MAX_MD_SIZE]; | |
514 | int ret = 0; | |
77a01145 RL |
515 | const EVP_MD *digest; |
516 | int md_size; | |
517 | void *md_data; | |
0f113f3e MC |
518 | |
519 | ctx = b->ptr; | |
77a01145 RL |
520 | md = ctx->md; |
521 | digest = EVP_MD_CTX_md(md); | |
522 | md_size = EVP_MD_size(digest); | |
523 | md_data = EVP_MD_CTX_md_data(md); | |
0f113f3e | 524 | |
77a01145 | 525 | if ((int)(ctx->buf_len - ctx->buf_off) < 2 * md_size) |
0f113f3e MC |
526 | return 1; |
527 | ||
77a01145 | 528 | if (!EVP_DigestInit_ex(md, digest, NULL)) |
0f113f3e | 529 | goto berr; |
77a01145 RL |
530 | memcpy(md_data, &(ctx->buf[ctx->buf_off]), md_size); |
531 | longswap(md_data, md_size); | |
532 | ctx->buf_off += md_size; | |
0f113f3e MC |
533 | |
534 | if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN))) | |
535 | goto berr; | |
536 | if (!EVP_DigestFinal_ex(md, tmp, NULL)) | |
537 | goto berr; | |
77a01145 RL |
538 | ret = memcmp(&(ctx->buf[ctx->buf_off]), tmp, md_size) == 0; |
539 | ctx->buf_off += md_size; | |
0f113f3e MC |
540 | if (ret == 1) { |
541 | ctx->sigio = 0; | |
542 | if (ctx->buf_len != ctx->buf_off) { | |
543 | memmove(ctx->buf, &(ctx->buf[ctx->buf_off]), | |
544 | ctx->buf_len - ctx->buf_off); | |
545 | } | |
546 | ctx->buf_len -= ctx->buf_off; | |
547 | ctx->buf_off = 0; | |
548 | } else { | |
549 | ctx->cont = 0; | |
550 | } | |
551 | return 1; | |
552 | berr: | |
553 | BIO_clear_retry_flags(b); | |
554 | return 0; | |
1745a3fb BL |
555 | } |
556 | ||
0f113f3e MC |
557 | static int block_out(BIO *b) |
558 | { | |
559 | BIO_OK_CTX *ctx; | |
560 | EVP_MD_CTX *md; | |
561 | unsigned long tl; | |
77a01145 RL |
562 | const EVP_MD *digest; |
563 | int md_size; | |
0f113f3e MC |
564 | |
565 | ctx = b->ptr; | |
77a01145 RL |
566 | md = ctx->md; |
567 | digest = EVP_MD_CTX_md(md); | |
568 | md_size = EVP_MD_size(digest); | |
0f113f3e MC |
569 | |
570 | tl = ctx->buf_len - OK_BLOCK_BLOCK; | |
571 | ctx->buf[0] = (unsigned char)(tl >> 24); | |
572 | ctx->buf[1] = (unsigned char)(tl >> 16); | |
573 | ctx->buf[2] = (unsigned char)(tl >> 8); | |
574 | ctx->buf[3] = (unsigned char)(tl); | |
575 | if (!EVP_DigestUpdate(md, | |
576 | (unsigned char *)&(ctx->buf[OK_BLOCK_BLOCK]), tl)) | |
577 | goto berr; | |
578 | if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL)) | |
579 | goto berr; | |
77a01145 | 580 | ctx->buf_len += md_size; |
0f113f3e MC |
581 | ctx->blockout = 1; |
582 | return 1; | |
583 | berr: | |
584 | BIO_clear_retry_flags(b); | |
585 | return 0; | |
586 | } | |
1745a3fb | 587 | |
0f113f3e MC |
588 | static int block_in(BIO *b) |
589 | { | |
590 | BIO_OK_CTX *ctx; | |
591 | EVP_MD_CTX *md; | |
592 | unsigned long tl = 0; | |
593 | unsigned char tmp[EVP_MAX_MD_SIZE]; | |
77a01145 | 594 | int md_size; |
0f113f3e MC |
595 | |
596 | ctx = b->ptr; | |
77a01145 RL |
597 | md = ctx->md; |
598 | md_size = EVP_MD_size(EVP_MD_CTX_md(md)); | |
0f113f3e MC |
599 | |
600 | assert(sizeof(tl) >= OK_BLOCK_BLOCK); /* always true */ | |
601 | tl = ctx->buf[0]; | |
602 | tl <<= 8; | |
603 | tl |= ctx->buf[1]; | |
604 | tl <<= 8; | |
605 | tl |= ctx->buf[2]; | |
606 | tl <<= 8; | |
607 | tl |= ctx->buf[3]; | |
608 | ||
77a01145 | 609 | if (ctx->buf_len < tl + OK_BLOCK_BLOCK + md_size) |
0f113f3e MC |
610 | return 1; |
611 | ||
612 | if (!EVP_DigestUpdate(md, | |
613 | (unsigned char *)&(ctx->buf[OK_BLOCK_BLOCK]), tl)) | |
614 | goto berr; | |
615 | if (!EVP_DigestFinal_ex(md, tmp, NULL)) | |
616 | goto berr; | |
77a01145 | 617 | if (memcmp(&(ctx->buf[tl + OK_BLOCK_BLOCK]), tmp, md_size) == 0) { |
0f113f3e | 618 | /* there might be parts from next block lurking around ! */ |
77a01145 | 619 | ctx->buf_off_save = tl + OK_BLOCK_BLOCK + md_size; |
0f113f3e MC |
620 | ctx->buf_len_save = ctx->buf_len; |
621 | ctx->buf_off = OK_BLOCK_BLOCK; | |
622 | ctx->buf_len = tl + OK_BLOCK_BLOCK; | |
623 | ctx->blockout = 1; | |
624 | } else { | |
625 | ctx->cont = 0; | |
626 | } | |
627 | return 1; | |
628 | berr: | |
629 | BIO_clear_retry_flags(b); | |
630 | return 0; | |
631 | } |