~ubuntu-branches/ubuntu/hardy/openssl/hardy-security

« back to all changes in this revision

Viewing changes to crypto/asn1/tasn_enc.c

  • Committer: Bazaar Package Importer
  • Author(s): Christoph Martin
  • Date: 2004-05-24 17:02:29 UTC
  • Revision ID: james.westby@ubuntu.com-20040524170229-ixlo08bbbly0xied
Tags: upstream-0.9.7d
ImportĀ upstreamĀ versionĀ 0.9.7d

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* tasn_enc.c */
 
2
/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
 
3
 * project 2000.
 
4
 */
 
5
/* ====================================================================
 
6
 * Copyright (c) 2000 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
 
 
60
#include <stddef.h>
 
61
#include <string.h>
 
62
#include <openssl/asn1.h>
 
63
#include <openssl/asn1t.h>
 
64
#include <openssl/objects.h>
 
65
 
 
66
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass);
 
67
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *seq, unsigned char **out, int skcontlen, const ASN1_ITEM *item, int isset);
 
68
 
 
69
/* Encode an ASN1 item, this is compatible with the
 
70
 * standard 'i2d' function. 'out' points to 
 
71
 * a buffer to output the data to, in future we will
 
72
 * have more advanced versions that can output data
 
73
 * a piece at a time and this will simply be a special
 
74
 * case.
 
75
 *
 
76
 * The new i2d has one additional feature. If the output
 
77
 * buffer is NULL (i.e. *out == NULL) then a buffer is
 
78
 * allocated and populated with the encoding.
 
79
 */
 
80
 
 
81
 
 
82
int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
 
83
{
 
84
        if(out && !*out) {
 
85
                unsigned char *p, *buf;
 
86
                int len;
 
87
                len = ASN1_item_ex_i2d(&val, NULL, it, -1, 0);
 
88
                if(len <= 0) return len;
 
89
                buf = OPENSSL_malloc(len);
 
90
                if(!buf) return -1;
 
91
                p = buf;
 
92
                ASN1_item_ex_i2d(&val, &p, it, -1, 0);
 
93
                *out = buf;
 
94
                return len;
 
95
        }
 
96
                
 
97
        return ASN1_item_ex_i2d(&val, out, it, -1, 0);
 
98
}
 
99
 
 
100
/* Encode an item, taking care of IMPLICIT tagging (if any).
 
101
 * This function performs the normal item handling: it can be
 
102
 * used in external types.
 
103
 */
 
104
 
 
105
int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass)
 
