~ubuntu-branches/ubuntu/lucid/openssl/lucid-proposed

« back to all changes in this revision

Viewing changes to crypto/asn1/bio_asn1.c

  • Committer: Bazaar Package Importer
  • Author(s): Kurt Roeckx
  • Date: 2009-06-13 18:15:46 UTC
  • mto: (11.1.5 squeeze)
  • mto: This revision was merged to the branch mainline in revision 34.
  • Revision ID: james.westby@ubuntu.com-20090613181546-vbfntai3b009dl1u
Tags: upstream-0.9.8k
ImportĀ upstreamĀ versionĀ 0.9.8k

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* bio_asn1.c */
 
2
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
 
3
 * project.
 
4
 */
 
5
/* ====================================================================
 
6
 * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
 
7
 *
 
8
 * Redistribution and use in source and binary forms, with or without
 
9
 * modification, are permitted provided that the following conditions
 
10
 * are met:
 
11
 *
 
12
 * 1. Redistributions of source code must retain the above copyright
 
13
 *    notice, this list of conditions and the following disclaimer. 
 
14
 *
 
15
 * 2. Redistributions in binary form must reproduce the above copyright
 
16
 *    notice, this list of conditions and the following disclaimer in
 
17
 *    the documentation and/or other materials provided with the
 
18
 *    distribution.
 
19
 *
 
20
 * 3. All advertising materials mentioning features or use of this
 
21
 *    software must display the following acknowledgment:
 
22
 *    "This product includes software developed by the OpenSSL Project
 
23
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
 
24
 *
 
25
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
 
26
 *    endorse or promote products derived from this software without
 
27
 *    prior written permission. For written permission, please contact
 
28
 *    licensing@OpenSSL.org.
 
29
 *
 
30
 * 5. Products derived from this software may not be called "OpenSSL"
 
31
 *    nor may "OpenSSL" appear in their names without prior written
 
32
 *    permission of the OpenSSL Project.
 
33
 *
 
34
 * 6. Redistributions of any form whatsoever must retain the following
 
35
 *    acknowledgment:
 
36
 *    "This product includes software developed by the OpenSSL Project
 
37
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
 
38
 *
 
39
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
 
40
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
41
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 
42
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
 
43
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
44
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
45
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
46
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 
48
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
49
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 
50
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 
51
 * ====================================================================
 
52
 *
 
53
 * This product includes cryptographic software written by Eric Young
 
54
 * (eay@cryptsoft.com).  This product includes software written by Tim
 
55
 * Hudson (tjh@cryptsoft.com).
 
56
 *
 
57
 */
 
58
 
 
59
/* Experimental ASN1 BIO. When written through the data is converted
 
60
 * to an ASN1 string type: default is OCTET STRING. Additional functions
 
61
 * can be provided to add prefix and suffix data.
 
62
 */
 
63
 
 
64
#include <string.h>
 
65
#include <openssl/bio.h>
 
66
#include <openssl/asn1.h>
 
67
 
 
68
/* Must be large enough for biggest tag+length */
 
69
#define DEFAULT_ASN1_BUF_SIZE 20
 
70
 
 
71
typedef enum 
 
72
        {
 
73
        ASN1_STATE_START,
 
74
        ASN1_STATE_PRE_COPY,
 
75
        ASN1_STATE_HEADER,
 
76
        ASN1_STATE_HEADER_COPY,
 
77
        ASN1_STATE_DATA_COPY,
 
78
        ASN1_STATE_POST_COPY,
 
79
        ASN1_STATE_DONE
 
80
        } asn1_bio_state_t;
 
81
 
 
82
typedef struct BIO_ASN1_EX_FUNCS_st
 
83
        {
 
84
        asn1_ps_func    *ex_func;
 
85
        asn1_ps_func    *ex_free_func;
 
86
        } BIO_ASN1_EX_FUNCS;
 
87
 
 
88
typedef struct BIO_ASN1_BUF_CTX_t
 
89
        {
 
90
        /* Internal state */
 
91
        asn1_bio_state_t state;
 
92
        /* Internal buffer */
 
93
        unsigned char *buf;
 
94
        /* Size of buffer */
 
95
        int bufsize;
 
96
        /* Current position in buffer */
 
97
        int bufpos;
 
98
        /* Current buffer length */
 
99
        int buflen;
 
100
        /* Amount of data to copy */
 
101
        int copylen;
 
102
        /* Class and tag to use */
 
103
        int asn1_class, asn1_tag;
 
104
        asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
 
105
        /* Extra buffer for prefix and suffix data */
 
106
        unsigned char *ex_buf;
 
107
        int ex_len;
 
108
        int ex_pos;
 
109
        void *ex_arg;
 
110
        } BIO_ASN1_BUF_CTX;
 
