1 /* Copyright (C) 1995-1998 Eric Young ([email protected])
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young ([email protected]).
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 ([email protected]).
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 ([email protected])"
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 ([email protected])"
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 <limits.h>
60 #include <string.h>
61
62 #include <openssl/bytestring.h>
63 #include <openssl/err.h>
64 #include <openssl/mem.h>
65
66 #include "../bytestring/internal.h"
67 #include "internal.h"
68
69 // These functions take a string in UTF8, ASCII or multibyte form and a mask
70 // of permissible ASN1 string types. It then works out the minimal type
71 // (using the order Printable < IA5 < T61 < BMP < Universal < UTF8) and
72 // creates a string of the correct type with the supplied data. Yes this is
73 // horrible: it has to be :-( The 'ncopy' form checks minimum and maximum
74 // size limits too.
75
ASN1_mbstring_copy(ASN1_STRING ** out,const unsigned char * in,ossl_ssize_t len,int inform,unsigned long mask)76 int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in,
77 ossl_ssize_t len, int inform, unsigned long mask) {
78 return ASN1_mbstring_ncopy(out, in, len, inform, mask, /*minsize=*/0,
79 /*maxsize=*/0);
80 }
81
OPENSSL_DECLARE_ERROR_REASON(ASN1,INVALID_BMPSTRING)82 OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_BMPSTRING)
83 OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_UNIVERSALSTRING)
84 OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_UTF8STRING)
85
86 int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in,
87 ossl_ssize_t len, int inform, unsigned long mask,
88 ossl_ssize_t minsize, ossl_ssize_t maxsize) {
89 if (len == -1) {
90 len = strlen((const char *)in);
91 }
92 if (!mask) {
93 mask = DIRSTRING_TYPE;
94 }
95
96 int (*decode_func)(CBS *, uint32_t *);
97 int error;
98 switch (inform) {
99 case MBSTRING_BMP:
100 decode_func = CBS_get_ucs2_be;
101 error = ASN1_R_INVALID_BMPSTRING;
102 break;
103
104 case MBSTRING_UNIV:
105 decode_func = CBS_get_utf32_be;
106 error = ASN1_R_INVALID_UNIVERSALSTRING;
107 break;
108
109 case MBSTRING_UTF8:
110 decode_func = CBS_get_utf8;
111 error = ASN1_R_INVALID_UTF8STRING;
112 break;
113
114 case MBSTRING_ASC:
115 decode_func = CBS_get_latin1;
116 error = ERR_R_INTERNAL_ERROR; // Latin-1 inputs are never invalid.
117 break;
118
119 default:
120 OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
121 return -1;
122 }
123
124 // Check |minsize| and |maxsize| and work out the minimal type, if any.
125 CBS cbs;
126 CBS_init(&cbs, in, len);
127 size_t utf8_len = 0, nchar = 0;
128 while (CBS_len(&cbs) != 0) {
129 uint32_t c;
130 if (!decode_func(&cbs, &c)) {
131 OPENSSL_PUT_ERROR(ASN1, error);
132 return -1;
133 }
134 if (nchar == 0 && (inform == MBSTRING_BMP || inform == MBSTRING_UNIV) &&
135 c == 0xfeff) {
136 // Reject byte-order mark. We could drop it but that would mean
137 // adding ambiguity around whether a BOM was included or not when
138 // matching strings.
139 //
140 // For a little-endian UCS-2 string, the BOM will appear as 0xfffe
141 // and will be rejected as noncharacter, below.
142 OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
143 return -1;
144 }
145
146 // Update which output formats are still possible.
147 if ((mask & B_ASN1_PRINTABLESTRING) && !asn1_is_printable(c)) {
148 mask &= ~B_ASN1_PRINTABLESTRING;
149 }
150 if ((mask & B_ASN1_IA5STRING) && (c > 127)) {
151 mask &= ~B_ASN1_IA5STRING;
152 }
153 if ((mask & B_ASN1_T61STRING) && (c > 0xff)) {
154 mask &= ~B_ASN1_T61STRING;
155 }
156 if ((mask & B_ASN1_BMPSTRING) && (c > 0xffff)) {
157 mask &= ~B_ASN1_BMPSTRING;
158 }
159 if (!mask) {
160 OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
161 return -1;
162 }
163
164 nchar++;
165 utf8_len += CBB_get_utf8_len(c);
166 if (maxsize > 0 && nchar > (size_t)maxsize) {
167 OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
168 ERR_add_error_dataf("maxsize=%zu", (size_t)maxsize);
169 return -1;
170 }
171 }
172
173 if (minsize > 0 && nchar < (size_t)minsize) {
174 OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
175 ERR_add_error_dataf("minsize=%zu", (size_t)minsize);
176 return -1;
177 }
178
179 // Now work out output format and string type
180 int str_type;
181 int (*encode_func)(CBB *, uint32_t) = CBB_add_latin1;
182 size_t size_estimate = nchar;
183 int outform = MBSTRING_ASC;
184 if (mask & B_ASN1_PRINTABLESTRING) {
185 str_type = V_ASN1_PRINTABLESTRING;
186 } else if (mask & B_ASN1_IA5STRING) {
187 str_type = V_ASN1_IA5STRING;
188 } else if (mask & B_ASN1_T61STRING) {
189 str_type = V_ASN1_T61STRING;
190 } else if (mask & B_ASN1_BMPSTRING) {
191 str_type = V_ASN1_BMPSTRING;
192 outform = MBSTRING_BMP;
193 encode_func = CBB_add_ucs2_be;
194 size_estimate = 2 * nchar;
195 } else if (mask & B_ASN1_UNIVERSALSTRING) {
196 str_type = V_ASN1_UNIVERSALSTRING;
197 encode_func = CBB_add_utf32_be;
198 size_estimate = 4 * nchar;
199 outform = MBSTRING_UNIV;
200 } else if (mask & B_ASN1_UTF8STRING) {
201 str_type = V_ASN1_UTF8STRING;
202 outform = MBSTRING_UTF8;
203 encode_func = CBB_add_utf8;
204 size_estimate = utf8_len;
205 } else {
206 OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
207 return -1;
208 }
209
210 if (!out) {
211 return str_type;
212 }
213
214 int free_dest = 0;
215 ASN1_STRING *dest;
216 if (*out) {
217 dest = *out;
218 } else {
219 free_dest = 1;
220 dest = ASN1_STRING_type_new(str_type);
221 if (!dest) {
222 return -1;
223 }
224 }
225
226 CBB cbb;
227 CBB_zero(&cbb);
228 // If both the same type just copy across
229 if (inform == outform) {
230 if (!ASN1_STRING_set(dest, in, len)) {
231 goto err;
232 }
233 dest->type = str_type;
234 *out = dest;
235 return str_type;
236 }
237 if (!CBB_init(&cbb, size_estimate + 1)) {
238 goto err;
239 }
240 CBS_init(&cbs, in, len);
241 while (CBS_len(&cbs) != 0) {
242 uint32_t c;
243 if (!decode_func(&cbs, &c) || !encode_func(&cbb, c)) {
244 OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR);
245 goto err;
246 }
247 }
248 uint8_t *data = NULL;
249 size_t data_len;
250 if (// OpenSSL historically NUL-terminated this value with a single byte,
251 // even for |MBSTRING_BMP| and |MBSTRING_UNIV|.
252 !CBB_add_u8(&cbb, 0) || !CBB_finish(&cbb, &data, &data_len) ||
253 data_len < 1 || data_len > INT_MAX) {
254 OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR);
255 OPENSSL_free(data);
256 goto err;
257 }
258 dest->type = str_type;
259 ASN1_STRING_set0(dest, data, (int)data_len - 1);
260 *out = dest;
261 return str_type;
262
263 err:
264 if (free_dest) {
265 ASN1_STRING_free(dest);
266 }
267 CBB_cleanup(&cbb);
268 return -1;
269 }
270
asn1_is_printable(uint32_t value)271 int asn1_is_printable(uint32_t value) {
272 if (value > 0x7f) {
273 return 0;
274 }
275 return OPENSSL_isalnum(value) || //
276 value == ' ' || value == '\'' || value == '(' || value == ')' ||
277 value == '+' || value == ',' || value == '-' || value == '.' ||
278 value == '/' || value == ':' || value == '=' || value == '?';
279 }
280