1 // Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <openssl/asn1.h>
16
17 #include <limits.h>
18 #include <string.h>
19
20 #include <openssl/bytestring.h>
21 #include <openssl/err.h>
22 #include <openssl/mem.h>
23
24 #include "../bytestring/internal.h"
25 #include "internal.h"
26
27 // These functions take a string in UTF8, ASCII or multibyte form and a mask
28 // of permissible ASN1 string types. It then works out the minimal type
29 // (using the order Printable < IA5 < T61 < BMP < Universal < UTF8) and
30 // creates a string of the correct type with the supplied data. Yes this is
31 // horrible: it has to be :-( The 'ncopy' form checks minimum and maximum
32 // size limits too.
33
ASN1_mbstring_copy(ASN1_STRING ** out,const unsigned char * in,ossl_ssize_t len,int inform,unsigned long mask)34 int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in,
35 ossl_ssize_t len, int inform, unsigned long mask) {
36 return ASN1_mbstring_ncopy(out, in, len, inform, mask, /*minsize=*/0,
37 /*maxsize=*/0);
38 }
39
OPENSSL_DECLARE_ERROR_REASON(ASN1,INVALID_BMPSTRING)40 OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_BMPSTRING)
41 OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_UNIVERSALSTRING)
42 OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_UTF8STRING)
43
44 int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in,
45 ossl_ssize_t len, int inform, unsigned long mask,
46 ossl_ssize_t minsize, ossl_ssize_t maxsize) {
47 if (len == -1) {
48 len = strlen((const char *)in);
49 }
50 if (!mask) {
51 mask = DIRSTRING_TYPE;
52 }
53
54 int (*decode_func)(CBS *, uint32_t *);
55 int error;
56 switch (inform) {
57 case MBSTRING_BMP:
58 decode_func = CBS_get_ucs2_be;
59 error = ASN1_R_INVALID_BMPSTRING;
60 break;
61
62 case MBSTRING_UNIV:
63 decode_func = CBS_get_utf32_be;
64 error = ASN1_R_INVALID_UNIVERSALSTRING;
65 break;
66
67 case MBSTRING_UTF8:
68 decode_func = CBS_get_utf8;
69 error = ASN1_R_INVALID_UTF8STRING;
70 break;
71
72 case MBSTRING_ASC:
73 decode_func = CBS_get_latin1;
74 error = ERR_R_INTERNAL_ERROR; // Latin-1 inputs are never invalid.
75 break;
76
77 default:
78 OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
79 return -1;
80 }
81
82 // Check |minsize| and |maxsize| and work out the minimal type, if any.
83 CBS cbs;
84 CBS_init(&cbs, in, len);
85 size_t utf8_len = 0, nchar = 0;
86 while (CBS_len(&cbs) != 0) {
87 uint32_t c;
88 if (!decode_func(&cbs, &c)) {
89 OPENSSL_PUT_ERROR(ASN1, error);
90 return -1;
91 }
92 if (nchar == 0 && (inform == MBSTRING_BMP || inform == MBSTRING_UNIV) &&
93 c == 0xfeff) {
94 // Reject byte-order mark. We could drop it but that would mean
95 // adding ambiguity around whether a BOM was included or not when
96 // matching strings.
97 //
98 // For a little-endian UCS-2 string, the BOM will appear as 0xfffe
99 // and will be rejected as noncharacter, below.
100 OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
101 return -1;
102 }
103
104 // Update which output formats are still possible.
105 if ((mask & B_ASN1_PRINTABLESTRING) && !asn1_is_printable(c)) {
106 mask &= ~B_ASN1_PRINTABLESTRING;
107 }
108 if ((mask & B_ASN1_IA5STRING) && (c > 127)) {
109 mask &= ~B_ASN1_IA5STRING;
110 }
111 if ((mask & B_ASN1_T61STRING) && (c > 0xff)) {
112 mask &= ~B_ASN1_T61STRING;
113 }
114 if ((mask & B_ASN1_BMPSTRING) && (c > 0xffff)) {
115 mask &= ~B_ASN1_BMPSTRING;
116 }
117 if (!mask) {
118 OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
119 return -1;
120 }
121
122 nchar++;
123 utf8_len += CBB_get_utf8_len(c);
124 if (maxsize > 0 && nchar > (size_t)maxsize) {
125 OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
126 ERR_add_error_dataf("maxsize=%zu", (size_t)maxsize);
127 return -1;
128 }
129 }
130
131 if (minsize > 0 && nchar < (size_t)minsize) {
132 OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
133 ERR_add_error_dataf("minsize=%zu", (size_t)minsize);
134 return -1;
135 }
136
137 // Now work out output format and string type
138 int str_type;
139 int (*encode_func)(CBB *, uint32_t) = CBB_add_latin1;
140 size_t size_estimate = nchar;
141 int outform = MBSTRING_ASC;
142 if (mask & B_ASN1_PRINTABLESTRING) {
143 str_type = V_ASN1_PRINTABLESTRING;
144 } else if (mask & B_ASN1_IA5STRING) {
145 str_type = V_ASN1_IA5STRING;
146 } else if (mask & B_ASN1_T61STRING) {
147 str_type = V_ASN1_T61STRING;
148 } else if (mask & B_ASN1_BMPSTRING) {
149 str_type = V_ASN1_BMPSTRING;
150 outform = MBSTRING_BMP;
151 encode_func = CBB_add_ucs2_be;
152 size_estimate = 2 * nchar;
153 } else if (mask & B_ASN1_UNIVERSALSTRING) {
154 str_type = V_ASN1_UNIVERSALSTRING;
155 encode_func = CBB_add_utf32_be;
156 size_estimate = 4 * nchar;
157 outform = MBSTRING_UNIV;
158 } else if (mask & B_ASN1_UTF8STRING) {
159 str_type = V_ASN1_UTF8STRING;
160 outform = MBSTRING_UTF8;
161 encode_func = CBB_add_utf8;
162 size_estimate = utf8_len;
163 } else {
164 OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
165 return -1;
166 }
167
168 if (!out) {
169 return str_type;
170 }
171
172 int free_dest = 0;
173 ASN1_STRING *dest;
174 if (*out) {
175 dest = *out;
176 } else {
177 free_dest = 1;
178 dest = ASN1_STRING_type_new(str_type);
179 if (!dest) {
180 return -1;
181 }
182 }
183
184 CBB cbb;
185 CBB_zero(&cbb);
186 // If both the same type just copy across
187 uint8_t *data = NULL;
188 size_t data_len = 0;
189 if (inform == outform) {
190 if (!ASN1_STRING_set(dest, in, len)) {
191 goto err;
192 }
193 dest->type = str_type;
194 *out = dest;
195 return str_type;
196 }
197 if (!CBB_init(&cbb, size_estimate + 1)) {
198 goto err;
199 }
200 CBS_init(&cbs, in, len);
201 while (CBS_len(&cbs) != 0) {
202 uint32_t c;
203 if (!decode_func(&cbs, &c) || !encode_func(&cbb, c)) {
204 OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR);
205 goto err;
206 }
207 }
208 if (/* OpenSSL historically NUL-terminated this value with a single byte,
209 * even for |MBSTRING_BMP| and |MBSTRING_UNIV|. */
210 !CBB_add_u8(&cbb, 0) || //
211 !CBB_finish(&cbb, &data, &data_len) || //
212 data_len < 1 || //
213 data_len > INT_MAX) {
214 OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR);
215 OPENSSL_free(data);
216 goto err;
217 }
218 dest->type = str_type;
219 ASN1_STRING_set0(dest, data, (int)data_len - 1);
220 *out = dest;
221 return str_type;
222
223 err:
224 if (free_dest) {
225 ASN1_STRING_free(dest);
226 }
227 CBB_cleanup(&cbb);
228 return -1;
229 }
230
asn1_is_printable(uint32_t value)231 int asn1_is_printable(uint32_t value) {
232 if (value > 0x7f) {
233 return 0;
234 }
235 return OPENSSL_isalnum(value) || //
236 value == ' ' || value == '\'' || value == '(' || value == ')' ||
237 value == '+' || value == ',' || value == '-' || value == '.' ||
238 value == '/' || value == ':' || value == '=' || value == '?';
239 }
240