111
 
 
112
 
 
113
static int asn1_bio_write(BIO *h, const char *buf,int num);
 
114
static int asn1_bio_read(BIO *h, char *buf, int size);
 
115
static int asn1_bio_puts(BIO *h, const char *str);
 
116
static int asn1_bio_gets(BIO *h, char *str, int size);
 
117
static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
 
118
static int asn1_bio_new(BIO *h);
 
119
static int asn1_bio_free(BIO *data);
 
120
static long asn1_bio_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
 
121
 
 
122
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
 
123
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
 
124
                                asn1_ps_func *cleanup, asn1_bio_state_t next);
 
125
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
 
126
                                asn1_ps_func *setup, 
 
127
                                asn1_bio_state_t ex_state,
 
128
                                asn1_bio_state_t other_state);
 
129
 
 
130
static BIO_METHOD methods_asn1=
 
131
        {
 
132
        BIO_TYPE_ASN1,
 
133
        "asn1",
 
134
        asn1_bio_write,
 
135
        asn1_bio_read,
 
136
        asn1_bio_puts,
 
137
        asn1_bio_gets,
 
138
        asn1_bio_ctrl,
 
139
        asn1_bio_new,
 
140
        asn1_bio_free,
 
141
        asn1_bio_callback_ctrl,
 
142
        };
 
143
 
 
144
BIO_METHOD *BIO_f_asn1(void)
 
145
        {
 
146
        return(&methods_asn1);
 
147
        }
 
148
 
 
149
 
 
150
static int asn1_bio_new(BIO *b)
 
151
        {
 
152
        BIO_ASN1_BUF_CTX *ctx;
 
153
        ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
 
154
        if (!ctx)
 
155
                return 0;
 
156
        if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE))
 
157
                return 0;
 
158
        b->init = 1;
 
159
        b->ptr = (char *)ctx;
 
160
        b->flags = 0;
 
161
        return 1;
 
162
        }
 
163
 
 
164
static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
 
165
        {
 
166
        ctx->buf = OPENSSL_malloc(size);
 
167
        if (!ctx->buf)
 
168
                return 0;
 
169
        ctx->bufsize = size;
 
170
        ctx->bufpos = 0;
 
171
        ctx->buflen = 0;
 
172
        ctx->copylen = 0;
 
173
        ctx->asn1_class = V_ASN1_UNIVERSAL;
 
174
        ctx->asn1_tag = V_ASN1_OCTET_STRING;
 
175
        ctx->ex_buf = 0;
 
176
        ctx->ex_pos = 0;
 
177
        ctx->ex_len = 0;
 
178
        ctx->state = ASN1_STATE_START;
 
179
        return 1;
 
180
        }
 
181
 
 
182
static int asn1_bio_free(BIO *b)
 
183
        {
 
184
        BIO_ASN1_BUF_CTX *ctx;
 
185
        ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
 
186
        if (ctx == NULL)
 
187
                return 0;
 
188
        if (ctx->buf)
 
189
                OPENSSL_free(ctx->buf);
 
190
        OPENSSL_free(ctx);
 
191
        b->init = 0;
 
192
        b->ptr = NULL;
 
193
        b->flags = 0;
 
194
        return 1;
 
195
        }
 
196
 
 
197
static int asn1_bio_write(BIO *b, const char *in , int inl)
 
