blob: 80cfac44e064a4c94916e5f5cce47760fe8123fe [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* 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
David Benjaminae153bb2018-05-10 16:23:03 -040059#include <limits.h>
Adam Langley2b2d66d2015-01-30 17:08:37 -080060#include <string.h>
61
David Benjaminae153bb2018-05-10 16:23:03 -040062#include <openssl/bytestring.h>
Adam Langley95c29f32014-06-20 12:00:00 -070063#include <openssl/err.h>
64#include <openssl/mem.h>
65
David Benjaminae153bb2018-05-10 16:23:03 -040066#include "../bytestring/internal.h"
David Benjamin260a10c2022-06-16 13:58:28 -040067#include "internal.h"
David Benjamin2b63add2017-12-04 17:05:54 -050068
David Benjamin46350482022-06-16 14:03:12 -040069// 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.
Adam Langley95c29f32014-06-20 12:00:00 -070075
76int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
David Benjamin260a10c2022-06-16 13:58:28 -040077 int inform, unsigned long mask) {
78 return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
Adam Langley95c29f32014-06-20 12:00:00 -070079}
80
David Benjaminae153bb2018-05-10 16:23:03 -040081OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_BMPSTRING)
82OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_UNIVERSALSTRING)
83OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_UTF8STRING)
84
Adam Langley95c29f32014-06-20 12:00:00 -070085int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
David Benjamin260a10c2022-06-16 13:58:28 -040086 int inform, unsigned long mask, long minsize,
87 long maxsize) {
David Benjaminc0b87a02022-06-16 14:02:15 -040088 if (len == -1) {
David Benjamin260a10c2022-06-16 13:58:28 -040089 len = strlen((const char *)in);
David Benjaminc0b87a02022-06-16 14:02:15 -040090 }
91 if (!mask) {
David Benjamin260a10c2022-06-16 13:58:28 -040092 mask = DIRSTRING_TYPE;
David Benjaminc0b87a02022-06-16 14:02:15 -040093 }
Adam Langley95c29f32014-06-20 12:00:00 -070094
David Benjamin260a10c2022-06-16 13:58:28 -040095 int (*decode_func)(CBS *, uint32_t *);
96 int error;
97 switch (inform) {
Adam Langley57707c72016-01-14 11:25:12 -080098 case MBSTRING_BMP:
David Benjamin260a10c2022-06-16 13:58:28 -040099 decode_func = cbs_get_ucs2_be;
100 error = ASN1_R_INVALID_BMPSTRING;
101 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700102
Adam Langley57707c72016-01-14 11:25:12 -0800103 case MBSTRING_UNIV:
David Benjamin260a10c2022-06-16 13:58:28 -0400104 decode_func = cbs_get_utf32_be;
105 error = ASN1_R_INVALID_UNIVERSALSTRING;
106 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700107
Adam Langley57707c72016-01-14 11:25:12 -0800108 case MBSTRING_UTF8:
David Benjamin260a10c2022-06-16 13:58:28 -0400109 decode_func = cbs_get_utf8;
110 error = ASN1_R_INVALID_UTF8STRING;
111 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700112
Adam Langley57707c72016-01-14 11:25:12 -0800113 case MBSTRING_ASC:
David Benjamin260a10c2022-06-16 13:58:28 -0400114 decode_func = cbs_get_latin1;
115 error = ERR_R_INTERNAL_ERROR; // Latin-1 inputs are never invalid.
116 break;
Adam Langley95c29f32014-06-20 12:00:00 -0700117
Adam Langley57707c72016-01-14 11:25:12 -0800118 default:
David Benjamin260a10c2022-06-16 13:58:28 -0400119 OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
120 return -1;
121 }
122
David Benjamin46350482022-06-16 14:03:12 -0400123 // Check |minsize| and |maxsize| and work out the minimal type, if any.
David Benjamin260a10c2022-06-16 13:58:28 -0400124 CBS cbs;
125 CBS_init(&cbs, in, len);
David Benjaminf7d37fb2023-02-04 19:45:04 -0500126 size_t utf8_len = 0, nchar = 0;
David Benjamin260a10c2022-06-16 13:58:28 -0400127 while (CBS_len(&cbs) != 0) {
128 uint32_t c;
129 if (!decode_func(&cbs, &c)) {
130 OPENSSL_PUT_ERROR(ASN1, error);
131 return -1;
132 }
133 if (nchar == 0 && (inform == MBSTRING_BMP || inform == MBSTRING_UNIV) &&
134 c == 0xfeff) {
David Benjamin46350482022-06-16 14:03:12 -0400135 // Reject byte-order mark. We could drop it but that would mean
136 // adding ambiguity around whether a BOM was included or not when
137 // matching strings.
138 //
139 // For a little-endian UCS-2 string, the BOM will appear as 0xfffe
140 // and will be rejected as noncharacter, below.
David Benjamin260a10c2022-06-16 13:58:28 -0400141 OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
142 return -1;
Adam Langley57707c72016-01-14 11:25:12 -0800143 }
Adam Langley95c29f32014-06-20 12:00:00 -0700144
David Benjamin46350482022-06-16 14:03:12 -0400145 // Update which output formats are still possible.
David Benjamin260a10c2022-06-16 13:58:28 -0400146 if ((mask & B_ASN1_PRINTABLESTRING) && !asn1_is_printable(c)) {
147 mask &= ~B_ASN1_PRINTABLESTRING;
148 }
149 if ((mask & B_ASN1_IA5STRING) && (c > 127)) {
150 mask &= ~B_ASN1_IA5STRING;
151 }
152 if ((mask & B_ASN1_T61STRING) && (c > 0xff)) {
153 mask &= ~B_ASN1_T61STRING;
154 }
155 if ((mask & B_ASN1_BMPSTRING) && (c > 0xffff)) {
156 mask &= ~B_ASN1_BMPSTRING;
157 }
158 if (!mask) {
159 OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
160 return -1;
David Benjaminae153bb2018-05-10 16:23:03 -0400161 }
162
David Benjamin260a10c2022-06-16 13:58:28 -0400163 nchar++;
164 utf8_len += cbb_get_utf8_len(c);
David Benjamin95804242023-02-09 15:51:35 -0500165 if (maxsize > 0 && nchar > (size_t)maxsize) {
166 OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
167 ERR_add_error_dataf("maxsize=%ld", maxsize);
168 return -1;
169 }
David Benjamin260a10c2022-06-16 13:58:28 -0400170 }
Adam Langley95c29f32014-06-20 12:00:00 -0700171
David Benjamin260a10c2022-06-16 13:58:28 -0400172 if (minsize > 0 && nchar < (size_t)minsize) {
173 OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
David Benjamin95804242023-02-09 15:51:35 -0500174 ERR_add_error_dataf("minsize=%ld", minsize);
David Benjamin260a10c2022-06-16 13:58:28 -0400175 return -1;
176 }
177
David Benjamin46350482022-06-16 14:03:12 -0400178 // Now work out output format and string type
David Benjaminf7d37fb2023-02-04 19:45:04 -0500179 int str_type;
David Benjamin260a10c2022-06-16 13:58:28 -0400180 int (*encode_func)(CBB *, uint32_t) = cbb_add_latin1;
181 size_t size_estimate = nchar;
182 int outform = MBSTRING_ASC;
183 if (mask & B_ASN1_PRINTABLESTRING) {
184 str_type = V_ASN1_PRINTABLESTRING;
185 } else if (mask & B_ASN1_IA5STRING) {
186 str_type = V_ASN1_IA5STRING;
187 } else if (mask & B_ASN1_T61STRING) {
188 str_type = V_ASN1_T61STRING;
189 } else if (mask & B_ASN1_BMPSTRING) {
190 str_type = V_ASN1_BMPSTRING;
191 outform = MBSTRING_BMP;
192 encode_func = cbb_add_ucs2_be;
193 size_estimate = 2 * nchar;
194 } else if (mask & B_ASN1_UNIVERSALSTRING) {
195 str_type = V_ASN1_UNIVERSALSTRING;
196 encode_func = cbb_add_utf32_be;
197 size_estimate = 4 * nchar;
198 outform = MBSTRING_UNIV;
199 } else if (mask & B_ASN1_UTF8STRING) {
200 str_type = V_ASN1_UTF8STRING;
201 outform = MBSTRING_UTF8;
202 encode_func = cbb_add_utf8;
203 size_estimate = utf8_len;
204 } else {
205 OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
206 return -1;
207 }
208
David Benjaminc0b87a02022-06-16 14:02:15 -0400209 if (!out) {
David Benjamin260a10c2022-06-16 13:58:28 -0400210 return str_type;
David Benjaminc0b87a02022-06-16 14:02:15 -0400211 }
David Benjaminf7d37fb2023-02-04 19:45:04 -0500212
213 int free_dest = 0;
214 ASN1_STRING *dest;
David Benjamin260a10c2022-06-16 13:58:28 -0400215 if (*out) {
David Benjamin260a10c2022-06-16 13:58:28 -0400216 dest = *out;
David Benjamin260a10c2022-06-16 13:58:28 -0400217 } else {
David Benjaminf7d37fb2023-02-04 19:45:04 -0500218 free_dest = 1;
David Benjamin260a10c2022-06-16 13:58:28 -0400219 dest = ASN1_STRING_type_new(str_type);
220 if (!dest) {
David Benjamin260a10c2022-06-16 13:58:28 -0400221 return -1;
222 }
David Benjamin260a10c2022-06-16 13:58:28 -0400223 }
224
David Benjamin46350482022-06-16 14:03:12 -0400225 // If both the same type just copy across
David Benjamin260a10c2022-06-16 13:58:28 -0400226 if (inform == outform) {
227 if (!ASN1_STRING_set(dest, in, len)) {
David Benjaminf7d37fb2023-02-04 19:45:04 -0500228 goto err;
David Benjamin260a10c2022-06-16 13:58:28 -0400229 }
David Benjaminf7d37fb2023-02-04 19:45:04 -0500230 dest->type = str_type;
231 *out = dest;
David Benjamin260a10c2022-06-16 13:58:28 -0400232 return str_type;
233 }
234
235 CBB cbb;
236 if (!CBB_init(&cbb, size_estimate + 1)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400237 goto err;
238 }
239 CBS_init(&cbs, in, len);
240 while (CBS_len(&cbs) != 0) {
241 uint32_t c;
242 if (!decode_func(&cbs, &c) || !encode_func(&cbb, c)) {
243 OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR);
244 goto err;
245 }
246 }
247 uint8_t *data = NULL;
248 size_t data_len;
David Benjamin46350482022-06-16 14:03:12 -0400249 if (// OpenSSL historically NUL-terminated this value with a single byte,
250 // even for |MBSTRING_BMP| and |MBSTRING_UNIV|.
David Benjamin260a10c2022-06-16 13:58:28 -0400251 !CBB_add_u8(&cbb, 0) || !CBB_finish(&cbb, &data, &data_len) ||
252 data_len < 1 || data_len > INT_MAX) {
253 OPENSSL_PUT_ERROR(ASN1, ERR_R_INTERNAL_ERROR);
254 OPENSSL_free(data);
255 goto err;
256 }
David Benjaminf7d37fb2023-02-04 19:45:04 -0500257 dest->type = str_type;
258 ASN1_STRING_set0(dest, data, (int)data_len - 1);
259 *out = dest;
David Benjamin260a10c2022-06-16 13:58:28 -0400260 return str_type;
261
262err:
David Benjaminf7d37fb2023-02-04 19:45:04 -0500263 if (free_dest) {
David Benjamin260a10c2022-06-16 13:58:28 -0400264 ASN1_STRING_free(dest);
David Benjaminc0b87a02022-06-16 14:02:15 -0400265 }
David Benjamin260a10c2022-06-16 13:58:28 -0400266 CBB_cleanup(&cbb);
267 return -1;
Adam Langley95c29f32014-06-20 12:00:00 -0700268}
269
David Benjamin260a10c2022-06-16 13:58:28 -0400270int asn1_is_printable(uint32_t value) {
271 if (value > 0x7f) {
272 return 0;
273 }
Bob Beck00c70b82023-02-01 12:41:49 -0700274 return OPENSSL_isalnum(value) || //
David Benjamin260a10c2022-06-16 13:58:28 -0400275 value == ' ' || value == '\'' || value == '(' || value == ')' ||
276 value == '+' || value == ',' || value == '-' || value == '.' ||
277 value == '/' || value == ':' || value == '=' || value == '?';
Adam Langley95c29f32014-06-20 12:00:00 -0700278}