• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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