198
        {
 
199
        BIO_ASN1_BUF_CTX *ctx;
 
200
        int wrmax, wrlen, ret;
 
201
        unsigned char *p;
 
202
        if (!in || (inl < 0) || (b->next_bio == NULL))
 
203
                return 0;
 
204
        ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
 
205
        if (ctx == NULL)
 
206
                return 0;
 
207
 
 
208
        wrlen = 0;
 
209
        ret = -1;
 
210
 
 
211
        for(;;)
 
212
                {
 
213
                switch (ctx->state)
 
214
                        {
 
215
 
 
216
                        /* Setup prefix data, call it */
 
217
                        case ASN1_STATE_START:
 
218
                        if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
 
219
                                ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
 
220
                                return 0;
 
221
                        break;
 
222
 
 
223
                        /* Copy any pre data first */
 
224
                        case ASN1_STATE_PRE_COPY:
 
225
 
 
226
                        ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
 
227
                                                        ASN1_STATE_HEADER);
 
228
 
 
229
                        if (ret <= 0)
 
230
                                goto done;
 
231
 
 
232
                        break;
 
233
 
 
234
                        case ASN1_STATE_HEADER:
 
235
                        ctx->buflen =
 
236
                                ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
 
237
                        OPENSSL_assert(ctx->buflen <= ctx->bufsize);
 
238
                        p = ctx->buf;
 
239
                        ASN1_put_object(&p, 0, inl,
 
240
                                        ctx->asn1_tag, ctx->asn1_class);
 
241
                        ctx->copylen = inl;
 
242
                        ctx->state = ASN1_STATE_HEADER_COPY;
 
243
 
 
244
                        break;
 
245
 
 
246
                        case ASN1_STATE_HEADER_COPY:    
 
247
                        ret = BIO_write(b->next_bio,
 
248
                                        ctx->buf + ctx->bufpos, ctx->buflen);
 
249
                        if (ret <= 0)
 
250
                                goto done;
 
251
 
 
252
                        ctx->buflen -= ret;
 
253
                        if (ctx->buflen)
 
254
                                ctx->bufpos += ret;
 
255
                        else
 
256
                                {
 
257
                                ctx->bufpos = 0;
 
258
                                ctx->state = ASN1_STATE_DATA_COPY;
 
259
                                }
 
260
 
 
261
                        break;
 
262
 
 
263
                        case ASN1_STATE_DATA_COPY:
 
264
 
 
265
                        if (inl > ctx->copylen)
 
266
                                wrmax = ctx->copylen;
 
267
                        else
 
268
                                wrmax = inl;
 
269
                        ret = BIO_write(b->next_bio, in, wrmax);
 
270
                        if (ret <= 0)
 
271
                                break;
 
272
                        wrlen += ret;
 
273
                        ctx->copylen -= ret;
 
274
                        in += ret;
 
275
                        inl -= ret;
 
276
 
 
277
                        if (ctx->copylen == 0)
 
278
                                ctx->state = ASN1_STATE_HEADER;
 
279
 
 
280
                        if (inl == 0)
 
281
                                goto done;
 
282
 
 
283
                        break;
 
284
 
 
285
                        default:
 
286
                        BIO_clear_retry_flags(b);
 
287
                        return 0;
 
288
 
 
289
                        }
 
290
 
 
291
                }
 
292
 
 
293
        done:
 
294
        BIO_clear_retry_flags(b);
 
295
        BIO_copy_next_retry(b);
 
296
 
 
297
        return (wrlen > 0) ? wrlen : ret;
 
298
 
 
299
        }
 
300
 
 
301
static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
 
302
                                asn1_ps_func *cleanup, asn1_bio_state_t next)
 
303
        {
 
304
        int ret;
 
305
        if (ctx->ex_len <= 0)
 
306
                return 1;
 
307
        for(;;)
 
308
                {
 
309
                ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos,
 
310
                                                                ctx->ex_len);
 
311
                if (ret <= 0)
 
312
                        break;
 
313
                ctx->ex_len -= ret;
 
314
                if (ctx->ex_len > 0)
 
315
                        ctx->ex_pos += ret;
 
316
                else
 
317
                        {
 
318
                        if(cleanup)
 
319
                                cleanup(b, &ctx->ex_buf, &ctx->ex_len,
 
320
                                                                &ctx->ex_arg);
 
321
                        ctx->state = next;
 
322
                        ctx->ex_pos = 0;
 
323
                        break;
 
324
                        }
 
325
                }
 
326
        return ret;
 
327
        }
 
328
 
 
329
static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
 
330
                                asn1_ps_func *setup, 
 
331
                                asn1_bio_state_t ex_state,
 
332
                                asn1_bio_state_t other_state)
 
333
        {
 
334
        if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg))
 
335
                {
 
336
                BIO_clear_retry_flags(b);
 
337
                return 0;
 
338
                }
 
339
        if (ctx->ex_len > 0)
 
340
                ctx->state = ex_state;
 
341
        else
 
342
                ctx->state = other_state;
 
343
        return 1;
 
344
        }
 
345
 
 
346
static int asn1_bio_read(BIO *b, char *in , int inl)
 
347
        {
 
348
        if (!b->next_bio)
 
349
                return 0;
 
350
        return BIO_read(b->next_bio, in , inl);
 
351
        }
 
352
 
 
353
static int asn1_bio_puts(BIO *b, const char *str)
 
354
        {
 
355
        return asn1_bio_write(b, str, strlen(str));
 
356
        }
 
357
 
 
358
static int asn1_bio_gets(BIO *b, char *str, int size)
 
359
        {
 
360
        if (!b->next_bio)
 
361
                return 0;
 
362
        return BIO_gets(b->next_bio, str , size);
 
363
        }
 
