1/*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2022 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
61typedef 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
84static 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_V30_ONLY(len) && \
108                memcmp( cur->MBEDTLS_PRIVATE(asn1), oid->MBEDTLS_PRIVATE_V30_ONLY(p), oid->MBEDTLS_PRIVATE_V30_ONLY(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) \
119int 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
127FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext)
128FN_OID_GET_ATTR1(lws_mbedtls_oid_get_x509_ext_type,
129		 oid_x509_ext_t, x509_ext, int, ext_type)
130
131typedef 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}
156lws_mbedtls_x509_san_other_name;
157
158
159typedef 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}
168lws_mbedtls_x509_subject_alternative_name;
169
170static int
171x509_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_V30_ONLY(len)	= len;
181	skid->MBEDTLS_PRIVATE_V30_ONLY(tag)	= MBEDTLS_ASN1_OCTET_STRING;
182	skid->MBEDTLS_PRIVATE_V30_ONLY(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
199static void
200lws_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_V30_ONLY(next);
208
209	while (n1) {
210		name = n1->MBEDTLS_PRIVATE_V30_ONLY(next);
211		free(n1);
212		n1 = name;
213	}
214}
215
216static int
217lws_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_V30_ONLY(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_V30_ONLY(p);
243		p = &bufferPointer;
244		end = name_buf->MBEDTLS_PRIVATE_V30_ONLY(p) +
245		      name_buf->MBEDTLS_PRIVATE_V30_ONLY(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_V30_ONLY(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
280static int
281lws_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_V30_ONLY(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_V30_ONLY(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_V30_ONLY(next);
333				lws_explicit_bzero(seq_prv, sizeof(*seq_cur));
334				lws_free(seq_prv);
335			}
336
337			name->MBEDTLS_PRIVATE_V30_ONLY(next) = NULL;
338
339			return r;
340		}
341
342		/* Allocate and assign next pointer */
343		if (cur->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(p)) {
344			if (cur->MBEDTLS_PRIVATE_V30_ONLY(next))
345				return 1;
346
347			cur->MBEDTLS_PRIVATE_V30_ONLY(next) =
348					lws_zalloc(sizeof(*cur), __func__);
349
350			if (!cur->MBEDTLS_PRIVATE_V30_ONLY(next))
351				return 1;
352
353			cur = cur->MBEDTLS_PRIVATE_V30_ONLY(next);
354		}
355
356		buf = &(cur->MBEDTLS_PRIVATE_V30_ONLY(buf));
357		buf->MBEDTLS_PRIVATE_V30_ONLY(tag) = tag;
358		buf->MBEDTLS_PRIVATE_V30_ONLY(p) = *p;
359		buf->MBEDTLS_PRIVATE_V30_ONLY(len) = tag_len;
360
361		*p += buf->MBEDTLS_PRIVATE_V30_ONLY(len);
362	}
363
364	/* Set final sequence entry's next pointer to NULL */
365	cur->MBEDTLS_PRIVATE_V30_ONLY(next) = NULL;
366
367	return *p != end;
368}
369
370static int
371x509_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_V30_ONLY(len) = len;
384		akid->keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(p) = *p;
385		akid->keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(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_V30_ONLY(len) = len;
420		akid->authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(p) = *p;
421		akid->authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(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
433int
434lws_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_V30_ONLY(v3_ext).MBEDTLS_PRIVATE_V30_ONLY(p),
438					*end_ext_data, *end_ext_octet;
439	const uint8_t *end = p + crt->MBEDTLS_PRIVATE_V30_ONLY(v3_ext).MBEDTLS_PRIVATE_V30_ONLY(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_V30_ONLY(len),
461					   MBEDTLS_ASN1_OID);
462		if (r)
463			return r;
464
465		extn_oid.MBEDTLS_PRIVATE_V30_ONLY(tag) = MBEDTLS_ASN1_OID;
466		extn_oid.MBEDTLS_PRIVATE_V30_ONLY(p) = p;
467		p += extn_oid.MBEDTLS_PRIVATE_V30_ONLY(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