1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 *
24 * These are additional apis that belong in mbedtls but do not yet exist there.
25 * Alternaives are provided for lws to use that understand additional standard
26 * v3 tls extensions. Error results are simplified to lws style.
27 *
28 * This file includes code taken from mbedtls and modified, and from an as of
29 * 2021-06-11 unaccepted-upstream patch for mbedtls contributed by Gábor Tóth
30 * <toth92g@gmail.com>. Gabor has graciously allowed use of his patch with more
31 * liberal terms but to not complicate matters I provide it here under the same
32 * Apache 2.0 terms as the mbedtls pieces.
33 *
34 * Those original pieces are licensed Apache-2.0 as follows
35 *
36 * Copyright The Mbed TLS Contributors
37 * SPDX-License-Identifier: Apache-2.0
38 *
39 * Licensed under the Apache License, Version 2.0 (the "License"); you may
40 * not use this file except in compliance with the License.
41 * You may obtain a copy of the License at
42 *
43 * http://www.apache.org/licenses/LICENSE-2.0
44 *
45 * Unless required by applicable law or agreed to in writing, software
46 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
47 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
48 * See the License for the specific language governing permissions and
49 * limitations under the License.
50 */
51
52 #include "private-lib-core.h"
53 #include "private-lib-tls-mbedtls.h"
54 #include <mbedtls/oid.h>
55 #include <mbedtls/x509.h>
56
57 /*
58 * This section from mbedtls oid.c
59 */
60
61 typedef struct {
62 mbedtls_oid_descriptor_t descriptor;
63 int ext_type;
64 } oid_x509_ext_t;
65
66 #define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s)
67
68 #define LWS_MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */
69 #define LWS_MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */
70
71 #define LWS_MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0)
72 #define LWS_MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1)
73
74 #define LWS_MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER LWS_MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER
75 #define LWS_MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER LWS_MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER
76
77 #define LWS_MBEDTLS_X509_SAN_OTHER_NAME 0
78 #define LWS_MBEDTLS_X509_SAN_RFC822_NAME 1
79 #define LWS_MBEDTLS_X509_SAN_DNS_NAME 2
80
81 #define LWS_MBEDTLS_ASN1_TAG_CLASS_MASK 0xC0
82 #define LWS_MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F
83
84 static const oid_x509_ext_t oid_x509_ext[] = {
85 { {ADD_LEN( LWS_MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ),
86 "id-ce-subjectKeyIdentifier",
87 "Subject Key Identifier" },
88 LWS_MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER,
89 },
90 { {ADD_LEN( LWS_MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ),
91 "id-ce-authorityKeyIdentifier",
92 "Authority Key Identifier" },
93 LWS_MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER,
94 },
95 { { NULL, 0, NULL, NULL }, 0 },
96 };
97
98 #define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \
99 static const TYPE_T * oid_ ## NAME ## _from_asn1( \
100 const mbedtls_asn1_buf *oid ) \
101 { \
102 const TYPE_T *p = (LIST); \
103 const mbedtls_oid_descriptor_t *cur = \
104 (const mbedtls_oid_descriptor_t *) p; \
105 if( p == NULL || oid == NULL ) return( NULL ); \
106 while( cur->MBEDTLS_PRIVATE(asn1) != NULL ) { \
107 if( cur->MBEDTLS_PRIVATE(asn1_len) == oid->MBEDTLS_PRIVATE(len) && \
108 memcmp( cur->MBEDTLS_PRIVATE(asn1), oid->MBEDTLS_PRIVATE(p), oid->MBEDTLS_PRIVATE(len) ) == 0 ) { \
109 return( p ); \
110 } \
111 p++; \
112 cur = (const mbedtls_oid_descriptor_t *) p; \
113 } \
114 return( NULL ); \
115 }
116
117
118 #define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \
119 int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \
120 { \
121 const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \
122 if (!data) return 1; \
123 *ATTR1 = data->ATTR1; \
124 return 0; \
125 }
126
127 FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext)
128 FN_OID_GET_ATTR1(lws_mbedtls_oid_get_x509_ext_type,
129 oid_x509_ext_t, x509_ext, int, ext_type)
130
131 typedef struct lws_mbedtls_x509_san_other_name
132 {
133 /**
134 * The type_id is an OID as deifned in RFC 5280.
135 * To check the value of the type id, you should use
136 * \p MBEDTLS_OID_CMP with a known OID mbedtls_x509_buf.
137 */
138 mbedtls_x509_buf type_id; /**< The type id. */
139 union
140 {
141 /**
142 * From RFC 4108 section 5:
143 * HardwareModuleName ::= SEQUENCE {
144 * hwType OBJECT IDENTIFIER,
145 * hwSerialNum OCTET STRING }
146 */
147 struct
148 {
149 mbedtls_x509_buf oid; /**< The object identifier. */
150 mbedtls_x509_buf val; /**< The named value. */
151 }
152 hardware_module_name;
153 }
154 value;
155 }
156 lws_mbedtls_x509_san_other_name;
157
158
159 typedef struct lws_mbedtls_x509_subject_alternative_name
160 {
161 int type; /**< The SAN type, value of LWS_MBEDTLS_X509_SAN_XXX. */
162 union {
163 lws_mbedtls_x509_san_other_name other_name; /**< The otherName supported type. */
164 mbedtls_x509_buf unstructured_name; /**< The buffer for the un constructed types. Only dnsName currently supported */
165 }
166 san; /**< A union of the supported SAN types */
167 }
168 lws_mbedtls_x509_subject_alternative_name;
169
170 static int
x509_get_skid(uint8_t ** p,const uint8_t * end,mbedtls_x509_buf * skid)171 x509_get_skid(uint8_t **p, const uint8_t *end, mbedtls_x509_buf *skid)
172 {
173 int ret = 1;
174 size_t len = 0u;
175
176 ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
177 if (ret)
178 return ret;
179
180 skid->MBEDTLS_PRIVATE(len) = len;
181 skid->MBEDTLS_PRIVATE(tag) = MBEDTLS_ASN1_OCTET_STRING;
182 skid->MBEDTLS_PRIVATE(p) = *p;
183 *p += len;
184
185 return *p != end;
186 }
187
188 /*
189 * Names may have multiple allocated segments in a linked-list, when the mbedtls
190 * api mbedtls_x509_get_name() fails, it doesn't clean up any already-allocated
191 * segments, wrongly leaving it to the caller to handle. This helper takes care
192 * of the missing cleaning for allocation error path.
193 *
194 * name.next must be set to NULL by user code before calling ...get_name(...,
195 * &name), since not every error exit sets it and it will contain garbage if
196 * defined on stack as is usual.
197 */
198
199 static void
lws_x509_clean_name(mbedtls_x509_name * name)200 lws_x509_clean_name(mbedtls_x509_name *name)
201 {
202 mbedtls_x509_name *n1;
203
204 if (!name)
205 return;
206
207 n1 = name->MBEDTLS_PRIVATE(next);
208
209 while (n1) {
210 name = n1->MBEDTLS_PRIVATE(next);
211 free(n1);
212 n1 = name;
213 }
214 }
215
216 static int
lws_mbedtls_x509_parse_general_name(const mbedtls_x509_buf * name_buf,lws_mbedtls_x509_subject_alternative_name * name)217 lws_mbedtls_x509_parse_general_name(const mbedtls_x509_buf *name_buf,
218 lws_mbedtls_x509_subject_alternative_name *name)
219 {
220 // mbedtls_x509_name_other_name other_name;
221 uint8_t *bufferPointer, **p, *end;
222 mbedtls_x509_name rfc822Name;
223 int ret;
224
225 switch (name_buf->MBEDTLS_PRIVATE(tag) &
226 (LWS_MBEDTLS_ASN1_TAG_CLASS_MASK |
227 LWS_MBEDTLS_ASN1_TAG_VALUE_MASK)) {
228
229 #if 0
230 case MBEDTLS_ASN1_CONTEXT_SPECIFIC | LWS_MBEDTLS_X509_SAN_OTHER_NAME:
231 ret = x509_get_other_name( name_buf, &other_name );
232 if (ret)
233 return ret;
234
235 memset(name, 0, sizeof(*name));
236 name->type = LWS_MBEDTLS_X509_SAN_OTHER_NAME;
237 memcpy(&name->name.other_name, &other_name, sizeof(other_name));
238 return 0;
239 #endif
240 case MBEDTLS_ASN1_SEQUENCE | LWS_MBEDTLS_X509_SAN_RFC822_NAME:
241
242 bufferPointer = name_buf->MBEDTLS_PRIVATE(p);
243 p = &bufferPointer;
244 end = name_buf->MBEDTLS_PRIVATE(p) +
245 name_buf->MBEDTLS_PRIVATE(len);
246
247 /* The leading ASN1 tag and length has been processed.
248 * Stepping back with 2 bytes, because mbedtls_x509_get_name
249 * expects the beginning of the SET tag */
250 *p = *p - 2;
251
252 rfc822Name.MBEDTLS_PRIVATE(next) = NULL;
253 ret = mbedtls_x509_get_name( p, end, &rfc822Name );
254 if (ret) {
255 lws_x509_clean_name(&rfc822Name);
256 return ret;
257 }
258
259 memset(name, 0, sizeof(*name));
260 name->type = LWS_MBEDTLS_X509_SAN_OTHER_NAME;
261 memcpy(&name->san.other_name,
262 &rfc822Name, sizeof(rfc822Name));
263 return 0;
264
265 case MBEDTLS_ASN1_CONTEXT_SPECIFIC | LWS_MBEDTLS_X509_SAN_DNS_NAME:
266 memset(name, 0, sizeof(*name));
267 name->type = LWS_MBEDTLS_X509_SAN_DNS_NAME;
268
269 memcpy(&name->san.unstructured_name,
270 name_buf, sizeof(*name_buf) );
271 return 0;
272
273 default:
274 return 1;
275 }
276
277 return 1;
278 }
279
280 static int
lws_x509_get_general_names(uint8_t ** p,const uint8_t * end,mbedtls_x509_sequence * name)281 lws_x509_get_general_names(uint8_t **p, const uint8_t *end,
282 mbedtls_x509_sequence *name )
283 {
284 mbedtls_asn1_sequence *cur = name;
285 mbedtls_asn1_buf *buf;
286 size_t len, tag_len;
287 unsigned char tag;
288 int r;
289
290 /* Get main sequence tag */
291 r = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
292 MBEDTLS_ASN1_SEQUENCE);
293 if (r)
294 return r;
295
296 if (*p + len != end)
297 return 1;
298
299 while (*p < end) {
300 lws_mbedtls_x509_subject_alternative_name dnb;
301 memset(&dnb, 0, sizeof(dnb));
302
303 tag = **p;
304 (*p)++;
305
306 r = mbedtls_asn1_get_len(p, end, &tag_len);
307 if (r)
308 return r;
309
310 /* Tag shall be CONTEXT_SPECIFIC or SET */
311 if ((tag & LWS_MBEDTLS_ASN1_TAG_CLASS_MASK) !=
312 MBEDTLS_ASN1_CONTEXT_SPECIFIC &&
313 (tag & (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) !=
314 (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE))
315 return 1;
316
317 /*
318 * Check that the name is structured correctly.
319 */
320 r = lws_mbedtls_x509_parse_general_name(
321 &cur->MBEDTLS_PRIVATE(buf), &dnb);
322 /*
323 * In case the extension is malformed, return an error,
324 * and clear the allocated sequences.
325 */
326 if (r && r != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
327 mbedtls_x509_sequence *seq_cur = name->MBEDTLS_PRIVATE(next);
328 mbedtls_x509_sequence *seq_prv;
329
330 while( seq_cur != NULL ) {
331 seq_prv = seq_cur;
332 seq_cur = seq_cur->MBEDTLS_PRIVATE(next);
333 lws_explicit_bzero(seq_prv, sizeof(*seq_cur));
334 lws_free(seq_prv);
335 }
336
337 name->MBEDTLS_PRIVATE(next) = NULL;
338
339 return r;
340 }
341
342 /* Allocate and assign next pointer */
343 if (cur->MBEDTLS_PRIVATE(buf).MBEDTLS_PRIVATE(p)) {
344 if (cur->MBEDTLS_PRIVATE(next))
345 return 1;
346
347 cur->MBEDTLS_PRIVATE(next) =
348 lws_zalloc(sizeof(*cur), __func__);
349
350 if (!cur->MBEDTLS_PRIVATE(next))
351 return 1;
352
353 cur = cur->MBEDTLS_PRIVATE(next);
354 }
355
356 buf = &(cur->MBEDTLS_PRIVATE(buf));
357 buf->MBEDTLS_PRIVATE(tag) = tag;
358 buf->MBEDTLS_PRIVATE(p) = *p;
359 buf->MBEDTLS_PRIVATE(len) = tag_len;
360
361 *p += buf->MBEDTLS_PRIVATE(len);
362 }
363
364 /* Set final sequence entry's next pointer to NULL */
365 cur->MBEDTLS_PRIVATE(next) = NULL;
366
367 return *p != end;
368 }
369
370 static int
x509_get_akid(uint8_t ** p,uint8_t * end,lws_mbedtls_x509_authority * akid)371 x509_get_akid(uint8_t **p, uint8_t *end, lws_mbedtls_x509_authority *akid)
372 {
373 size_t len = 0u;
374 int r;
375
376 r = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
377 MBEDTLS_ASN1_SEQUENCE);
378 if (r)
379 return r;
380
381 r = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC);
382 if (!r) {
383 akid->keyIdentifier.MBEDTLS_PRIVATE(len) = len;
384 akid->keyIdentifier.MBEDTLS_PRIVATE(p) = *p;
385 akid->keyIdentifier.MBEDTLS_PRIVATE(tag) = MBEDTLS_ASN1_OCTET_STRING;
386
387 *p += len;
388 }
389
390 if (*p < end) {
391 /* Getting authorityCertIssuer using the required specific
392 * class tag [1] */
393 r = mbedtls_asn1_get_tag(p, end, &len,
394 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
395 MBEDTLS_ASN1_CONSTRUCTED | 1 );
396 if (!r) {
397 /* Getting directoryName using the required specific
398 * class tag [4] */
399 r = mbedtls_asn1_get_tag(p, end, &len,
400 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
401 MBEDTLS_ASN1_CONSTRUCTED | 4);
402 if (r)
403 return(r);
404
405 /* "end" also includes the CertSerialNumber field
406 * so "len" shall be used */
407 r = lws_x509_get_general_names(p, (*p + len),
408 &akid->authorityCertIssuer);
409 }
410 }
411
412 if (*p < end) {
413 r = mbedtls_asn1_get_tag(p, end, &len,
414 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
415 MBEDTLS_ASN1_INTEGER );
416 if (r)
417 return r;
418
419 akid->authorityCertSerialNumber.MBEDTLS_PRIVATE(len) = len;
420 akid->authorityCertSerialNumber.MBEDTLS_PRIVATE(p) = *p;
421 akid->authorityCertSerialNumber.MBEDTLS_PRIVATE(tag) = MBEDTLS_ASN1_OCTET_STRING;
422 *p += len;
423 }
424
425 return *p != end;
426 }
427
428 /*
429 * Work around lack of this in mbedtls... we don't need to do sanity checks
430 * sanity checks because they will be done at x509 validation time
431 */
432
433 int
lws_x509_get_crt_ext(mbedtls_x509_crt * crt,mbedtls_x509_buf * skid,lws_mbedtls_x509_authority * akid)434 lws_x509_get_crt_ext(mbedtls_x509_crt *crt, mbedtls_x509_buf *skid,
435 lws_mbedtls_x509_authority *akid)
436 {
437 uint8_t *p = crt->MBEDTLS_PRIVATE(v3_ext).MBEDTLS_PRIVATE(p),
438 *end_ext_data, *end_ext_octet;
439 const uint8_t *end = p + crt->MBEDTLS_PRIVATE(v3_ext).MBEDTLS_PRIVATE(len);
440 size_t len;
441 int r = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
442 MBEDTLS_ASN1_SEQUENCE);
443 if (r)
444 return r;
445
446 while (p < end) {
447 mbedtls_x509_buf extn_oid = { 0, 0, NULL };
448 int is_critical = 0; /* DEFAULT FALSE */
449 int ext_type = 0;
450
451 r = mbedtls_asn1_get_tag(&p, end, &len,
452 MBEDTLS_ASN1_CONSTRUCTED |
453 MBEDTLS_ASN1_SEQUENCE);
454 if (r)
455 return r;
456
457 end_ext_data = p + len;
458
459 /* Get extension ID */
460 r = mbedtls_asn1_get_tag(&p, end_ext_data, &extn_oid.MBEDTLS_PRIVATE(len),
461 MBEDTLS_ASN1_OID);
462 if (r)
463 return r;
464
465 extn_oid.MBEDTLS_PRIVATE(tag) = MBEDTLS_ASN1_OID;
466 extn_oid.MBEDTLS_PRIVATE(p) = p;
467 p += extn_oid.MBEDTLS_PRIVATE(len);
468
469 /* Get optional critical */
470 r = mbedtls_asn1_get_bool(&p, end_ext_data, &is_critical);
471 if (r && r != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)
472 return r;
473
474 /* Data should be octet string type */
475 r = mbedtls_asn1_get_tag(&p, end_ext_data, &len,
476 MBEDTLS_ASN1_OCTET_STRING);
477 if (r)
478 return r;
479
480 end_ext_octet = p + len;
481
482 if (end_ext_octet != end_ext_data)
483 return 1;
484
485 r = lws_mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type);
486 if (r) {
487 p = end_ext_octet;
488 continue;
489 }
490
491 switch (ext_type) {
492 case LWS_MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER:
493 /* Parse subject key identifier */
494 r = x509_get_skid(&p, end_ext_data, skid);
495 if (r)
496 return r;
497 break;
498
499 case LWS_MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER:
500 /* Parse authority key identifier */
501 r = x509_get_akid(&p, end_ext_octet, akid);
502 if (r)
503 return r;
504 break;
505
506 default:
507 p = end_ext_octet;
508 }
509 }
510
511 return 0;
512 }
513