364
 
 
365
static long asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
 
366
        {
 
367
        if (b->next_bio == NULL) return(0);
 
368
        return BIO_callback_ctrl(b->next_bio,cmd,fp);
 
369
        }
 
370
 
 
371
static long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
 
372
        {
 
373
        BIO_ASN1_BUF_CTX *ctx;
 
374
        BIO_ASN1_EX_FUNCS *ex_func;
 
375
        long ret = 1;
 
376
        ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
 
377
        if (ctx == NULL)
 
378
                return 0;
 
379
        switch(cmd)
 
380
                {
 
381
 
 
382
                case BIO_C_SET_PREFIX:
 
383
                ex_func = arg2;
 
384
                ctx->prefix  = ex_func->ex_func;
 
385
                ctx->prefix_free  = ex_func->ex_free_func;
 
386
                break;
 
387
 
 
388
                case BIO_C_GET_PREFIX:
 
389
                ex_func = arg2;
 
390
                ex_func->ex_func = ctx->prefix;
 
391
                ex_func->ex_free_func = ctx->prefix_free;
 
392
                break;
 
393
 
 
394
                case BIO_C_SET_SUFFIX:
 
395
                ex_func = arg2;
 
396
                ctx->suffix  = ex_func->ex_func;
 
397
                ctx->suffix_free  = ex_func->ex_free_func;
 
398
                break;
 
399
 
 
400
                case BIO_C_GET_SUFFIX:
 
401
                ex_func = arg2;
 
402
                ex_func->ex_func = ctx->suffix;
 
403
                ex_func->ex_free_func = ctx->suffix_free;
 
404
                break;
 
405
 
 
406
                case BIO_C_SET_EX_ARG:
 
407
                ctx->ex_arg = arg2;
 
408
                break;
 
409
 
 
410
                case BIO_C_GET_EX_ARG:
 
411
                *(void **)arg2 = ctx->ex_arg;
 
412
                break;
 
413
 
 
414
                case BIO_CTRL_FLUSH:
 
415
                if (!b->next_bio)
 
416
                        return 0;
 
417
 
 
418
                /* Call post function if possible */
 
419
                if (ctx->state == ASN1_STATE_HEADER)
 
420
                        {
 
421
                        if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
 
422
                                ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
 
423
                                return 0;
 
424
                        }
 
425
 
 
426
                if (ctx->state == ASN1_STATE_POST_COPY)
 
427
                        {
 
428
                        ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
 
429
                                                        ASN1_STATE_DONE);
 
430
                        if (ret <= 0)
 
431
                                return ret;
 
432
                        }
 
433
 
 
434
                if (ctx->state == ASN1_STATE_DONE)
 
435
                        return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
 
436
                else
 
437
                        {
 
438
                        BIO_clear_retry_flags(b);
 
439
                        return 0;
 
440
                        }
 
441
                break;
 
442
 
 
443
 
 
444
                default:
 
445
                if (!b->next_bio)
 
446
                        return 0;
 
447
                return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
 
448
 
 
449
                }
 
450
 
 
451
        return ret;
 
452
        }
 
453
 
 
454
static int asn1_bio_set_ex(BIO *b, int cmd,
 
455
                asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
 
456
        {
 
457
        BIO_ASN1_EX_FUNCS extmp;
 
458
        extmp.ex_func = ex_func;
 
459
        extmp.ex_free_func = ex_free_func;
 
460
        return BIO_ctrl(b, cmd, 0, &extmp);
 
461
        }
 
462
 
 
463
static int asn1_bio_get_ex(BIO *b, int cmd,
 
464
                asn1_ps_func **ex_func, asn1_ps_func **ex_free_func)
 
465
        {
 
466
        BIO_ASN1_EX_FUNCS extmp;
 
467
        int ret;
 
468
        ret = BIO_ctrl(b, cmd, 0, &extmp);
 
469
        if (ret > 0)
 
470
                {
 
471
                *ex_func = extmp.ex_func;
 
472
                *ex_free_func = extmp.ex_free_func;
 
473
                }
 
474
        return ret;
 
475
        }
 
476
 
 
477
int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free)
 
478
        {
 
479
        return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
 
480
        }
 
481
 
 
482
int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, asn1_ps_func **pprefix_free)
 
483
        {
 
484
        return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
 
485
        }
 
486
 
 
487
int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free)
 
488
        {
 
489
        return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
 
490
        }
 
491
 
 
492
int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, asn1_ps_func **psuffix_free)
 
493
        {
 
494
        return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
 
495
        }