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