1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: a_mbstr.c,v 1.24 2021/12/25 13:17:48 jsing Exp $ */
2f5b1c8a1SJohn Marino /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3f5b1c8a1SJohn Marino * project 1999.
4f5b1c8a1SJohn Marino */
5f5b1c8a1SJohn Marino /* ====================================================================
6f5b1c8a1SJohn Marino * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
7f5b1c8a1SJohn Marino *
8f5b1c8a1SJohn Marino * Redistribution and use in source and binary forms, with or without
9f5b1c8a1SJohn Marino * modification, are permitted provided that the following conditions
10f5b1c8a1SJohn Marino * are met:
11f5b1c8a1SJohn Marino *
12f5b1c8a1SJohn Marino * 1. Redistributions of source code must retain the above copyright
13f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer.
14f5b1c8a1SJohn Marino *
15f5b1c8a1SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
16f5b1c8a1SJohn Marino * notice, this list of conditions and the following disclaimer in
17f5b1c8a1SJohn Marino * the documentation and/or other materials provided with the
18f5b1c8a1SJohn Marino * distribution.
19f5b1c8a1SJohn Marino *
20f5b1c8a1SJohn Marino * 3. All advertising materials mentioning features or use of this
21f5b1c8a1SJohn Marino * software must display the following acknowledgment:
22f5b1c8a1SJohn Marino * "This product includes software developed by the OpenSSL Project
23f5b1c8a1SJohn Marino * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24f5b1c8a1SJohn Marino *
25f5b1c8a1SJohn Marino * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26f5b1c8a1SJohn Marino * endorse or promote products derived from this software without
27f5b1c8a1SJohn Marino * prior written permission. For written permission, please contact
28f5b1c8a1SJohn Marino * licensing@OpenSSL.org.
29f5b1c8a1SJohn Marino *
30f5b1c8a1SJohn Marino * 5. Products derived from this software may not be called "OpenSSL"
31f5b1c8a1SJohn Marino * nor may "OpenSSL" appear in their names without prior written
32f5b1c8a1SJohn Marino * permission of the OpenSSL Project.
33f5b1c8a1SJohn Marino *
34f5b1c8a1SJohn Marino * 6. Redistributions of any form whatsoever must retain the following
35f5b1c8a1SJohn Marino * acknowledgment:
36f5b1c8a1SJohn Marino * "This product includes software developed by the OpenSSL Project
37f5b1c8a1SJohn Marino * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38f5b1c8a1SJohn Marino *
39f5b1c8a1SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40f5b1c8a1SJohn Marino * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41f5b1c8a1SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42f5b1c8a1SJohn Marino * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43f5b1c8a1SJohn Marino * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44f5b1c8a1SJohn Marino * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45f5b1c8a1SJohn Marino * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46f5b1c8a1SJohn Marino * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47f5b1c8a1SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48f5b1c8a1SJohn Marino * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49f5b1c8a1SJohn Marino * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50f5b1c8a1SJohn Marino * OF THE POSSIBILITY OF SUCH DAMAGE.
51f5b1c8a1SJohn Marino * ====================================================================
52f5b1c8a1SJohn Marino *
53f5b1c8a1SJohn Marino * This product includes cryptographic software written by Eric Young
54f5b1c8a1SJohn Marino * (eay@cryptsoft.com). This product includes software written by Tim
55f5b1c8a1SJohn Marino * Hudson (tjh@cryptsoft.com).
56f5b1c8a1SJohn Marino *
57f5b1c8a1SJohn Marino */
58f5b1c8a1SJohn Marino
59f5b1c8a1SJohn Marino #include <ctype.h>
60f5b1c8a1SJohn Marino #include <stdio.h>
61f5b1c8a1SJohn Marino #include <string.h>
62f5b1c8a1SJohn Marino
63f5b1c8a1SJohn Marino #include <openssl/asn1.h>
64f5b1c8a1SJohn Marino #include <openssl/err.h>
65f5b1c8a1SJohn Marino
66f5b1c8a1SJohn Marino #include "asn1_locl.h"
67f5b1c8a1SJohn Marino
68f5b1c8a1SJohn Marino static int traverse_string(const unsigned char *p, int len, int inform,
69f5b1c8a1SJohn Marino int (*rfunc)(unsigned long value, void *in), void *arg);
70f5b1c8a1SJohn Marino static int in_utf8(unsigned long value, void *arg);
71f5b1c8a1SJohn Marino static int out_utf8(unsigned long value, void *arg);
72f5b1c8a1SJohn Marino static int type_str(unsigned long value, void *arg);
73f5b1c8a1SJohn Marino static int cpy_asc(unsigned long value, void *arg);
74f5b1c8a1SJohn Marino static int cpy_bmp(unsigned long value, void *arg);
75f5b1c8a1SJohn Marino static int cpy_univ(unsigned long value, void *arg);
76f5b1c8a1SJohn Marino static int cpy_utf8(unsigned long value, void *arg);
77f5b1c8a1SJohn Marino static int is_printable(unsigned long value);
78f5b1c8a1SJohn Marino
79f5b1c8a1SJohn Marino /* These functions take a string in UTF8, ASCII or multibyte form and
80f5b1c8a1SJohn Marino * a mask of permissible ASN1 string types. It then works out the minimal
81f5b1c8a1SJohn Marino * type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
82f5b1c8a1SJohn Marino * and creates a string of the correct type with the supplied data.
83f5b1c8a1SJohn Marino * Yes this is horrible: it has to be :-(
84f5b1c8a1SJohn Marino * The 'ncopy' form checks minimum and maximum size limits too.
85f5b1c8a1SJohn Marino */
86f5b1c8a1SJohn Marino
87f5b1c8a1SJohn Marino int
ASN1_mbstring_copy(ASN1_STRING ** out,const unsigned char * in,int len,int inform,unsigned long mask)88f5b1c8a1SJohn Marino ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
89f5b1c8a1SJohn Marino int inform, unsigned long mask)
90f5b1c8a1SJohn Marino {
91f5b1c8a1SJohn Marino return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
92f5b1c8a1SJohn Marino }
93f5b1c8a1SJohn Marino
94f5b1c8a1SJohn Marino int
ASN1_mbstring_ncopy(ASN1_STRING ** out,const unsigned char * in,int len,int inform,unsigned long mask,long minsize,long maxsize)95f5b1c8a1SJohn Marino ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
96f5b1c8a1SJohn Marino int inform, unsigned long mask, long minsize, long maxsize)
97f5b1c8a1SJohn Marino {
98f5b1c8a1SJohn Marino int str_type;
99f5b1c8a1SJohn Marino int ret;
100f5b1c8a1SJohn Marino char free_out;
101f5b1c8a1SJohn Marino int outform, outlen = 0;
102f5b1c8a1SJohn Marino ASN1_STRING *dest;
103f5b1c8a1SJohn Marino unsigned char *p;
104f5b1c8a1SJohn Marino int nchar;
105f5b1c8a1SJohn Marino int (*cpyfunc)(unsigned long, void *) = NULL;
106f5b1c8a1SJohn Marino
107f5b1c8a1SJohn Marino if (len < 0)
108f5b1c8a1SJohn Marino len = strlen((const char *)in);
109f5b1c8a1SJohn Marino if (!mask)
110f5b1c8a1SJohn Marino mask = DIRSTRING_TYPE;
111f5b1c8a1SJohn Marino
112f5b1c8a1SJohn Marino /* First do a string check and work out the number of characters */
113f5b1c8a1SJohn Marino switch (inform) {
114f5b1c8a1SJohn Marino case MBSTRING_BMP:
115f5b1c8a1SJohn Marino if (len & 1) {
11672c33676SMaxim Ag ASN1error(ASN1_R_INVALID_BMPSTRING_LENGTH);
117f5b1c8a1SJohn Marino return -1;
118f5b1c8a1SJohn Marino }
119f5b1c8a1SJohn Marino nchar = len >> 1;
120f5b1c8a1SJohn Marino break;
121f5b1c8a1SJohn Marino
122f5b1c8a1SJohn Marino case MBSTRING_UNIV:
123f5b1c8a1SJohn Marino if (len & 3) {
12472c33676SMaxim Ag ASN1error(ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
125f5b1c8a1SJohn Marino return -1;
126f5b1c8a1SJohn Marino }
127f5b1c8a1SJohn Marino nchar = len >> 2;
128f5b1c8a1SJohn Marino break;
129f5b1c8a1SJohn Marino
130f5b1c8a1SJohn Marino case MBSTRING_UTF8:
131f5b1c8a1SJohn Marino nchar = 0;
132f5b1c8a1SJohn Marino /* This counts the characters and does utf8 syntax checking */
133f5b1c8a1SJohn Marino ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
134f5b1c8a1SJohn Marino if (ret < 0) {
13572c33676SMaxim Ag ASN1error(ASN1_R_INVALID_UTF8STRING);
136f5b1c8a1SJohn Marino return -1;
137f5b1c8a1SJohn Marino }
138f5b1c8a1SJohn Marino break;
139f5b1c8a1SJohn Marino
140f5b1c8a1SJohn Marino case MBSTRING_ASC:
141f5b1c8a1SJohn Marino nchar = len;
142f5b1c8a1SJohn Marino break;
143f5b1c8a1SJohn Marino
144f5b1c8a1SJohn Marino default:
14572c33676SMaxim Ag ASN1error(ASN1_R_UNKNOWN_FORMAT);
146f5b1c8a1SJohn Marino return -1;
147f5b1c8a1SJohn Marino }
148f5b1c8a1SJohn Marino
149f5b1c8a1SJohn Marino if ((minsize > 0) && (nchar < minsize)) {
15072c33676SMaxim Ag ASN1error(ASN1_R_STRING_TOO_SHORT);
151f5b1c8a1SJohn Marino ERR_asprintf_error_data("minsize=%ld", minsize);
152f5b1c8a1SJohn Marino return -1;
153f5b1c8a1SJohn Marino }
154f5b1c8a1SJohn Marino
155f5b1c8a1SJohn Marino if ((maxsize > 0) && (nchar > maxsize)) {
15672c33676SMaxim Ag ASN1error(ASN1_R_STRING_TOO_LONG);
157f5b1c8a1SJohn Marino ERR_asprintf_error_data("maxsize=%ld", maxsize);
158f5b1c8a1SJohn Marino return -1;
159f5b1c8a1SJohn Marino }
160f5b1c8a1SJohn Marino
161f5b1c8a1SJohn Marino /* Now work out minimal type (if any) */
162f5b1c8a1SJohn Marino if (traverse_string(in, len, inform, type_str, &mask) < 0) {
16372c33676SMaxim Ag ASN1error(ASN1_R_ILLEGAL_CHARACTERS);
164f5b1c8a1SJohn Marino return -1;
165f5b1c8a1SJohn Marino }
166f5b1c8a1SJohn Marino
167f5b1c8a1SJohn Marino
168f5b1c8a1SJohn Marino /* Now work out output format and string type */
169f5b1c8a1SJohn Marino outform = MBSTRING_ASC;
170f5b1c8a1SJohn Marino if (mask & B_ASN1_PRINTABLESTRING)
171f5b1c8a1SJohn Marino str_type = V_ASN1_PRINTABLESTRING;
172f5b1c8a1SJohn Marino else if (mask & B_ASN1_IA5STRING)
173f5b1c8a1SJohn Marino str_type = V_ASN1_IA5STRING;
174f5b1c8a1SJohn Marino else if (mask & B_ASN1_T61STRING)
175f5b1c8a1SJohn Marino str_type = V_ASN1_T61STRING;
176f5b1c8a1SJohn Marino else if (mask & B_ASN1_BMPSTRING) {
177f5b1c8a1SJohn Marino str_type = V_ASN1_BMPSTRING;
178f5b1c8a1SJohn Marino outform = MBSTRING_BMP;
179f5b1c8a1SJohn Marino } else if (mask & B_ASN1_UNIVERSALSTRING) {
180f5b1c8a1SJohn Marino str_type = V_ASN1_UNIVERSALSTRING;
181f5b1c8a1SJohn Marino outform = MBSTRING_UNIV;
182f5b1c8a1SJohn Marino } else {
183f5b1c8a1SJohn Marino str_type = V_ASN1_UTF8STRING;
184f5b1c8a1SJohn Marino outform = MBSTRING_UTF8;
185f5b1c8a1SJohn Marino }
186f5b1c8a1SJohn Marino if (!out)
187f5b1c8a1SJohn Marino return str_type;
188f5b1c8a1SJohn Marino if (*out) {
189f5b1c8a1SJohn Marino free_out = 0;
190f5b1c8a1SJohn Marino dest = *out;
191f5b1c8a1SJohn Marino if (dest->data) {
192f5b1c8a1SJohn Marino dest->length = 0;
193f5b1c8a1SJohn Marino free(dest->data);
194f5b1c8a1SJohn Marino dest->data = NULL;
195f5b1c8a1SJohn Marino }
196f5b1c8a1SJohn Marino dest->type = str_type;
197f5b1c8a1SJohn Marino } else {
198f5b1c8a1SJohn Marino free_out = 1;
199f5b1c8a1SJohn Marino dest = ASN1_STRING_type_new(str_type);
200f5b1c8a1SJohn Marino if (!dest) {
20172c33676SMaxim Ag ASN1error(ERR_R_MALLOC_FAILURE);
202f5b1c8a1SJohn Marino return -1;
203f5b1c8a1SJohn Marino }
204f5b1c8a1SJohn Marino *out = dest;
205f5b1c8a1SJohn Marino }
206f5b1c8a1SJohn Marino /* If both the same type just copy across */
207f5b1c8a1SJohn Marino if (inform == outform) {
208f5b1c8a1SJohn Marino if (!ASN1_STRING_set(dest, in, len)) {
20972c33676SMaxim Ag ASN1error(ERR_R_MALLOC_FAILURE);
210f5b1c8a1SJohn Marino goto err;
211f5b1c8a1SJohn Marino }
212f5b1c8a1SJohn Marino return str_type;
213f5b1c8a1SJohn Marino }
214f5b1c8a1SJohn Marino
215f5b1c8a1SJohn Marino /* Work out how much space the destination will need */
216f5b1c8a1SJohn Marino switch (outform) {
217f5b1c8a1SJohn Marino case MBSTRING_ASC:
218f5b1c8a1SJohn Marino outlen = nchar;
219f5b1c8a1SJohn Marino cpyfunc = cpy_asc;
220f5b1c8a1SJohn Marino break;
221f5b1c8a1SJohn Marino
222f5b1c8a1SJohn Marino case MBSTRING_BMP:
223f5b1c8a1SJohn Marino outlen = nchar << 1;
224f5b1c8a1SJohn Marino cpyfunc = cpy_bmp;
225f5b1c8a1SJohn Marino break;
226f5b1c8a1SJohn Marino
227f5b1c8a1SJohn Marino case MBSTRING_UNIV:
228f5b1c8a1SJohn Marino outlen = nchar << 2;
229f5b1c8a1SJohn Marino cpyfunc = cpy_univ;
230f5b1c8a1SJohn Marino break;
231f5b1c8a1SJohn Marino
232f5b1c8a1SJohn Marino case MBSTRING_UTF8:
233f5b1c8a1SJohn Marino outlen = 0;
234f5b1c8a1SJohn Marino if (traverse_string(in, len, inform, out_utf8, &outlen) < 0) {
23572c33676SMaxim Ag ASN1error(ASN1_R_ILLEGAL_CHARACTERS);
236f5b1c8a1SJohn Marino goto err;
237f5b1c8a1SJohn Marino }
238f5b1c8a1SJohn Marino cpyfunc = cpy_utf8;
239f5b1c8a1SJohn Marino break;
240f5b1c8a1SJohn Marino }
241f5b1c8a1SJohn Marino if (!(p = malloc(outlen + 1))) {
24272c33676SMaxim Ag ASN1error(ERR_R_MALLOC_FAILURE);
243f5b1c8a1SJohn Marino goto err;
244f5b1c8a1SJohn Marino }
245f5b1c8a1SJohn Marino dest->length = outlen;
246f5b1c8a1SJohn Marino dest->data = p;
247f5b1c8a1SJohn Marino p[outlen] = 0;
248f5b1c8a1SJohn Marino traverse_string(in, len, inform, cpyfunc, &p);
249f5b1c8a1SJohn Marino return str_type;
250f5b1c8a1SJohn Marino
251f5b1c8a1SJohn Marino err:
252f5b1c8a1SJohn Marino if (free_out) {
253f5b1c8a1SJohn Marino ASN1_STRING_free(dest);
254f5b1c8a1SJohn Marino *out = NULL;
255f5b1c8a1SJohn Marino }
256f5b1c8a1SJohn Marino return -1;
257f5b1c8a1SJohn Marino }
258f5b1c8a1SJohn Marino
259f5b1c8a1SJohn Marino /* This function traverses a string and passes the value of each character
260f5b1c8a1SJohn Marino * to an optional function along with a void * argument.
261f5b1c8a1SJohn Marino */
262f5b1c8a1SJohn Marino
263f5b1c8a1SJohn Marino static int
traverse_string(const unsigned char * p,int len,int inform,int (* rfunc)(unsigned long value,void * in),void * arg)264f5b1c8a1SJohn Marino traverse_string(const unsigned char *p, int len, int inform,
265f5b1c8a1SJohn Marino int (*rfunc)(unsigned long value, void *in), void *arg)
266f5b1c8a1SJohn Marino {
267f5b1c8a1SJohn Marino unsigned long value;
268f5b1c8a1SJohn Marino int ret;
269f5b1c8a1SJohn Marino
270f5b1c8a1SJohn Marino while (len) {
271f5b1c8a1SJohn Marino switch (inform) {
272f5b1c8a1SJohn Marino case MBSTRING_ASC:
273f5b1c8a1SJohn Marino value = *p++;
274f5b1c8a1SJohn Marino len--;
275f5b1c8a1SJohn Marino break;
276f5b1c8a1SJohn Marino case MBSTRING_BMP:
277f5b1c8a1SJohn Marino value = *p++ << 8;
278f5b1c8a1SJohn Marino value |= *p++;
279f5b1c8a1SJohn Marino /* BMP is explictly defined to not support surrogates */
280f5b1c8a1SJohn Marino if (UNICODE_IS_SURROGATE(value))
281f5b1c8a1SJohn Marino return -1;
282f5b1c8a1SJohn Marino len -= 2;
283f5b1c8a1SJohn Marino break;
284f5b1c8a1SJohn Marino case MBSTRING_UNIV:
285f5b1c8a1SJohn Marino value = (unsigned long)*p++ << 24;
286f5b1c8a1SJohn Marino value |= *p++ << 16;
287f5b1c8a1SJohn Marino value |= *p++ << 8;
288f5b1c8a1SJohn Marino value |= *p++;
289f5b1c8a1SJohn Marino if (value > UNICODE_MAX || UNICODE_IS_SURROGATE(value))
290f5b1c8a1SJohn Marino return -1;
291f5b1c8a1SJohn Marino len -= 4;
292f5b1c8a1SJohn Marino break;
293f5b1c8a1SJohn Marino default:
294f5b1c8a1SJohn Marino ret = UTF8_getc(p, len, &value);
295f5b1c8a1SJohn Marino if (ret < 0)
296f5b1c8a1SJohn Marino return -1;
297f5b1c8a1SJohn Marino len -= ret;
298f5b1c8a1SJohn Marino p += ret;
299f5b1c8a1SJohn Marino break;
300f5b1c8a1SJohn Marino }
301f5b1c8a1SJohn Marino if (rfunc) {
302f5b1c8a1SJohn Marino ret = rfunc(value, arg);
303f5b1c8a1SJohn Marino if (ret <= 0)
304f5b1c8a1SJohn Marino return ret;
305f5b1c8a1SJohn Marino }
306f5b1c8a1SJohn Marino }
307f5b1c8a1SJohn Marino return 1;
308f5b1c8a1SJohn Marino }
309f5b1c8a1SJohn Marino
310f5b1c8a1SJohn Marino /* Various utility functions for traverse_string */
311f5b1c8a1SJohn Marino
312f5b1c8a1SJohn Marino /* Just count number of characters */
313f5b1c8a1SJohn Marino
314f5b1c8a1SJohn Marino static int
in_utf8(unsigned long value,void * arg)315f5b1c8a1SJohn Marino in_utf8(unsigned long value, void *arg)
316f5b1c8a1SJohn Marino {
317f5b1c8a1SJohn Marino int *nchar;
318f5b1c8a1SJohn Marino
319f5b1c8a1SJohn Marino nchar = arg;
320f5b1c8a1SJohn Marino (*nchar)++;
321f5b1c8a1SJohn Marino return 1;
322f5b1c8a1SJohn Marino }
323f5b1c8a1SJohn Marino
324f5b1c8a1SJohn Marino /* Determine size of output as a UTF8 String */
325f5b1c8a1SJohn Marino
326f5b1c8a1SJohn Marino static int
out_utf8(unsigned long value,void * arg)327f5b1c8a1SJohn Marino out_utf8(unsigned long value, void *arg)
328f5b1c8a1SJohn Marino {
329f5b1c8a1SJohn Marino int *outlen;
330f5b1c8a1SJohn Marino int ret;
331f5b1c8a1SJohn Marino
332f5b1c8a1SJohn Marino outlen = arg;
333f5b1c8a1SJohn Marino ret = UTF8_putc(NULL, -1, value);
334f5b1c8a1SJohn Marino if (ret < 0)
335f5b1c8a1SJohn Marino return ret;
336f5b1c8a1SJohn Marino *outlen += ret;
337f5b1c8a1SJohn Marino return 1;
338f5b1c8a1SJohn Marino }
339f5b1c8a1SJohn Marino
340f5b1c8a1SJohn Marino /* Determine the "type" of a string: check each character against a
341f5b1c8a1SJohn Marino * supplied "mask".
342f5b1c8a1SJohn Marino */
343f5b1c8a1SJohn Marino
344f5b1c8a1SJohn Marino static int
type_str(unsigned long value,void * arg)345f5b1c8a1SJohn Marino type_str(unsigned long value, void *arg)
346f5b1c8a1SJohn Marino {
347f5b1c8a1SJohn Marino unsigned long types;
348f5b1c8a1SJohn Marino
349f5b1c8a1SJohn Marino types = *((unsigned long *)arg);
350f5b1c8a1SJohn Marino if ((types & B_ASN1_PRINTABLESTRING) && !is_printable(value))
351f5b1c8a1SJohn Marino types &= ~B_ASN1_PRINTABLESTRING;
352f5b1c8a1SJohn Marino if ((types & B_ASN1_IA5STRING) && (value > 127))
353f5b1c8a1SJohn Marino types &= ~B_ASN1_IA5STRING;
354f5b1c8a1SJohn Marino if ((types & B_ASN1_T61STRING) && (value > 0xff))
355f5b1c8a1SJohn Marino types &= ~B_ASN1_T61STRING;
356f5b1c8a1SJohn Marino if ((types & B_ASN1_BMPSTRING) && (value > 0xffff))
357f5b1c8a1SJohn Marino types &= ~B_ASN1_BMPSTRING;
358f5b1c8a1SJohn Marino if (!types)
359f5b1c8a1SJohn Marino return -1;
360f5b1c8a1SJohn Marino *((unsigned long *)arg) = types;
361f5b1c8a1SJohn Marino return 1;
362f5b1c8a1SJohn Marino }
363f5b1c8a1SJohn Marino
364f5b1c8a1SJohn Marino /* Copy one byte per character ASCII like strings */
365f5b1c8a1SJohn Marino
366f5b1c8a1SJohn Marino static int
cpy_asc(unsigned long value,void * arg)367f5b1c8a1SJohn Marino cpy_asc(unsigned long value, void *arg)
368f5b1c8a1SJohn Marino {
369f5b1c8a1SJohn Marino unsigned char **p, *q;
370f5b1c8a1SJohn Marino
371f5b1c8a1SJohn Marino p = arg;
372f5b1c8a1SJohn Marino q = *p;
373f5b1c8a1SJohn Marino *q = value;
374f5b1c8a1SJohn Marino (*p)++;
375f5b1c8a1SJohn Marino return 1;
376f5b1c8a1SJohn Marino }
377f5b1c8a1SJohn Marino
378f5b1c8a1SJohn Marino /* Copy two byte per character BMPStrings */
379f5b1c8a1SJohn Marino
380f5b1c8a1SJohn Marino static int
cpy_bmp(unsigned long value,void * arg)381f5b1c8a1SJohn Marino cpy_bmp(unsigned long value, void *arg)
382f5b1c8a1SJohn Marino {
383f5b1c8a1SJohn Marino unsigned char **p, *q;
384f5b1c8a1SJohn Marino
385f5b1c8a1SJohn Marino p = arg;
386f5b1c8a1SJohn Marino q = *p;
387f5b1c8a1SJohn Marino *q++ = (value >> 8) & 0xff;
388f5b1c8a1SJohn Marino *q = value & 0xff;
389f5b1c8a1SJohn Marino *p += 2;
390f5b1c8a1SJohn Marino return 1;
391f5b1c8a1SJohn Marino }
392f5b1c8a1SJohn Marino
393f5b1c8a1SJohn Marino /* Copy four byte per character UniversalStrings */
394f5b1c8a1SJohn Marino
395f5b1c8a1SJohn Marino static int
cpy_univ(unsigned long value,void * arg)396f5b1c8a1SJohn Marino cpy_univ(unsigned long value, void *arg)
397f5b1c8a1SJohn Marino {
398f5b1c8a1SJohn Marino unsigned char **p, *q;
399f5b1c8a1SJohn Marino
400f5b1c8a1SJohn Marino p = arg;
401f5b1c8a1SJohn Marino q = *p;
402f5b1c8a1SJohn Marino *q++ = (value >> 24) & 0xff;
403f5b1c8a1SJohn Marino *q++ = (value >> 16) & 0xff;
404f5b1c8a1SJohn Marino *q++ = (value >> 8) & 0xff;
405f5b1c8a1SJohn Marino *q = value & 0xff;
406f5b1c8a1SJohn Marino *p += 4;
407f5b1c8a1SJohn Marino return 1;
408f5b1c8a1SJohn Marino }
409f5b1c8a1SJohn Marino
410f5b1c8a1SJohn Marino /* Copy to a UTF8String */
411f5b1c8a1SJohn Marino
412f5b1c8a1SJohn Marino static int
cpy_utf8(unsigned long value,void * arg)413f5b1c8a1SJohn Marino cpy_utf8(unsigned long value, void *arg)
414f5b1c8a1SJohn Marino {
415f5b1c8a1SJohn Marino unsigned char **p;
416f5b1c8a1SJohn Marino
417f5b1c8a1SJohn Marino int ret;
418f5b1c8a1SJohn Marino p = arg;
419f5b1c8a1SJohn Marino /* We already know there is enough room so pass 0xff as the length */
420f5b1c8a1SJohn Marino ret = UTF8_putc(*p, 0xff, value);
421f5b1c8a1SJohn Marino *p += ret;
422f5b1c8a1SJohn Marino return 1;
423f5b1c8a1SJohn Marino }
424f5b1c8a1SJohn Marino
425f5b1c8a1SJohn Marino /* Return 1 if the character is permitted in a PrintableString */
426f5b1c8a1SJohn Marino static int
is_printable(unsigned long value)427f5b1c8a1SJohn Marino is_printable(unsigned long value)
428f5b1c8a1SJohn Marino {
429f5b1c8a1SJohn Marino int ch;
430f5b1c8a1SJohn Marino
431f5b1c8a1SJohn Marino if (value > 0x7f)
432f5b1c8a1SJohn Marino return 0;
433f5b1c8a1SJohn Marino ch = (int)value;
434f5b1c8a1SJohn Marino
435f5b1c8a1SJohn Marino /* Note: we can't use 'isalnum' because certain accented
436f5b1c8a1SJohn Marino * characters may count as alphanumeric in some environments.
437f5b1c8a1SJohn Marino */
438f5b1c8a1SJohn Marino if ((ch >= 'a') && (ch <= 'z'))
439f5b1c8a1SJohn Marino return 1;
440f5b1c8a1SJohn Marino if ((ch >= 'A') && (ch <= 'Z'))
441f5b1c8a1SJohn Marino return 1;
442f5b1c8a1SJohn Marino if ((ch >= '0') && (ch <= '9'))
443f5b1c8a1SJohn Marino return 1;
444f5b1c8a1SJohn Marino if ((ch == ' ') || strchr("'()+,-./:=?", ch))
445f5b1c8a1SJohn Marino return 1;
446f5b1c8a1SJohn Marino return 0;
447f5b1c8a1SJohn Marino }
448