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