Line data Source code
1 : /* a_strex.c */
2 : /*
3 : * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4 : * 2000.
5 : */
6 : /* ====================================================================
7 : * Copyright (c) 2000 The OpenSSL Project. All rights reserved.
8 : *
9 : * Redistribution and use in source and binary forms, with or without
10 : * modification, are permitted provided that the following conditions
11 : * are met:
12 : *
13 : * 1. Redistributions of source code must retain the above copyright
14 : * notice, this list of conditions and the following disclaimer.
15 : *
16 : * 2. Redistributions in binary form must reproduce the above copyright
17 : * notice, this list of conditions and the following disclaimer in
18 : * the documentation and/or other materials provided with the
19 : * distribution.
20 : *
21 : * 3. All advertising materials mentioning features or use of this
22 : * software must display the following acknowledgment:
23 : * "This product includes software developed by the OpenSSL Project
24 : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25 : *
26 : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 : * endorse or promote products derived from this software without
28 : * prior written permission. For written permission, please contact
29 : * licensing@OpenSSL.org.
30 : *
31 : * 5. Products derived from this software may not be called "OpenSSL"
32 : * nor may "OpenSSL" appear in their names without prior written
33 : * permission of the OpenSSL Project.
34 : *
35 : * 6. Redistributions of any form whatsoever must retain the following
36 : * acknowledgment:
37 : * "This product includes software developed by the OpenSSL Project
38 : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39 : *
40 : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 : * OF THE POSSIBILITY OF SUCH DAMAGE.
52 : * ====================================================================
53 : *
54 : * This product includes cryptographic software written by Eric Young
55 : * (eay@cryptsoft.com). This product includes software written by Tim
56 : * Hudson (tjh@cryptsoft.com).
57 : *
58 : */
59 :
60 : #include <stdio.h>
61 : #include <string.h>
62 : #include "cryptlib.h"
63 : #include <openssl/crypto.h>
64 : #include <openssl/x509.h>
65 : #include <openssl/asn1.h>
66 :
67 : #include "charmap.h"
68 :
69 : /*
70 : * ASN1_STRING_print_ex() and X509_NAME_print_ex(). Enhanced string and name
71 : * printing routines handling multibyte characters, RFC2253 and a host of
72 : * other options.
73 : */
74 :
75 : #define CHARTYPE_BS_ESC (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253)
76 :
77 : #define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \
78 : ASN1_STRFLGS_ESC_QUOTE | \
79 : ASN1_STRFLGS_ESC_CTRL | \
80 : ASN1_STRFLGS_ESC_MSB)
81 :
82 : /*
83 : * Three IO functions for sending data to memory, a BIO and and a FILE
84 : * pointer.
85 : */
86 : #if 0 /* never used */
87 : static int send_mem_chars(void *arg, const void *buf, int len)
88 : {
89 : unsigned char **out = arg;
90 : if (!out)
91 : return 1;
92 : memcpy(*out, buf, len);
93 : *out += len;
94 : return 1;
95 : }
96 : #endif
97 :
98 0 : static int send_bio_chars(void *arg, const void *buf, int len)
99 : {
100 0 : if (!arg)
101 : return 1;
102 0 : if (BIO_write(arg, buf, len) != len)
103 : return 0;
104 0 : return 1;
105 : }
106 :
107 0 : static int send_fp_chars(void *arg, const void *buf, int len)
108 : {
109 0 : if (!arg)
110 : return 1;
111 0 : if (fwrite(buf, 1, len, arg) != (unsigned int)len)
112 : return 0;
113 0 : return 1;
114 : }
115 :
116 : typedef int char_io (void *arg, const void *buf, int len);
117 :
118 : /*
119 : * This function handles display of strings, one character at a time. It is
120 : * passed an unsigned long for each character because it could come from 2 or
121 : * even 4 byte forms.
122 : */
123 :
124 0 : static int do_esc_char(unsigned long c, unsigned char flags, char *do_quotes,
125 : char_io *io_ch, void *arg)
126 : {
127 : unsigned char chflgs, chtmp;
128 : char tmphex[HEX_SIZE(long) + 3];
129 :
130 0 : if (c > 0xffffffffL)
131 : return -1;
132 0 : if (c > 0xffff) {
133 0 : BIO_snprintf(tmphex, sizeof tmphex, "\\W%08lX", c);
134 0 : if (!io_ch(arg, tmphex, 10))
135 : return -1;
136 0 : return 10;
137 : }
138 0 : if (c > 0xff) {
139 0 : BIO_snprintf(tmphex, sizeof tmphex, "\\U%04lX", c);
140 0 : if (!io_ch(arg, tmphex, 6))
141 : return -1;
142 0 : return 6;
143 : }
144 0 : chtmp = (unsigned char)c;
145 0 : if (chtmp > 0x7f)
146 0 : chflgs = flags & ASN1_STRFLGS_ESC_MSB;
147 : else
148 0 : chflgs = char_type[chtmp] & flags;
149 0 : if (chflgs & CHARTYPE_BS_ESC) {
150 : /* If we don't escape with quotes, signal we need quotes */
151 0 : if (chflgs & ASN1_STRFLGS_ESC_QUOTE) {
152 0 : if (do_quotes)
153 0 : *do_quotes = 1;
154 0 : if (!io_ch(arg, &chtmp, 1))
155 : return -1;
156 0 : return 1;
157 : }
158 0 : if (!io_ch(arg, "\\", 1))
159 : return -1;
160 0 : if (!io_ch(arg, &chtmp, 1))
161 : return -1;
162 0 : return 2;
163 : }
164 0 : if (chflgs & (ASN1_STRFLGS_ESC_CTRL | ASN1_STRFLGS_ESC_MSB)) {
165 0 : BIO_snprintf(tmphex, 11, "\\%02X", chtmp);
166 0 : if (!io_ch(arg, tmphex, 3))
167 : return -1;
168 0 : return 3;
169 : }
170 : /*
171 : * If we get this far and do any escaping at all must escape the escape
172 : * character itself: backslash.
173 : */
174 0 : if (chtmp == '\\' && flags & ESC_FLAGS) {
175 0 : if (!io_ch(arg, "\\\\", 2))
176 : return -1;
177 0 : return 2;
178 : }
179 0 : if (!io_ch(arg, &chtmp, 1))
180 : return -1;
181 0 : return 1;
182 : }
183 :
184 : #define BUF_TYPE_WIDTH_MASK 0x7
185 : #define BUF_TYPE_CONVUTF8 0x8
186 :
187 : /*
188 : * This function sends each character in a buffer to do_esc_char(). It
189 : * interprets the content formats and converts to or from UTF8 as
190 : * appropriate.
191 : */
192 :
193 0 : static int do_buf(unsigned char *buf, int buflen,
194 : int type, unsigned char flags, char *quotes, char_io *io_ch,
195 : void *arg)
196 : {
197 : int i, outlen, len;
198 : unsigned char orflags, *p, *q;
199 : unsigned long c;
200 : p = buf;
201 0 : q = buf + buflen;
202 : outlen = 0;
203 0 : while (p != q) {
204 0 : if (p == buf && flags & ASN1_STRFLGS_ESC_2253)
205 : orflags = CHARTYPE_FIRST_ESC_2253;
206 : else
207 : orflags = 0;
208 0 : switch (type & BUF_TYPE_WIDTH_MASK) {
209 : case 4:
210 0 : c = ((unsigned long)*p++) << 24;
211 0 : c |= ((unsigned long)*p++) << 16;
212 0 : c |= ((unsigned long)*p++) << 8;
213 0 : c |= *p++;
214 0 : break;
215 :
216 : case 2:
217 0 : c = ((unsigned long)*p++) << 8;
218 0 : c |= *p++;
219 0 : break;
220 :
221 : case 1:
222 0 : c = *p++;
223 0 : break;
224 :
225 : case 0:
226 0 : i = UTF8_getc(p, buflen, &c);
227 0 : if (i < 0)
228 : return -1; /* Invalid UTF8String */
229 0 : p += i;
230 0 : break;
231 : default:
232 : return -1; /* invalid width */
233 : }
234 0 : if (p == q && flags & ASN1_STRFLGS_ESC_2253)
235 : orflags = CHARTYPE_LAST_ESC_2253;
236 0 : if (type & BUF_TYPE_CONVUTF8) {
237 : unsigned char utfbuf[6];
238 : int utflen;
239 0 : utflen = UTF8_putc(utfbuf, sizeof utfbuf, c);
240 0 : for (i = 0; i < utflen; i++) {
241 : /*
242 : * We don't need to worry about setting orflags correctly
243 : * because if utflen==1 its value will be correct anyway
244 : * otherwise each character will be > 0x7f and so the
245 : * character will never be escaped on first and last.
246 : */
247 0 : len =
248 0 : do_esc_char(utfbuf[i], (unsigned char)(flags | orflags),
249 : quotes, io_ch, arg);
250 0 : if (len < 0)
251 0 : return -1;
252 0 : outlen += len;
253 : }
254 : } else {
255 0 : len =
256 0 : do_esc_char(c, (unsigned char)(flags | orflags), quotes,
257 : io_ch, arg);
258 0 : if (len < 0)
259 : return -1;
260 0 : outlen += len;
261 : }
262 : }
263 : return outlen;
264 : }
265 :
266 : /* This function hex dumps a buffer of characters */
267 :
268 0 : static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf,
269 : int buflen)
270 : {
271 : static const char hexdig[] = "0123456789ABCDEF";
272 : unsigned char *p, *q;
273 : char hextmp[2];
274 0 : if (arg) {
275 : p = buf;
276 0 : q = buf + buflen;
277 0 : while (p != q) {
278 0 : hextmp[0] = hexdig[*p >> 4];
279 0 : hextmp[1] = hexdig[*p & 0xf];
280 0 : if (!io_ch(arg, hextmp, 2))
281 : return -1;
282 0 : p++;
283 : }
284 : }
285 0 : return buflen << 1;
286 : }
287 :
288 : /*
289 : * "dump" a string. This is done when the type is unknown, or the flags
290 : * request it. We can either dump the content octets or the entire DER
291 : * encoding. This uses the RFC2253 #01234 format.
292 : */
293 :
294 0 : static int do_dump(unsigned long lflags, char_io *io_ch, void *arg,
295 : ASN1_STRING *str)
296 : {
297 : /*
298 : * Placing the ASN1_STRING in a temp ASN1_TYPE allows the DER encoding to
299 : * readily obtained
300 : */
301 : ASN1_TYPE t;
302 : unsigned char *der_buf, *p;
303 : int outlen, der_len;
304 :
305 0 : if (!io_ch(arg, "#", 1))
306 : return -1;
307 : /* If we don't dump DER encoding just dump content octets */
308 0 : if (!(lflags & ASN1_STRFLGS_DUMP_DER)) {
309 0 : outlen = do_hex_dump(io_ch, arg, str->data, str->length);
310 0 : if (outlen < 0)
311 : return -1;
312 0 : return outlen + 1;
313 : }
314 0 : t.type = str->type;
315 0 : t.value.ptr = (char *)str;
316 0 : der_len = i2d_ASN1_TYPE(&t, NULL);
317 0 : der_buf = OPENSSL_malloc(der_len);
318 0 : if (!der_buf)
319 : return -1;
320 0 : p = der_buf;
321 0 : i2d_ASN1_TYPE(&t, &p);
322 0 : outlen = do_hex_dump(io_ch, arg, der_buf, der_len);
323 0 : OPENSSL_free(der_buf);
324 0 : if (outlen < 0)
325 : return -1;
326 0 : return outlen + 1;
327 : }
328 :
329 : /*
330 : * Lookup table to convert tags to character widths, 0 = UTF8 encoded, -1 is
331 : * used for non string types otherwise it is the number of bytes per
332 : * character
333 : */
334 :
335 : static const signed char tag2nbyte[] = {
336 : -1, -1, -1, -1, -1, /* 0-4 */
337 : -1, -1, -1, -1, -1, /* 5-9 */
338 : -1, -1, 0, -1, /* 10-13 */
339 : -1, -1, -1, -1, /* 15-17 */
340 : -1, 1, 1, /* 18-20 */
341 : -1, 1, 1, 1, /* 21-24 */
342 : -1, 1, -1, /* 25-27 */
343 : 4, -1, 2 /* 28-30 */
344 : };
345 :
346 : /*
347 : * This is the main function, print out an ASN1_STRING taking note of various
348 : * escape and display options. Returns number of characters written or -1 if
349 : * an error occurred.
350 : */
351 :
352 0 : static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags,
353 : ASN1_STRING *str)
354 : {
355 : int outlen, len;
356 : int type;
357 : char quotes;
358 : unsigned char flags;
359 0 : quotes = 0;
360 : /* Keep a copy of escape flags */
361 0 : flags = (unsigned char)(lflags & ESC_FLAGS);
362 :
363 0 : type = str->type;
364 :
365 : outlen = 0;
366 :
367 0 : if (lflags & ASN1_STRFLGS_SHOW_TYPE) {
368 : const char *tagname;
369 0 : tagname = ASN1_tag2str(type);
370 0 : outlen += strlen(tagname);
371 0 : if (!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1))
372 : return -1;
373 0 : outlen++;
374 : }
375 :
376 : /* Decide what to do with type, either dump content or display it */
377 :
378 : /* Dump everything */
379 0 : if (lflags & ASN1_STRFLGS_DUMP_ALL)
380 : type = -1;
381 : /* Ignore the string type */
382 0 : else if (lflags & ASN1_STRFLGS_IGNORE_TYPE)
383 : type = 1;
384 : else {
385 : /* Else determine width based on type */
386 0 : if ((type > 0) && (type < 31))
387 0 : type = tag2nbyte[type];
388 : else
389 : type = -1;
390 0 : if ((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN))
391 : type = 1;
392 : }
393 :
394 0 : if (type == -1) {
395 0 : len = do_dump(lflags, io_ch, arg, str);
396 0 : if (len < 0)
397 : return -1;
398 0 : outlen += len;
399 0 : return outlen;
400 : }
401 :
402 0 : if (lflags & ASN1_STRFLGS_UTF8_CONVERT) {
403 : /*
404 : * Note: if string is UTF8 and we want to convert to UTF8 then we
405 : * just interpret it as 1 byte per character to avoid converting
406 : * twice.
407 : */
408 0 : if (!type)
409 : type = 1;
410 : else
411 0 : type |= BUF_TYPE_CONVUTF8;
412 : }
413 :
414 0 : len = do_buf(str->data, str->length, type, flags, "es, io_ch, NULL);
415 0 : if (len < 0)
416 : return -1;
417 0 : outlen += len;
418 0 : if (quotes)
419 0 : outlen += 2;
420 0 : if (!arg)
421 : return outlen;
422 0 : if (quotes && !io_ch(arg, "\"", 1))
423 : return -1;
424 0 : if (do_buf(str->data, str->length, type, flags, NULL, io_ch, arg) < 0)
425 : return -1;
426 0 : if (quotes && !io_ch(arg, "\"", 1))
427 : return -1;
428 0 : return outlen;
429 : }
430 :
431 : /* Used for line indenting: print 'indent' spaces */
432 :
433 : static int do_indent(char_io *io_ch, void *arg, int indent)
434 : {
435 : int i;
436 0 : for (i = 0; i < indent; i++)
437 0 : if (!io_ch(arg, " ", 1))
438 : return 0;
439 : return 1;
440 : }
441 :
442 : #define FN_WIDTH_LN 25
443 : #define FN_WIDTH_SN 10
444 :
445 0 : static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n,
446 : int indent, unsigned long flags)
447 : {
448 : int i, prev = -1, orflags, cnt;
449 : int fn_opt, fn_nid;
450 : ASN1_OBJECT *fn;
451 : ASN1_STRING *val;
452 : X509_NAME_ENTRY *ent;
453 : char objtmp[80];
454 : const char *objbuf;
455 : int outlen, len;
456 : char *sep_dn, *sep_mv, *sep_eq;
457 : int sep_dn_len, sep_mv_len, sep_eq_len;
458 0 : if (indent < 0)
459 : indent = 0;
460 : outlen = indent;
461 0 : if (!do_indent(io_ch, arg, indent))
462 : return -1;
463 0 : switch (flags & XN_FLAG_SEP_MASK) {
464 : case XN_FLAG_SEP_MULTILINE:
465 : sep_dn = "\n";
466 : sep_dn_len = 1;
467 : sep_mv = " + ";
468 : sep_mv_len = 3;
469 : break;
470 :
471 : case XN_FLAG_SEP_COMMA_PLUS:
472 : sep_dn = ",";
473 : sep_dn_len = 1;
474 : sep_mv = "+";
475 : sep_mv_len = 1;
476 : indent = 0;
477 0 : break;
478 :
479 : case XN_FLAG_SEP_CPLUS_SPC:
480 : sep_dn = ", ";
481 : sep_dn_len = 2;
482 : sep_mv = " + ";
483 : sep_mv_len = 3;
484 : indent = 0;
485 0 : break;
486 :
487 : case XN_FLAG_SEP_SPLUS_SPC:
488 : sep_dn = "; ";
489 : sep_dn_len = 2;
490 : sep_mv = " + ";
491 : sep_mv_len = 3;
492 : indent = 0;
493 0 : break;
494 :
495 : default:
496 : return -1;
497 : }
498 :
499 0 : if (flags & XN_FLAG_SPC_EQ) {
500 : sep_eq = " = ";
501 : sep_eq_len = 3;
502 : } else {
503 : sep_eq = "=";
504 : sep_eq_len = 1;
505 : }
506 :
507 0 : fn_opt = flags & XN_FLAG_FN_MASK;
508 :
509 0 : cnt = X509_NAME_entry_count(n);
510 0 : for (i = 0; i < cnt; i++) {
511 0 : if (flags & XN_FLAG_DN_REV)
512 0 : ent = X509_NAME_get_entry(n, cnt - i - 1);
513 : else
514 0 : ent = X509_NAME_get_entry(n, i);
515 0 : if (prev != -1) {
516 0 : if (prev == ent->set) {
517 0 : if (!io_ch(arg, sep_mv, sep_mv_len))
518 : return -1;
519 0 : outlen += sep_mv_len;
520 : } else {
521 0 : if (!io_ch(arg, sep_dn, sep_dn_len))
522 : return -1;
523 0 : outlen += sep_dn_len;
524 0 : if (!do_indent(io_ch, arg, indent))
525 : return -1;
526 0 : outlen += indent;
527 : }
528 : }
529 0 : prev = ent->set;
530 0 : fn = X509_NAME_ENTRY_get_object(ent);
531 0 : val = X509_NAME_ENTRY_get_data(ent);
532 0 : fn_nid = OBJ_obj2nid(fn);
533 0 : if (fn_opt != XN_FLAG_FN_NONE) {
534 : int objlen, fld_len;
535 0 : if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) {
536 0 : OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1);
537 : fld_len = 0; /* XXX: what should this be? */
538 : objbuf = objtmp;
539 : } else {
540 0 : if (fn_opt == XN_FLAG_FN_SN) {
541 : fld_len = FN_WIDTH_SN;
542 0 : objbuf = OBJ_nid2sn(fn_nid);
543 0 : } else if (fn_opt == XN_FLAG_FN_LN) {
544 : fld_len = FN_WIDTH_LN;
545 0 : objbuf = OBJ_nid2ln(fn_nid);
546 : } else {
547 : fld_len = 0; /* XXX: what should this be? */
548 : objbuf = "";
549 : }
550 : }
551 0 : objlen = strlen(objbuf);
552 0 : if (!io_ch(arg, objbuf, objlen))
553 : return -1;
554 0 : if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) {
555 0 : if (!do_indent(io_ch, arg, fld_len - objlen))
556 : return -1;
557 0 : outlen += fld_len - objlen;
558 : }
559 0 : if (!io_ch(arg, sep_eq, sep_eq_len))
560 : return -1;
561 0 : outlen += objlen + sep_eq_len;
562 : }
563 : /*
564 : * If the field name is unknown then fix up the DER dump flag. We
565 : * might want to limit this further so it will DER dump on anything
566 : * other than a few 'standard' fields.
567 : */
568 0 : if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS))
569 : orflags = ASN1_STRFLGS_DUMP_ALL;
570 : else
571 : orflags = 0;
572 :
573 0 : len = do_print_ex(io_ch, arg, flags | orflags, val);
574 0 : if (len < 0)
575 : return -1;
576 0 : outlen += len;
577 : }
578 : return outlen;
579 : }
580 :
581 : /* Wrappers round the main functions */
582 :
583 0 : int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent,
584 : unsigned long flags)
585 : {
586 0 : if (flags == XN_FLAG_COMPAT)
587 0 : return X509_NAME_print(out, nm, indent);
588 0 : return do_name_ex(send_bio_chars, out, nm, indent, flags);
589 : }
590 :
591 : #ifndef OPENSSL_NO_FP_API
592 0 : int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent,
593 : unsigned long flags)
594 : {
595 0 : if (flags == XN_FLAG_COMPAT) {
596 : BIO *btmp;
597 : int ret;
598 0 : btmp = BIO_new_fp(fp, BIO_NOCLOSE);
599 0 : if (!btmp)
600 : return -1;
601 0 : ret = X509_NAME_print(btmp, nm, indent);
602 0 : BIO_free(btmp);
603 0 : return ret;
604 : }
605 0 : return do_name_ex(send_fp_chars, fp, nm, indent, flags);
606 : }
607 : #endif
608 :
609 0 : int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags)
610 : {
611 0 : return do_print_ex(send_bio_chars, out, flags, str);
612 : }
613 :
614 : #ifndef OPENSSL_NO_FP_API
615 0 : int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags)
616 : {
617 0 : return do_print_ex(send_fp_chars, fp, flags, str);
618 : }
619 : #endif
620 :
621 : /*
622 : * Utility function: convert any string type to UTF8, returns number of bytes
623 : * in output string or a negative error code
624 : */
625 :
626 17904 : int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in)
627 : {
628 17904 : ASN1_STRING stmp, *str = &stmp;
629 : int mbflag, type, ret;
630 17904 : if (!in)
631 : return -1;
632 17904 : type = in->type;
633 17904 : if ((type < 0) || (type > 30))
634 : return -1;
635 17904 : mbflag = tag2nbyte[type];
636 17904 : if (mbflag == -1)
637 : return -1;
638 17904 : mbflag |= MBSTRING_FLAG;
639 17904 : stmp.data = NULL;
640 17904 : stmp.length = 0;
641 17904 : stmp.flags = 0;
642 17904 : ret =
643 17904 : ASN1_mbstring_copy(&str, in->data, in->length, mbflag,
644 : B_ASN1_UTF8STRING);
645 17904 : if (ret < 0)
646 : return ret;
647 17904 : *out = stmp.data;
648 17904 : return stmp.length;
649 : }
|