106
{
 
107
        const ASN1_TEMPLATE *tt = NULL;
 
108
        unsigned char *p = NULL;
 
109
        int i, seqcontlen, seqlen;
 
110
        ASN1_STRING *strtmp;
 
111
        const ASN1_COMPAT_FUNCS *cf;
 
112
        const ASN1_EXTERN_FUNCS *ef;
 
113
        const ASN1_AUX *aux = it->funcs;
 
114
        ASN1_aux_cb *asn1_cb;
 
115
        if((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) return 0;
 
116
        if(aux && aux->asn1_cb) asn1_cb = aux->asn1_cb;
 
117
        else asn1_cb = 0;
 
118
 
 
119
        switch(it->itype) {
 
120
 
 
121
                case ASN1_ITYPE_PRIMITIVE:
 
122
                if(it->templates)
 
123
                        return ASN1_template_i2d(pval, out, it->templates);
 
124
                return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
 
125
                break;
 
126
 
 
127
                case ASN1_ITYPE_MSTRING:
 
128
                strtmp = (ASN1_STRING *)*pval;
 
129
                return asn1_i2d_ex_primitive(pval, out, it, -1, 0);
 
130
 
 
131
                case ASN1_ITYPE_CHOICE:
 
132
                if(asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it))
 
133
                                return 0;
 
134
                i = asn1_get_choice_selector(pval, it);
 
135
                if((i >= 0) && (i < it->tcount)) {
 
136
                        ASN1_VALUE **pchval;
 
137
                        const ASN1_TEMPLATE *chtt;
 
138
                        chtt = it->templates + i;
 
139
                        pchval = asn1_get_field_ptr(pval, chtt);
 
140
                        return ASN1_template_i2d(pchval, out, chtt);
 
141
                } 
 
142
                /* Fixme: error condition if selector out of range */
 
143
                if(asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it))
 
144
                                return 0;
 
145
                break;
 
146
 
 
147
                case ASN1_ITYPE_EXTERN:
 
148
                /* If new style i2d it does all the work */
 
149
                ef = it->funcs;
 
150
                return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
 
151
 
 
152
                case ASN1_ITYPE_COMPAT:
 
153
                /* old style hackery... */
 
154
                cf = it->funcs;
 
155
                if(out) p = *out;
 
156
                i = cf->asn1_i2d(*pval, out);
 
157
                /* Fixup for IMPLICIT tag: note this messes up for tags > 30,
 
158
                 * but so did the old code. Tags > 30 are very rare anyway.
 
159
                 */
 
160
                if(out && (tag != -1))
 
161
                        *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
 
162
                return i;
 
163
                
 
164
                case ASN1_ITYPE_SEQUENCE:
 
165
                i = asn1_enc_restore(&seqcontlen, out, pval, it);
 
166
                /* An error occurred */
 
167
                if(i < 0) return 0;
 
168
                /* We have a valid cached encoding... */
 
169
                if(i > 0) return seqcontlen;
 
170
                /* Otherwise carry on */
 
171
                seqcontlen = 0;
 
172
                /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
 
173
                if(tag == -1) {
 
174
                        tag = V_ASN1_SEQUENCE;
 
175
                        aclass = V_ASN1_UNIVERSAL;
 
176
                }
 
177
                if(asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it))
 
178
                                return 0;
 
179
                /* First work out sequence content length */
 
180
                for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
 
181
                        const ASN1_TEMPLATE *seqtt;
 
182
                        ASN1_VALUE **pseqval;
 
183
                        seqtt = asn1_do_adb(pval, tt, 1);
 
184
                        if(!seqtt) return 0;
 
185
                        pseqval = asn1_get_field_ptr(pval, seqtt);
 
186
                        /* FIXME: check for errors in enhanced version */
 
187
                        /* FIXME: special handling of indefinite length encoding */
 
188
                        seqcontlen += ASN1_template_i2d(pseqval, NULL, seqtt);
 
189
                }
 
190
                seqlen = ASN1_object_size(1, seqcontlen, tag);
 
191
                if(!out) return seqlen;
 
192
                /* Output SEQUENCE header */
 
193
                ASN1_put_object(out, 1, seqcontlen, tag, aclass);
 
194
                for(i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
 
195
                        const ASN1_TEMPLATE *seqtt;
 
196
                        ASN1_VALUE **pseqval;
 
197
                        seqtt = asn1_do_adb(pval, tt, 1);
 
198
                        if(!seqtt) return 0;
 
199
                        pseqval = asn1_get_field_ptr(pval, seqtt);
 
200
                        /* FIXME: check for errors in enhanced version */
 
201
                        ASN1_template_i2d(pseqval, out, seqtt);
 
202
                }
 
203
                if(asn1_cb  && !asn1_cb(ASN1_OP_I2D_POST, pval, it))
 
204
                                return 0;
 
205
                return seqlen;
 
206
 
 
207
                default:
 
208
                return 0;
 
209
        }
 
210
        return 0;
 
211
}
 
212
 
 
213
int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out, const ASN1_TEMPLATE *tt)
 
