|
1 /* crypto/evp/bio_ber.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 <errno.h> |
|
61 #include "cryptlib.h" |
|
62 #include <openssl/buffer.h> |
|
63 #include <openssl/evp.h> |
|
64 |
|
65 static int ber_write(BIO *h,char *buf,int num); |
|
66 static int ber_read(BIO *h,char *buf,int size); |
|
67 /*static int ber_puts(BIO *h,char *str); */ |
|
68 /*static int ber_gets(BIO *h,char *str,int size); */ |
|
69 static long ber_ctrl(BIO *h,int cmd,long arg1,char *arg2); |
|
70 static int ber_new(BIO *h); |
|
71 static int ber_free(BIO *data); |
|
72 static long ber_callback_ctrl(BIO *h,int cmd,void *(*fp)()); |
|
73 #define BER_BUF_SIZE (32) |
|
74 |
|
75 /* This is used to hold the state of the BER objects being read. */ |
|
76 typedef struct ber_struct |
|
77 { |
|
78 int tag; |
|
79 int class; |
|
80 long length; |
|
81 int inf; |
|
82 int num_left; |
|
83 int depth; |
|
84 } BER_CTX; |
|
85 |
|
86 typedef struct bio_ber_struct |
|
87 { |
|
88 int tag; |
|
89 int class; |
|
90 long length; |
|
91 int inf; |
|
92 |
|
93 /* most of the following are used when doing non-blocking IO */ |
|
94 /* reading */ |
|
95 long num_left; /* number of bytes still to read/write in block */ |
|
96 int depth; /* used with indefinite encoding. */ |
|
97 int finished; /* No more read data */ |
|
98 |
|
99 /* writting */ |
|
100 char *w_addr; |
|
101 int w_offset; |
|
102 int w_left; |
|
103 |
|
104 int buf_len; |
|
105 int buf_off; |
|
106 unsigned char buf[BER_BUF_SIZE]; |
|
107 } BIO_BER_CTX; |
|
108 |
|
109 static BIO_METHOD methods_ber= |
|
110 { |
|
111 BIO_TYPE_CIPHER,"cipher", |
|
112 ber_write, |
|
113 ber_read, |
|
114 NULL, /* ber_puts, */ |
|
115 NULL, /* ber_gets, */ |
|
116 ber_ctrl, |
|
117 ber_new, |
|
118 ber_free, |
|
119 ber_callback_ctrl, |
|
120 }; |
|
121 |
|
122 BIO_METHOD *BIO_f_ber(void) |
|
123 { |
|
124 return(&methods_ber); |
|
125 } |
|
126 |
|
127 static int ber_new(BIO *bi) |
|
128 { |
|
129 BIO_BER_CTX *ctx; |
|
130 |
|
131 ctx=(BIO_BER_CTX *)OPENSSL_malloc(sizeof(BIO_BER_CTX)); |
|
132 if (ctx == NULL) return(0); |
|
133 |
|
134 memset((char *)ctx,0,sizeof(BIO_BER_CTX)); |
|
135 |
|
136 bi->init=0; |
|
137 bi->ptr=(char *)ctx; |
|
138 bi->flags=0; |
|
139 return(1); |
|
140 } |
|
141 |
|
142 static int ber_free(BIO *a) |
|
143 { |
|
144 BIO_BER_CTX *b; |
|
145 |
|
146 if (a == NULL) return(0); |
|
147 b=(BIO_BER_CTX *)a->ptr; |
|
148 OPENSSL_cleanse(a->ptr,sizeof(BIO_BER_CTX)); |
|
149 OPENSSL_free(a->ptr); |
|
150 a->ptr=NULL; |
|
151 a->init=0; |
|
152 a->flags=0; |
|
153 return(1); |
|
154 } |
|
155 |
|
156 int bio_ber_get_header(BIO *bio, BIO_BER_CTX *ctx) |
|
157 { |
|
158 char buf[64]; |
|
159 int i,j,n; |
|
160 int ret; |
|
161 unsigned char *p; |
|
162 unsigned long length |
|
163 int tag; |
|
164 int class; |
|
165 long max; |
|
166 |
|
167 BIO_clear_retry_flags(b); |
|
168 |
|
169 /* Pack the buffer down if there is a hole at the front */ |
|
170 if (ctx->buf_off != 0) |
|
171 { |
|
172 p=ctx->buf; |
|
173 j=ctx->buf_off; |
|
174 n=ctx->buf_len-j; |
|
175 for (i=0; i<n; i++) |
|
176 { |
|
177 p[0]=p[j]; |
|
178 p++; |
|
179 } |
|
180 ctx->buf_len-j; |
|
181 ctx->buf_off=0; |
|
182 } |
|
183 |
|
184 /* If there is more room, read some more data */ |
|
185 i=BER_BUF_SIZE-ctx->buf_len; |
|
186 if (i) |
|
187 { |
|
188 i=BIO_read(bio->next_bio,&(ctx->buf[ctx->buf_len]),i); |
|
189 if (i <= 0) |
|
190 { |
|
191 BIO_copy_next_retry(b); |
|
192 return(i); |
|
193 } |
|
194 else |
|
195 ctx->buf_len+=i; |
|
196 } |
|
197 |
|
198 max=ctx->buf_len; |
|
199 p=ctx->buf; |
|
200 ret=ASN1_get_object(&p,&length,&tag,&class,max); |
|
201 |
|
202 if (ret & 0x80) |
|
203 { |
|
204 if ((ctx->buf_len < BER_BUF_SIZE) && |
|
205 (ERR_GET_REASON(ERR_peek_error()) == ASN1_R_TOO_LONG)) |
|
206 { |
|
207 ERR_clear_error(); /* clear the error */ |
|
208 BIO_set_retry_read(b); |
|
209 } |
|
210 return(-1); |
|
211 } |
|
212 |
|
213 /* We have no error, we have a header, so make use of it */ |
|
214 |
|
215 if ((ctx->tag >= 0) && (ctx->tag != tag)) |
|
216 { |
|
217 BIOerr(BIO_F_BIO_BER_GET_HEADER,BIO_R_TAG_MISMATCH); |
|
218 sprintf(buf,"tag=%d, got %d",ctx->tag,tag); |
|
219 ERR_add_error_data(1,buf); |
|
220 return(-1); |
|
221 } |
|
222 if (ret & 0x01) |
|
223 if (ret & V_ASN1_CONSTRUCTED) |
|
224 } |
|
225 |
|
226 static int ber_read(BIO *b, char *out, int outl) |
|
227 { |
|
228 int ret=0,i,n; |
|
229 BIO_BER_CTX *ctx; |
|
230 |
|
231 BIO_clear_retry_flags(b); |
|
232 |
|
233 if (out == NULL) return(0); |
|
234 ctx=(BIO_BER_CTX *)b->ptr; |
|
235 |
|
236 if ((ctx == NULL) || (b->next_bio == NULL)) return(0); |
|
237 |
|
238 if (ctx->finished) return(0); |
|
239 |
|
240 again: |
|
241 /* First see if we are half way through reading a block */ |
|
242 if (ctx->num_left > 0) |
|
243 { |
|
244 if (ctx->num_left < outl) |
|
245 n=ctx->num_left; |
|
246 else |
|
247 n=outl; |
|
248 i=BIO_read(b->next_bio,out,n); |
|
249 if (i <= 0) |
|
250 { |
|
251 BIO_copy_next_retry(b); |
|
252 return(i); |
|
253 } |
|
254 ctx->num_left-=i; |
|
255 outl-=i; |
|
256 ret+=i; |
|
257 if (ctx->num_left <= 0) |
|
258 { |
|
259 ctx->depth--; |
|
260 if (ctx->depth <= 0) |
|
261 ctx->finished=1; |
|
262 } |
|
263 if (outl <= 0) |
|
264 return(ret); |
|
265 else |
|
266 goto again; |
|
267 } |
|
268 else /* we need to read another BER header */ |
|
269 { |
|
270 } |
|
271 } |
|
272 |
|
273 static int ber_write(BIO *b, char *in, int inl) |
|
274 { |
|
275 int ret=0,n,i; |
|
276 BIO_ENC_CTX *ctx; |
|
277 |
|
278 ctx=(BIO_ENC_CTX *)b->ptr; |
|
279 ret=inl; |
|
280 |
|
281 BIO_clear_retry_flags(b); |
|
282 n=ctx->buf_len-ctx->buf_off; |
|
283 while (n > 0) |
|
284 { |
|
285 i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n); |
|
286 if (i <= 0) |
|
287 { |
|
288 BIO_copy_next_retry(b); |
|
289 return(i); |
|
290 } |
|
291 ctx->buf_off+=i; |
|
292 n-=i; |
|
293 } |
|
294 /* at this point all pending data has been written */ |
|
295 |
|
296 if ((in == NULL) || (inl <= 0)) return(0); |
|
297 |
|
298 ctx->buf_off=0; |
|
299 while (inl > 0) |
|
300 { |
|
301 n=(inl > ENC_BLOCK_SIZE)?ENC_BLOCK_SIZE:inl; |
|
302 EVP_CipherUpdate(&(ctx->cipher), |
|
303 (unsigned char *)ctx->buf,&ctx->buf_len, |
|
304 (unsigned char *)in,n); |
|
305 inl-=n; |
|
306 in+=n; |
|
307 |
|
308 ctx->buf_off=0; |
|
309 n=ctx->buf_len; |
|
310 while (n > 0) |
|
311 { |
|
312 i=BIO_write(b->next_bio,&(ctx->buf[ctx->buf_off]),n); |
|
313 if (i <= 0) |
|
314 { |
|
315 BIO_copy_next_retry(b); |
|
316 return(i); |
|
317 } |
|
318 n-=i; |
|
319 ctx->buf_off+=i; |
|
320 } |
|
321 ctx->buf_len=0; |
|
322 ctx->buf_off=0; |
|
323 } |
|
324 BIO_copy_next_retry(b); |
|
325 return(ret); |
|
326 } |
|
327 |
|
328 static long ber_ctrl(BIO *b, int cmd, long num, char *ptr) |
|
329 { |
|
330 BIO *dbio; |
|
331 BIO_ENC_CTX *ctx,*dctx; |
|
332 long ret=1; |
|
333 int i; |
|
334 |
|
335 ctx=(BIO_ENC_CTX *)b->ptr; |
|
336 |
|
337 switch (cmd) |
|
338 { |
|
339 case BIO_CTRL_RESET: |
|
340 ctx->ok=1; |
|
341 ctx->finished=0; |
|
342 EVP_CipherInit_ex(&(ctx->cipher),NULL,NULL,NULL,NULL, |
|
343 ctx->cipher.berrypt); |
|
344 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); |
|
345 break; |
|
346 case BIO_CTRL_EOF: /* More to read */ |
|
347 if (ctx->cont <= 0) |
|
348 ret=1; |
|
349 else |
|
350 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); |
|
351 break; |
|
352 case BIO_CTRL_WPENDING: |
|
353 ret=ctx->buf_len-ctx->buf_off; |
|
354 if (ret <= 0) |
|
355 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); |
|
356 break; |
|
357 case BIO_CTRL_PENDING: /* More to read in buffer */ |
|
358 ret=ctx->buf_len-ctx->buf_off; |
|
359 if (ret <= 0) |
|
360 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); |
|
361 break; |
|
362 case BIO_CTRL_FLUSH: |
|
363 /* do a final write */ |
|
364 again: |
|
365 while (ctx->buf_len != ctx->buf_off) |
|
366 { |
|
367 i=ber_write(b,NULL,0); |
|
368 if (i < 0) |
|
369 { |
|
370 ret=i; |
|
371 break; |
|
372 } |
|
373 } |
|
374 |
|
375 if (!ctx->finished) |
|
376 { |
|
377 ctx->finished=1; |
|
378 ctx->buf_off=0; |
|
379 ret=EVP_CipherFinal_ex(&(ctx->cipher), |
|
380 (unsigned char *)ctx->buf, |
|
381 &(ctx->buf_len)); |
|
382 ctx->ok=(int)ret; |
|
383 if (ret <= 0) break; |
|
384 |
|
385 /* push out the bytes */ |
|
386 goto again; |
|
387 } |
|
388 |
|
389 /* Finally flush the underlying BIO */ |
|
390 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); |
|
391 break; |
|
392 case BIO_C_GET_CIPHER_STATUS: |
|
393 ret=(long)ctx->ok; |
|
394 break; |
|
395 case BIO_C_DO_STATE_MACHINE: |
|
396 BIO_clear_retry_flags(b); |
|
397 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); |
|
398 BIO_copy_next_retry(b); |
|
399 break; |
|
400 |
|
401 case BIO_CTRL_DUP: |
|
402 dbio=(BIO *)ptr; |
|
403 dctx=(BIO_ENC_CTX *)dbio->ptr; |
|
404 memcpy(&(dctx->cipher),&(ctx->cipher),sizeof(ctx->cipher)); |
|
405 dbio->init=1; |
|
406 break; |
|
407 default: |
|
408 ret=BIO_ctrl(b->next_bio,cmd,num,ptr); |
|
409 break; |
|
410 } |
|
411 return(ret); |
|
412 } |
|
413 |
|
414 static long ber_callback_ctrl(BIO *b, int cmd, void *(*fp)()) |
|
415 { |
|
416 long ret=1; |
|
417 |
|
418 if (b->next_bio == NULL) return(0); |
|
419 switch (cmd) |
|
420 { |
|
421 default: |
|
422 ret=BIO_callback_ctrl(b->next_bio,cmd,fp); |
|
423 break; |
|
424 } |
|
425 return(ret); |
|
426 } |
|
427 |
|
428 /* |
|
429 void BIO_set_cipher_ctx(b,c) |
|
430 BIO *b; |
|
431 EVP_CIPHER_ctx *c; |
|
432 { |
|
433 if (b == NULL) return; |
|
434 |
|
435 if ((b->callback != NULL) && |
|
436 (b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,0L) <= 0)) |
|
437 return; |
|
438 |
|
439 b->init=1; |
|
440 ctx=(BIO_ENC_CTX *)b->ptr; |
|
441 memcpy(ctx->cipher,c,sizeof(EVP_CIPHER_CTX)); |
|
442 |
|
443 if (b->callback != NULL) |
|
444 b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,1L); |
|
445 } |
|
446 */ |
|
447 |
|
448 void BIO_set_cipher(BIO *b, EVP_CIPHER *c, unsigned char *k, unsigned char *i, |
|
449 int e) |
|
450 { |
|
451 BIO_ENC_CTX *ctx; |
|
452 |
|
453 if (b == NULL) return; |
|
454 |
|
455 if ((b->callback != NULL) && |
|
456 (b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,0L) <= 0)) |
|
457 return; |
|
458 |
|
459 b->init=1; |
|
460 ctx=(BIO_ENC_CTX *)b->ptr; |
|
461 EVP_CipherInit_ex(&(ctx->cipher),c,NULL,k,i,e); |
|
462 |
|
463 if (b->callback != NULL) |
|
464 b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,1L); |
|
465 } |
|
466 |