1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * All rights reserved.
3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This package is an SSL implementation written
5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * by Eric Young (eay@cryptsoft.com).
6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The implementation was written so as to conform with Netscapes SSL.
7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This library is free for commercial and non-commercial use as long as
9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the following conditions are aheared to.  The following conditions
10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * apply to all code found in this distribution, be it the RC4, RSA,
11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * included with this distribution is covered by the same copyright terms
13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright remains Eric Young's, and as such any Copyright notices in
16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the code are not to be removed.
17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * If this package is used in a product, Eric Young should be given attribution
18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * as the author of the parts of the library used.
19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This can be in the form of a textual message at program startup or
20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * in documentation (online or textual) provided with the package.
21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without
23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions
24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met:
25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the copyright
26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer.
27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright
28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer in the
29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    documentation and/or other materials provided with the distribution.
30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this software
31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    must display the following acknowledgement:
32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes cryptographic software written by
33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *     Eric Young (eay@cryptsoft.com)"
34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    The word 'cryptographic' can be left out if the rouines from the library
35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    being used are not cryptographic related :-).
36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. If you include any Windows specific code (or a derivative thereof) from
37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    the apps directory (application code) you must include an acknowledgement:
38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SUCH DAMAGE.
51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The licence and distribution terms for any publically available version or
53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * derivative of this code cannot be changed.  i.e. this code cannot simply be
54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * copied and put under another distribution licence
55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * [including the GNU Public Licence.] */
56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/asn1.h>
58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <string.h>
60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h>
62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/mem.h>
63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
65d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int traverse_string(const unsigned char *p, int len, int inform,
66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		 int (*rfunc)(unsigned long value, void *in), void *arg);
67d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int in_utf8(unsigned long value, void *arg);
68d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int out_utf8(unsigned long value, void *arg);
69d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int type_str(unsigned long value, void *arg);
70d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int cpy_asc(unsigned long value, void *arg);
71d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int cpy_bmp(unsigned long value, void *arg);
72d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int cpy_univ(unsigned long value, void *arg);
73d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int cpy_utf8(unsigned long value, void *arg);
74d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int is_printable(unsigned long value);
75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
76d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* These functions take a string in UTF8, ASCII or multibyte form and
77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * a mask of permissible ASN1 string types. It then works out the minimal
78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * and creates a string of the correct type with the supplied data.
80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Yes this is horrible: it has to be :-(
81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The 'ncopy' form checks minimum and maximum size limits too.
82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */
83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
84d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley					int inform, unsigned long mask)
86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
88d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
90d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley					int inform, unsigned long mask,
92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley					long minsize, long maxsize)
93d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
94d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int str_type;
95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int ret;
96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	char free_out;
97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int outform, outlen = 0;
98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	ASN1_STRING *dest;
99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	unsigned char *p;
100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int nchar;
101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	char strbuf[32];
102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int (*cpyfunc)(unsigned long,void *) = NULL;
103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(len == -1) len = strlen((const char *)in);
104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(!mask) mask = DIRSTRING_TYPE;
105d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	/* First do a string check and work out the number of characters */
107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	switch(inform) {
108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		case MBSTRING_BMP:
110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(len & 1) {
111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy,  ASN1_R_INVALID_BMPSTRING_LENGTH);
112d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			return -1;
113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		}
114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		nchar = len >> 1;
115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		break;
116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		case MBSTRING_UNIV:
118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(len & 3) {
119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy,  ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			return -1;
121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		}
122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		nchar = len >> 2;
123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		break;
124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
125d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		case MBSTRING_UTF8:
126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		nchar = 0;
127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		/* This counts the characters and does utf8 syntax checking */
128d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(ret < 0) {
130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy,  ASN1_R_INVALID_UTF8STRING);
131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			return -1;
132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		}
133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		break;
134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		case MBSTRING_ASC:
136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		nchar = len;
137d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		break;
138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		default:
140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy,  ASN1_R_UNKNOWN_FORMAT);
141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return -1;
142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
144d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if((minsize > 0) && (nchar < minsize)) {
145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy,  ASN1_R_STRING_TOO_SHORT);
146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize);
147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		ERR_add_error_data(2, "minsize=", strbuf);
148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return -1;
149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if((maxsize > 0) && (nchar > maxsize)) {
152d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy,  ASN1_R_STRING_TOO_LONG);
153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize);
154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		ERR_add_error_data(2, "maxsize=", strbuf);
155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return -1;
156d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	/* Now work out minimal type (if any) */
159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(traverse_string(in, len, inform, type_str, &mask) < 0) {
160d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy,  ASN1_R_ILLEGAL_CHARACTERS);
161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return -1;
162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
164d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	/* Now work out output format and string type */
166d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	outform = MBSTRING_ASC;
167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(mask & B_ASN1_PRINTABLESTRING) str_type = V_ASN1_PRINTABLESTRING;
168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	else if(mask & B_ASN1_IA5STRING) str_type = V_ASN1_IA5STRING;
169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	else if(mask & B_ASN1_T61STRING) str_type = V_ASN1_T61STRING;
170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	else if(mask & B_ASN1_BMPSTRING) {
171d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		str_type = V_ASN1_BMPSTRING;
172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		outform = MBSTRING_BMP;
173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	} else if(mask & B_ASN1_UNIVERSALSTRING) {
174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		str_type = V_ASN1_UNIVERSALSTRING;
175d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		outform = MBSTRING_UNIV;
176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	} else {
177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		str_type = V_ASN1_UTF8STRING;
178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		outform = MBSTRING_UTF8;
179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(!out) return str_type;
181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(*out) {
182d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		free_out = 0;
183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		dest = *out;
184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(dest->data) {
185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			dest->length = 0;
186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			OPENSSL_free(dest->data);
187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			dest->data = NULL;
188d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		}
189d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		dest->type = str_type;
190d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	} else {
191d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		free_out = 1;
192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		dest = ASN1_STRING_type_new(str_type);
193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(!dest) {
194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy,  ERR_R_MALLOC_FAILURE);
195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			return -1;
196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		}
197d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		*out = dest;
198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	/* If both the same type just copy across */
200d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(inform == outform) {
201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(!ASN1_STRING_set(dest, in, len)) {
202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ERR_R_MALLOC_FAILURE);
203d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			return -1;
204d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		}
205d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return str_type;
206d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
208d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	/* Work out how much space the destination will need */
209d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	switch(outform) {
210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		case MBSTRING_ASC:
211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		outlen = nchar;
212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		cpyfunc = cpy_asc;
213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		break;
214d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
215d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		case MBSTRING_BMP:
216d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		outlen = nchar << 1;
217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		cpyfunc = cpy_bmp;
218d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		break;
219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
220d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		case MBSTRING_UNIV:
221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		outlen = nchar << 2;
222d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		cpyfunc = cpy_univ;
223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		break;
224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		case MBSTRING_UTF8:
226d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		outlen = 0;
227d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		traverse_string(in, len, inform, out_utf8, &outlen);
228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		cpyfunc = cpy_utf8;
229d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		break;
230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
231d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(!(p = OPENSSL_malloc(outlen + 1))) {
232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(free_out) ASN1_STRING_free(dest);
233d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		OPENSSL_PUT_ERROR(ASN1, ASN1_mbstring_ncopy, ERR_R_MALLOC_FAILURE);
234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		return -1;
235d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
236d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	dest->length = outlen;
237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	dest->data = p;
238d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	p[outlen] = 0;
239d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	traverse_string(in, len, inform, cpyfunc, &p);
240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return str_type;
241d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
243d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* This function traverses a string and passes the value of each character
244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * to an optional function along with a void * argument.
245d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */
246d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
247d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int traverse_string(const unsigned char *p, int len, int inform,
248d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		 int (*rfunc)(unsigned long value, void *in), void *arg)
249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
250d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	unsigned long value;
251d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int ret;
252d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	while(len) {
253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(inform == MBSTRING_ASC) {
254d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			value = *p++;
255d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			len--;
256d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		} else if(inform == MBSTRING_BMP) {
257d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			value = *p++ << 8;
258d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			value |= *p++;
259d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			len -= 2;
260d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		} else if(inform == MBSTRING_UNIV) {
261d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			value = ((unsigned long)*p++) << 24;
262d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			value |= ((unsigned long)*p++) << 16;
263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			value |= *p++ << 8;
264d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			value |= *p++;
265d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			len -= 4;
266d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		} else {
267d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			ret = UTF8_getc(p, len, &value);
268d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			if(ret < 0) return -1;
269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			len -= ret;
270d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			p += ret;
271d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		}
272d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		if(rfunc) {
273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			ret = rfunc(value, arg);
274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley			if(ret <= 0) return ret;
275d9e397b599b13d642138480a28c14db7a136bf0Adam Langley		}
276d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	}
277d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return 1;
278d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
279d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Various utility functions for traverse_string */
281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
282d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Just count number of characters */
283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
284d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int in_utf8(unsigned long value, void *arg)
285d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
286d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int *nchar;
287d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	nchar = arg;
288d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	(*nchar)++;
289d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return 1;
290d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
291d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Determine size of output as a UTF8 String */
293d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
294d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int out_utf8(unsigned long value, void *arg)
295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
296d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int *outlen;
297d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	outlen = arg;
298d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	*outlen += UTF8_putc(NULL, -1, value);
299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return 1;
300d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
302d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Determine the "type" of a string: check each character against a
303d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * supplied "mask".
304d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */
305d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
306d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int type_str(unsigned long value, void *arg)
307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
308d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	unsigned long types;
309d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	types = *((unsigned long *)arg);
310d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if((types & B_ASN1_PRINTABLESTRING) && !is_printable(value))
311d9e397b599b13d642138480a28c14db7a136bf0Adam Langley					types &= ~B_ASN1_PRINTABLESTRING;
312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if((types & B_ASN1_IA5STRING) && (value > 127))
313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley					types &= ~B_ASN1_IA5STRING;
314d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if((types & B_ASN1_T61STRING) && (value > 0xff))
315d9e397b599b13d642138480a28c14db7a136bf0Adam Langley					types &= ~B_ASN1_T61STRING;
316d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if((types & B_ASN1_BMPSTRING) && (value > 0xffff))
317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley					types &= ~B_ASN1_BMPSTRING;
318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(!types) return -1;
319d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	*((unsigned long *)arg) = types;
320d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return 1;
321d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
322d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
323d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copy one byte per character ASCII like strings */
324d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
325d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int cpy_asc(unsigned long value, void *arg)
326d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
327d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	unsigned char **p, *q;
328d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	p = arg;
329d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	q = *p;
330d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	*q = (unsigned char) value;
331d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	(*p)++;
332d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return 1;
333d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
334d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copy two byte per character BMPStrings */
336d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
337d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int cpy_bmp(unsigned long value, void *arg)
338d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
339d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	unsigned char **p, *q;
340d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	p = arg;
341d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	q = *p;
342d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	*q++ = (unsigned char) ((value >> 8) & 0xff);
343d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	*q = (unsigned char) (value & 0xff);
344d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	*p += 2;
345d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return 1;
346d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
347d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
348d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copy four byte per character UniversalStrings */
349d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
350d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int cpy_univ(unsigned long value, void *arg)
351d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
352d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	unsigned char **p, *q;
353d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	p = arg;
354d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	q = *p;
355d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	*q++ = (unsigned char) ((value >> 24) & 0xff);
356d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	*q++ = (unsigned char) ((value >> 16) & 0xff);
357d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	*q++ = (unsigned char) ((value >> 8) & 0xff);
358d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	*q = (unsigned char) (value & 0xff);
359d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	*p += 4;
360d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return 1;
361d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
362d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
363d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Copy to a UTF8String */
364d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
365d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int cpy_utf8(unsigned long value, void *arg)
366d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	unsigned char **p;
368d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int ret;
369d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	p = arg;
370d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	/* We already know there is enough room so pass 0xff as the length */
371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	ret = UTF8_putc(*p, 0xff, value);
372d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	*p += ret;
373d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return 1;
374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
375d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
376d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Return 1 if the character is permitted in a PrintableString */
377d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int is_printable(unsigned long value)
378d9e397b599b13d642138480a28c14db7a136bf0Adam Langley{
379d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	int ch;
380d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if(value > 0x7f) return 0;
381d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	ch = (int) value;
382d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	/* Note: we can't use 'isalnum' because certain accented
383d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	 * characters may count as alphanumeric in some environments.
384d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	 */
385d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if((ch >= 'a') && (ch <= 'z')) return 1;
386d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if((ch >= 'A') && (ch <= 'Z')) return 1;
387d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if((ch >= '0') && (ch <= '9')) return 1;
388d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	if ((ch == ' ') || strchr("'()+,-./:=?", ch)) return 1;
389d9e397b599b13d642138480a28c14db7a136bf0Adam Langley	return 0;
390d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
391