214
{
 
215
        int i, ret, flags, aclass;
 
216
        flags = tt->flags;
 
217
        aclass = flags & ASN1_TFLG_TAG_CLASS;
 
218
        if(flags & ASN1_TFLG_SK_MASK) {
 
219
                /* SET OF, SEQUENCE OF */
 
220
                STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
 
221
                int isset, sktag, skaclass;
 
222
                int skcontlen, sklen;
 
223
                ASN1_VALUE *skitem;
 
224
                if(!*pval) return 0;
 
225
                if(flags & ASN1_TFLG_SET_OF) {
 
226
                        isset = 1;
 
227
                        /* 2 means we reorder */
 
228
                        if(flags & ASN1_TFLG_SEQUENCE_OF) isset = 2;
 
229
                } else isset = 0;
 
230
                /* First work out inner tag value */
 
231
                if(flags & ASN1_TFLG_IMPTAG) {
 
232
                        sktag = tt->tag;
 
233
                        skaclass = aclass;
 
234
                } else {
 
235
                        skaclass = V_ASN1_UNIVERSAL;
 
236
                        if(isset) sktag = V_ASN1_SET;
 
237
                        else sktag = V_ASN1_SEQUENCE;
 
238
                }
 
239
                /* Now work out length of items */
 
240
                skcontlen = 0;
 
241
                for(i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
 
242
                        skitem = sk_ASN1_VALUE_value(sk, i);
 
243
                        skcontlen += ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), -1, 0);
 
244
                }
 
245
                sklen = ASN1_object_size(1, skcontlen, sktag);
 
246
                /* If EXPLICIT need length of surrounding tag */
 
247
                if(flags & ASN1_TFLG_EXPTAG)
 
248
                        ret = ASN1_object_size(1, sklen, tt->tag);
 
249
                else ret = sklen;
 
250
 
 
251
                if(!out) return ret;
 
252
 
 
253
                /* Now encode this lot... */
 
254
                /* EXPLICIT tag */
 
255
                if(flags & ASN1_TFLG_EXPTAG)
 
256
                        ASN1_put_object(out, 1, sklen, tt->tag, aclass);
 
257
                /* SET or SEQUENCE and IMPLICIT tag */
 
258
                ASN1_put_object(out, 1, skcontlen, sktag, skaclass);
 
259
                /* And finally the stuff itself */
 
260
                asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), isset);
 
261
 
 
262
                return ret;
 
263
        }
 
264
                        
 
265
        if(flags & ASN1_TFLG_EXPTAG) {
 
266
                /* EXPLICIT tagging */
 
267
                /* Find length of tagged item */
 
268
                i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, 0);
 
269
                if(!i) return 0;
 
270
                /* Find length of EXPLICIT tag */
 
271
                ret = ASN1_object_size(1, i, tt->tag);
 
272
                if(out) {
 
273
                        /* Output tag and item */
 
274
                        ASN1_put_object(out, 1, i, tt->tag, aclass);
 
275
                        ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0);
 
276
                }
 
277
                return ret;
 
278
        }
 
279
        if(flags & ASN1_TFLG_IMPTAG) {
 
280
                /* IMPLICIT tagging */
 
281
                return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), tt->tag, aclass);
 
282
        }
 
283
        /* Nothing special: treat as normal */
 
284
        return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, 0);
 
285
}
 
286
 
 
287
/* Temporary structure used to hold DER encoding of items for SET OF */
 
288
 
 
289
typedef struct {
 
290
        unsigned char *data;
 
291
        int length;
 
292
        ASN1_VALUE *field;
 
293
} DER_ENC;
 
294
 
 
295
static int der_cmp(const void *a, const void *b)
 
296
{
 
297
        const DER_ENC *d1 = a, *d2 = b;
 
298
        int cmplen, i;
 
299
        cmplen = (d1->length < d2->length) ? d1->length : d2->length;
 
300
        i = memcmp(d1->data, d2->data, cmplen);
 
301
        if(i) return i;
 
302
        return d1->length - d2->length;
 
303
}
 
304
 
 
305
/* Output the content octets of SET OF or SEQUENCE OF */
 
306
 
 
307
static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, int skcontlen, const ASN1_ITEM *item, int do_sort)
 
