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