308
{
 
309
        int i;
 
310
        ASN1_VALUE *skitem;
 
311
        unsigned char *tmpdat = NULL, *p = NULL;
 
312
        DER_ENC *derlst = NULL, *tder;
 
313
        if(do_sort) {
 
314
                /* Don't need to sort less than 2 items */
 
315
                if(sk_ASN1_VALUE_num(sk) < 2) do_sort = 0;
 
316
                else {
 
317
                        derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) * sizeof(*derlst));
 
318
                        tmpdat = OPENSSL_malloc(skcontlen);
 
319
                        if(!derlst || !tmpdat) return 0;
 
320
                }
 
321
        }
 
322
        /* If not sorting just output each item */
 
323
        if(!do_sort) {
 
324
                for(i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
 
325
                        skitem = sk_ASN1_VALUE_value(sk, i);
 
326
                        ASN1_item_i2d(skitem, out, item);
 
327
                }
 
328
                return 1;
 
329
        }
 
330
        p = tmpdat;
 
331
        /* Doing sort: build up a list of each member's DER encoding */
 
332
        for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
 
333
                skitem = sk_ASN1_VALUE_value(sk, i);
 
334
                tder->data = p;
 
335
                tder->length = ASN1_item_i2d(skitem, &p, item);
 
336
                tder->field = skitem;
 
337
        }
 
338
        /* Now sort them */
 
339
        qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
 
340
        /* Output sorted DER encoding */        
 
341
        p = *out;
 
342
        for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
 
343
                memcpy(p, tder->data, tder->length);
 
344
                p += tder->length;
 
345
        }
 
346
        *out = p;
 
347
        /* If do_sort is 2 then reorder the STACK */
 
348
        if(do_sort == 2) {
 
349
                for(i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
 
350
                        sk_ASN1_VALUE_set(sk, i, tder->field);
 
351
        }
 
352
        OPENSSL_free(derlst);
 
353
        OPENSSL_free(tmpdat);
 
354
        return 1;
 
355
}
 
356
 
 
357
static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass)
 
358
{
 
359
        int len;
 
360
        int utype;
 
361
        int usetag;
 
362
 
 
363
        utype = it->utype;
 
364
 
 
365
        /* Get length of content octets and maybe find
 
366
         * out the underlying type.
 
367
         */
 
368
 
 
369
        len = asn1_ex_i2c(pval, NULL, &utype, it);
 
370
 
 
371
        /* If SEQUENCE, SET or OTHER then header is
 
372
         * included in pseudo content octets so don't
 
373
         * include tag+length. We need to check here
 
374
         * because the call to asn1_ex_i2c() could change
 
375
         * utype.
 
376
         */
 
377
        if((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
 
378
           (utype == V_ASN1_OTHER))
 
379
                usetag = 0;
 
380
        else usetag = 1;
 
381
 
 
382
        /* -1 means omit type */
 
383
 
 
384
        if(len == -1) return 0;
 
385
 
 
386
        /* If not implicitly tagged get tag from underlying type */
 
387
        if(tag == -1) tag = utype;
 
388
 
 
389
        /* Output tag+length followed by content octets */
 
390
        if(out) {
 
391
                if(usetag) ASN1_put_object(out, 0, len, tag, aclass);
 
392
                asn1_ex_i2c(pval, *out, &utype, it);
 
393
                *out += len;
 
394
        }
 
395
 
 
396
        if(usetag) return ASN1_object_size(0, len, tag);
 
397
        return len;
 
398
}
 
399
 
 
400
/* Produce content octets from a structure */
 
401
 
 
402
int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, const ASN1_ITEM *it)
 
403
{
 
404
        ASN1_BOOLEAN *tbool = NULL;
 
405
        ASN1_STRING *strtmp;
 
406
        ASN1_OBJECT *otmp;
 
407
        int utype;
 
408
        unsigned char *cont, c;
 
409
        int len;
 
410
        const ASN1_PRIMITIVE_FUNCS *pf;
 
411
        pf = it->funcs;
 
412
        if(pf && pf->prim_i2c) return pf->prim_i2c(pval, cout, putype, it);
 
413
 
 
414
        /* Should type be omitted? */
 
415
        if((it->itype != ASN1_ITYPE_PRIMITIVE) || (it->utype != V_ASN1_BOOLEAN)) {
 
416
                if(!*pval) return -1;
 
417
        }
 
418
 
 
419
        if(it->itype == ASN1_ITYPE_MSTRING) {
 
420
                /* If MSTRING type set the underlying type */
 
421
                strtmp = (ASN1_STRING *)*pval;
 
422
                utype = strtmp->type;
 
423
                *putype = utype;
 
424
        } else if(it->utype == V_ASN1_ANY) {
 
425
                /* If ANY set type and pointer to value */
 
426
                ASN1_TYPE *typ;
 
427
                typ = (ASN1_TYPE *)*pval;
 
428
                utype = typ->type;
 
429
                *putype = utype;
 
430
                pval = (ASN1_VALUE **)&typ->value.ptr;
 
431
        } else utype = *putype;
 
432
 
 
433
        switch(utype) {
 
434
                case V_ASN1_OBJECT:
 
435
                otmp = (ASN1_OBJECT *)*pval;
 
436
                cont = otmp->data;
 
437
                len = otmp->length;
 
438
                break;
 
439
 
 
440
                case V_ASN1_NULL:
 
441
                cont = NULL;
 
442
                len = 0;
 
443
                break;
 
444
 
 
445
                case V_ASN1_BOOLEAN:
 
446
                tbool = (ASN1_BOOLEAN *)pval;
 
447
                if(*tbool == -1) return -1;
 
448
                /* Default handling if value == size field then omit */
 
449
                if(*tbool && (it->size > 0)) return -1;
 
450
                if(!*tbool && !it->size) return -1;
 
451
                c = (unsigned char)*tbool;
 
452
                cont = &c;
 
453
                len = 1;
 
454
                break;
 
455
 
 
456
                case V_ASN1_BIT_STRING:
 
457
                return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, cout ? &cout : NULL);
 
458
                break;
 
459
 
 
460
                case V_ASN1_INTEGER:
 
461
                case V_ASN1_NEG_INTEGER:
 
462
                case V_ASN1_ENUMERATED:
 
463
                case V_ASN1_NEG_ENUMERATED:
 
464
                /* These are all have the same content format
 
465
                 * as ASN1_INTEGER
 
466
                 */
 
467
                return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
 
468
                break;
 
469
 
 
470
                case V_ASN1_OCTET_STRING:
 
471
                case V_ASN1_NUMERICSTRING:
 
472
                case V_ASN1_PRINTABLESTRING:
 
473
                case V_ASN1_T61STRING:
 
474
                case V_ASN1_VIDEOTEXSTRING:
 
475
                case V_ASN1_IA5STRING:
 
476
                case V_ASN1_UTCTIME:
 
477
                case V_ASN1_GENERALIZEDTIME:
 
478
                case V_ASN1_GRAPHICSTRING:
 
479
                case V_ASN1_VISIBLESTRING:
 
480
                case V_ASN1_GENERALSTRING:
 
481
                case V_ASN1_UNIVERSALSTRING:
 
482
                case V_ASN1_BMPSTRING:
 
483
                case V_ASN1_UTF8STRING:
 
484
                case V_ASN1_SEQUENCE:
 
485
                case V_ASN1_SET:
 
486
                default:
 
487
                /* All based on ASN1_STRING and handled the same */
 
488
                strtmp = (ASN1_STRING *)*pval;
 
489
                cont = strtmp->data;
 
490
                len = strtmp->length;
 
491
 
 
492
                break;
 
493
 
 
494
        }
 
495
        if(cout && len) memcpy(cout, cont, len);
 
496
        return len;
 
497
}