1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_ci * libwebsockets - small server side websockets and web server implementation 3d4afb5ceSopenharmony_ci * 4d4afb5ceSopenharmony_ci * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com> 5d4afb5ceSopenharmony_ci * 6d4afb5ceSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7d4afb5ceSopenharmony_ci * of this software and associated documentation files (the "Software"), to 8d4afb5ceSopenharmony_ci * deal in the Software without restriction, including without limitation the 9d4afb5ceSopenharmony_ci * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10d4afb5ceSopenharmony_ci * sell copies of the Software, and to permit persons to whom the Software is 11d4afb5ceSopenharmony_ci * furnished to do so, subject to the following conditions: 12d4afb5ceSopenharmony_ci * 13d4afb5ceSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14d4afb5ceSopenharmony_ci * all copies or substantial portions of the Software. 15d4afb5ceSopenharmony_ci * 16d4afb5ceSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17d4afb5ceSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18d4afb5ceSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19d4afb5ceSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20d4afb5ceSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21d4afb5ceSopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22d4afb5ceSopenharmony_ci * IN THE SOFTWARE. 23d4afb5ceSopenharmony_ci */ 24d4afb5ceSopenharmony_ci 25d4afb5ceSopenharmony_ci#include "private-lib-core.h" 26d4afb5ceSopenharmony_ci#include "private-lib-tls-mbedtls.h" 27d4afb5ceSopenharmony_ci#include <mbedtls/oid.h> 28d4afb5ceSopenharmony_ci 29d4afb5ceSopenharmony_ci#if defined(LWS_PLAT_OPTEE) || defined(OPTEE_DEV_KIT) 30d4afb5ceSopenharmony_cistruct tm { 31d4afb5ceSopenharmony_ciint tm_sec; // seconds [0,61] 32d4afb5ceSopenharmony_ciint tm_min; // minutes [0,59] 33d4afb5ceSopenharmony_ciint tm_hour; // hour [0,23] 34d4afb5ceSopenharmony_ciint tm_mday; // day of month [1,31] 35d4afb5ceSopenharmony_ciint tm_mon; // month of year [0,11] 36d4afb5ceSopenharmony_ciint tm_year; // years since 1900 37d4afb5ceSopenharmony_ciint tm_wday; // day of week [0,6] (Sunday = 0) 38d4afb5ceSopenharmony_ciint tm_yday; // day of year [0,365] 39d4afb5ceSopenharmony_ciint tm_isdst; // daylight savings flag 40d4afb5ceSopenharmony_ci}; 41d4afb5ceSopenharmony_citime_t mktime(struct tm *t) 42d4afb5ceSopenharmony_ci{ 43d4afb5ceSopenharmony_ci return (time_t)0; 44d4afb5ceSopenharmony_ci} 45d4afb5ceSopenharmony_ci#endif 46d4afb5ceSopenharmony_ci 47d4afb5ceSopenharmony_cistatic time_t 48d4afb5ceSopenharmony_cilws_tls_mbedtls_time_to_unix(mbedtls_x509_time *xtime) 49d4afb5ceSopenharmony_ci{ 50d4afb5ceSopenharmony_ci struct tm t; 51d4afb5ceSopenharmony_ci 52d4afb5ceSopenharmony_ci if (!xtime || !xtime->MBEDTLS_PRIVATE_V30_ONLY(year) || xtime->MBEDTLS_PRIVATE_V30_ONLY(year) < 0) 53d4afb5ceSopenharmony_ci return (time_t)(long long)-1; 54d4afb5ceSopenharmony_ci 55d4afb5ceSopenharmony_ci memset(&t, 0, sizeof(t)); 56d4afb5ceSopenharmony_ci 57d4afb5ceSopenharmony_ci t.tm_year = xtime->MBEDTLS_PRIVATE_V30_ONLY(year) - 1900; 58d4afb5ceSopenharmony_ci t.tm_mon = xtime->MBEDTLS_PRIVATE_V30_ONLY(mon) - 1; /* mbedtls months are 1+, tm are 0+ */ 59d4afb5ceSopenharmony_ci t.tm_mday = xtime->MBEDTLS_PRIVATE_V30_ONLY(day) - 1; /* mbedtls days are 1+, tm are 0+ */ 60d4afb5ceSopenharmony_ci t.tm_hour = xtime->MBEDTLS_PRIVATE_V30_ONLY(hour); 61d4afb5ceSopenharmony_ci t.tm_min = xtime->MBEDTLS_PRIVATE_V30_ONLY(min); 62d4afb5ceSopenharmony_ci t.tm_sec = xtime->MBEDTLS_PRIVATE_V30_ONLY(sec); 63d4afb5ceSopenharmony_ci t.tm_isdst = -1; 64d4afb5ceSopenharmony_ci 65d4afb5ceSopenharmony_ci return mktime(&t); 66d4afb5ceSopenharmony_ci} 67d4afb5ceSopenharmony_ci 68d4afb5ceSopenharmony_cistatic int 69d4afb5ceSopenharmony_cilws_tls_mbedtls_get_x509_name(mbedtls_x509_name *name, 70d4afb5ceSopenharmony_ci union lws_tls_cert_info_results *buf, size_t len) 71d4afb5ceSopenharmony_ci{ 72d4afb5ceSopenharmony_ci int r = -1; 73d4afb5ceSopenharmony_ci 74d4afb5ceSopenharmony_ci buf->ns.len = 0; 75d4afb5ceSopenharmony_ci 76d4afb5ceSopenharmony_ci while (name) { 77d4afb5ceSopenharmony_ci /* 78d4afb5ceSopenharmony_ci if (MBEDTLS_OID_CMP(type, &name->oid)) { 79d4afb5ceSopenharmony_ci name = name->next; 80d4afb5ceSopenharmony_ci continue; 81d4afb5ceSopenharmony_ci } 82d4afb5ceSopenharmony_ci*/ 83d4afb5ceSopenharmony_ci lws_strnncpy(&buf->ns.name[buf->ns.len], 84d4afb5ceSopenharmony_ci (const char *)name->MBEDTLS_PRIVATE_V30_ONLY(val).MBEDTLS_PRIVATE_V30_ONLY(p), 85d4afb5ceSopenharmony_ci name->MBEDTLS_PRIVATE_V30_ONLY(val).MBEDTLS_PRIVATE_V30_ONLY(len), 86d4afb5ceSopenharmony_ci len - (size_t)buf->ns.len); 87d4afb5ceSopenharmony_ci buf->ns.len = (int)strlen(buf->ns.name); 88d4afb5ceSopenharmony_ci 89d4afb5ceSopenharmony_ci r = 0; 90d4afb5ceSopenharmony_ci name = name->MBEDTLS_PRIVATE_V30_ONLY(next); 91d4afb5ceSopenharmony_ci } 92d4afb5ceSopenharmony_ci 93d4afb5ceSopenharmony_ci return r; 94d4afb5ceSopenharmony_ci} 95d4afb5ceSopenharmony_ci 96d4afb5ceSopenharmony_ci 97d4afb5ceSopenharmony_ciint 98d4afb5ceSopenharmony_cilws_tls_mbedtls_cert_info(mbedtls_x509_crt *x509, enum lws_tls_cert_info type, 99d4afb5ceSopenharmony_ci union lws_tls_cert_info_results *buf, size_t len) 100d4afb5ceSopenharmony_ci{ 101d4afb5ceSopenharmony_ci mbedtls_x509_buf skid; 102d4afb5ceSopenharmony_ci lws_mbedtls_x509_authority akid; 103d4afb5ceSopenharmony_ci 104d4afb5ceSopenharmony_ci if (!x509) 105d4afb5ceSopenharmony_ci return -1; 106d4afb5ceSopenharmony_ci 107d4afb5ceSopenharmony_ci if (!len) 108d4afb5ceSopenharmony_ci len = sizeof(buf->ns.name); 109d4afb5ceSopenharmony_ci 110d4afb5ceSopenharmony_ci switch (type) { 111d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_VALIDITY_FROM: 112d4afb5ceSopenharmony_ci buf->time = lws_tls_mbedtls_time_to_unix(&x509->MBEDTLS_PRIVATE_V30_ONLY(valid_from)); 113d4afb5ceSopenharmony_ci if (buf->time == (time_t)(long long)-1) 114d4afb5ceSopenharmony_ci return -1; 115d4afb5ceSopenharmony_ci break; 116d4afb5ceSopenharmony_ci 117d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_VALIDITY_TO: 118d4afb5ceSopenharmony_ci buf->time = lws_tls_mbedtls_time_to_unix(&x509->MBEDTLS_PRIVATE_V30_ONLY(valid_to)); 119d4afb5ceSopenharmony_ci if (buf->time == (time_t)(long long)-1) 120d4afb5ceSopenharmony_ci return -1; 121d4afb5ceSopenharmony_ci break; 122d4afb5ceSopenharmony_ci 123d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_COMMON_NAME: 124d4afb5ceSopenharmony_ci return lws_tls_mbedtls_get_x509_name(&x509->MBEDTLS_PRIVATE_V30_ONLY(subject), buf, len); 125d4afb5ceSopenharmony_ci 126d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_ISSUER_NAME: 127d4afb5ceSopenharmony_ci return lws_tls_mbedtls_get_x509_name(&x509->MBEDTLS_PRIVATE_V30_ONLY(issuer), buf, len); 128d4afb5ceSopenharmony_ci 129d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_USAGE: 130d4afb5ceSopenharmony_ci buf->usage = x509->MBEDTLS_PRIVATE(key_usage); 131d4afb5ceSopenharmony_ci break; 132d4afb5ceSopenharmony_ci 133d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY: 134d4afb5ceSopenharmony_ci { 135d4afb5ceSopenharmony_ci char *p = buf->ns.name; 136d4afb5ceSopenharmony_ci size_t r = len, u; 137d4afb5ceSopenharmony_ci 138d4afb5ceSopenharmony_ci switch (mbedtls_pk_get_type(&x509->MBEDTLS_PRIVATE_V30_ONLY(pk))) { 139d4afb5ceSopenharmony_ci case MBEDTLS_PK_RSA: 140d4afb5ceSopenharmony_ci { 141d4afb5ceSopenharmony_ci mbedtls_rsa_context *rsa = mbedtls_pk_rsa(x509->MBEDTLS_PRIVATE_V30_ONLY(pk)); 142d4afb5ceSopenharmony_ci 143d4afb5ceSopenharmony_ci if (mbedtls_mpi_write_string(&rsa->MBEDTLS_PRIVATE(N), 16, p, r, &u)) 144d4afb5ceSopenharmony_ci return -1; 145d4afb5ceSopenharmony_ci r -= u; 146d4afb5ceSopenharmony_ci p += u; 147d4afb5ceSopenharmony_ci if (mbedtls_mpi_write_string(&rsa->MBEDTLS_PRIVATE(E), 16, p, r, &u)) 148d4afb5ceSopenharmony_ci return -1; 149d4afb5ceSopenharmony_ci 150d4afb5ceSopenharmony_ci p += u; 151d4afb5ceSopenharmony_ci buf->ns.len = lws_ptr_diff(p, buf->ns.name); 152d4afb5ceSopenharmony_ci break; 153d4afb5ceSopenharmony_ci } 154d4afb5ceSopenharmony_ci case MBEDTLS_PK_ECKEY: 155d4afb5ceSopenharmony_ci { 156d4afb5ceSopenharmony_ci mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(x509->MBEDTLS_PRIVATE_V30_ONLY(pk)); 157d4afb5ceSopenharmony_ci 158d4afb5ceSopenharmony_ci if (mbedtls_mpi_write_string(&ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), 16, p, r, &u)) 159d4afb5ceSopenharmony_ci return -1; 160d4afb5ceSopenharmony_ci r -= u; 161d4afb5ceSopenharmony_ci p += u; 162d4afb5ceSopenharmony_ci if (mbedtls_mpi_write_string(&ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), 16, p, r, &u)) 163d4afb5ceSopenharmony_ci return -1; 164d4afb5ceSopenharmony_ci r -= u; 165d4afb5ceSopenharmony_ci p += u; 166d4afb5ceSopenharmony_ci if (mbedtls_mpi_write_string(&ecp->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 16, p, r, &u)) 167d4afb5ceSopenharmony_ci return -1; 168d4afb5ceSopenharmony_ci p += u; 169d4afb5ceSopenharmony_ci buf->ns.len = lws_ptr_diff(p, buf->ns.name); 170d4afb5ceSopenharmony_ci break; 171d4afb5ceSopenharmony_ci } 172d4afb5ceSopenharmony_ci default: 173d4afb5ceSopenharmony_ci lwsl_notice("%s: x509 has unsupported pubkey type %d\n", 174d4afb5ceSopenharmony_ci __func__, 175d4afb5ceSopenharmony_ci mbedtls_pk_get_type(&x509->MBEDTLS_PRIVATE_V30_ONLY(pk))); 176d4afb5ceSopenharmony_ci 177d4afb5ceSopenharmony_ci return -1; 178d4afb5ceSopenharmony_ci } 179d4afb5ceSopenharmony_ci break; 180d4afb5ceSopenharmony_ci } 181d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_DER_RAW: 182d4afb5ceSopenharmony_ci 183d4afb5ceSopenharmony_ci buf->ns.len = (int)x509->MBEDTLS_PRIVATE_V30_ONLY(raw).MBEDTLS_PRIVATE_V30_ONLY(len); 184d4afb5ceSopenharmony_ci 185d4afb5ceSopenharmony_ci if (len < x509->MBEDTLS_PRIVATE_V30_ONLY(raw).MBEDTLS_PRIVATE_V30_ONLY(len)) 186d4afb5ceSopenharmony_ci /* 187d4afb5ceSopenharmony_ci * The buffer is too small and the attempt failed, but 188d4afb5ceSopenharmony_ci * the required object length is in buf->ns.len 189d4afb5ceSopenharmony_ci */ 190d4afb5ceSopenharmony_ci return -1; 191d4afb5ceSopenharmony_ci 192d4afb5ceSopenharmony_ci memcpy(buf->ns.name, x509->MBEDTLS_PRIVATE_V30_ONLY(raw).MBEDTLS_PRIVATE_V30_ONLY(p), 193d4afb5ceSopenharmony_ci x509->MBEDTLS_PRIVATE_V30_ONLY(raw).MBEDTLS_PRIVATE_V30_ONLY(len)); 194d4afb5ceSopenharmony_ci break; 195d4afb5ceSopenharmony_ci 196d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID: 197d4afb5ceSopenharmony_ci 198d4afb5ceSopenharmony_ci memset(&akid, 0, sizeof(akid)); 199d4afb5ceSopenharmony_ci memset(&skid, 0, sizeof(skid)); 200d4afb5ceSopenharmony_ci 201d4afb5ceSopenharmony_ci lws_x509_get_crt_ext(x509, &skid, &akid); 202d4afb5ceSopenharmony_ci if (akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(tag) != MBEDTLS_ASN1_OCTET_STRING) 203d4afb5ceSopenharmony_ci return 1; 204d4afb5ceSopenharmony_ci buf->ns.len = (int)akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(len); 205d4afb5ceSopenharmony_ci if (!akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(p) || 206d4afb5ceSopenharmony_ci len < (size_t)buf->ns.len) 207d4afb5ceSopenharmony_ci return -1; 208d4afb5ceSopenharmony_ci memcpy(buf->ns.name, akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(p), (size_t)buf->ns.len); 209d4afb5ceSopenharmony_ci break; 210d4afb5ceSopenharmony_ci 211d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_ISSUER: { 212d4afb5ceSopenharmony_ci mbedtls_x509_sequence * ip; 213d4afb5ceSopenharmony_ci 214d4afb5ceSopenharmony_ci memset(&akid, 0, sizeof(akid)); 215d4afb5ceSopenharmony_ci memset(&skid, 0, sizeof(skid)); 216d4afb5ceSopenharmony_ci 217d4afb5ceSopenharmony_ci lws_x509_get_crt_ext(x509, &skid, &akid); 218d4afb5ceSopenharmony_ci 219d4afb5ceSopenharmony_ci ip = &akid.authorityCertIssuer; 220d4afb5ceSopenharmony_ci 221d4afb5ceSopenharmony_ci buf->ns.len = 0; 222d4afb5ceSopenharmony_ci 223d4afb5ceSopenharmony_ci while (ip) { 224d4afb5ceSopenharmony_ci if (akid.keyIdentifier.MBEDTLS_PRIVATE_V30_ONLY(tag) != MBEDTLS_ASN1_OCTET_STRING || 225d4afb5ceSopenharmony_ci !ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(p) || 226d4afb5ceSopenharmony_ci ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(len) < 9 || 227d4afb5ceSopenharmony_ci len < (size_t)ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(len) - 9u) 228d4afb5ceSopenharmony_ci break; 229d4afb5ceSopenharmony_ci 230d4afb5ceSopenharmony_ci memcpy(buf->ns.name + buf->ns.len, ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(p), 231d4afb5ceSopenharmony_ci (size_t)ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(len) - 9); 232d4afb5ceSopenharmony_ci buf->ns.len = buf->ns.len + (int)ip->MBEDTLS_PRIVATE_V30_ONLY(buf).MBEDTLS_PRIVATE_V30_ONLY(len) - 9; 233d4afb5ceSopenharmony_ci 234d4afb5ceSopenharmony_ci ip = ip->MBEDTLS_PRIVATE_V30_ONLY(next); 235d4afb5ceSopenharmony_ci } 236d4afb5ceSopenharmony_ci break; 237d4afb5ceSopenharmony_ci } 238d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_SERIAL: 239d4afb5ceSopenharmony_ci 240d4afb5ceSopenharmony_ci memset(&akid, 0, sizeof(akid)); 241d4afb5ceSopenharmony_ci memset(&skid, 0, sizeof(skid)); 242d4afb5ceSopenharmony_ci 243d4afb5ceSopenharmony_ci lws_x509_get_crt_ext(x509, &skid, &akid); 244d4afb5ceSopenharmony_ci 245d4afb5ceSopenharmony_ci if (akid.authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(tag) != MBEDTLS_ASN1_OCTET_STRING) 246d4afb5ceSopenharmony_ci return 1; 247d4afb5ceSopenharmony_ci buf->ns.len = (int)akid.authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(len); 248d4afb5ceSopenharmony_ci if (!akid.authorityCertSerialNumber.MBEDTLS_PRIVATE_V30_ONLY(p) || 249d4afb5ceSopenharmony_ci len < (size_t)buf->ns.len) 250d4afb5ceSopenharmony_ci return -1; 251d4afb5ceSopenharmony_ci memcpy(buf->ns.name, akid.authorityCertSerialNumber. 252d4afb5ceSopenharmony_ci MBEDTLS_PRIVATE_V30_ONLY(p), (size_t)buf->ns.len); 253d4afb5ceSopenharmony_ci break; 254d4afb5ceSopenharmony_ci 255d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_SUBJECT_KEY_ID: 256d4afb5ceSopenharmony_ci 257d4afb5ceSopenharmony_ci memset(&akid, 0, sizeof(akid)); 258d4afb5ceSopenharmony_ci memset(&skid, 0, sizeof(skid)); 259d4afb5ceSopenharmony_ci 260d4afb5ceSopenharmony_ci lws_x509_get_crt_ext(x509, &skid, &akid); 261d4afb5ceSopenharmony_ci 262d4afb5ceSopenharmony_ci if (skid.MBEDTLS_PRIVATE_V30_ONLY(tag) != MBEDTLS_ASN1_OCTET_STRING) 263d4afb5ceSopenharmony_ci return 1; 264d4afb5ceSopenharmony_ci buf->ns.len = (int)skid.MBEDTLS_PRIVATE_V30_ONLY(len); 265d4afb5ceSopenharmony_ci if (len < (size_t)buf->ns.len) 266d4afb5ceSopenharmony_ci return -1; 267d4afb5ceSopenharmony_ci memcpy(buf->ns.name, skid.MBEDTLS_PRIVATE_V30_ONLY(p), (size_t)buf->ns.len); 268d4afb5ceSopenharmony_ci break; 269d4afb5ceSopenharmony_ci default: 270d4afb5ceSopenharmony_ci return -1; 271d4afb5ceSopenharmony_ci } 272d4afb5ceSopenharmony_ci 273d4afb5ceSopenharmony_ci return 0; 274d4afb5ceSopenharmony_ci} 275d4afb5ceSopenharmony_ci 276d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK) 277d4afb5ceSopenharmony_ciint 278d4afb5ceSopenharmony_cilws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type, 279d4afb5ceSopenharmony_ci union lws_tls_cert_info_results *buf, size_t len) 280d4afb5ceSopenharmony_ci{ 281d4afb5ceSopenharmony_ci mbedtls_x509_crt *x509; 282d4afb5ceSopenharmony_ci 283d4afb5ceSopenharmony_ci x509 = ssl_ctx_get_mbedtls_x509_crt(vhost->tls.ssl_ctx); 284d4afb5ceSopenharmony_ci 285d4afb5ceSopenharmony_ci return lws_tls_mbedtls_cert_info(x509, type, buf, len); 286d4afb5ceSopenharmony_ci} 287d4afb5ceSopenharmony_ci 288d4afb5ceSopenharmony_ciint 289d4afb5ceSopenharmony_cilws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type, 290d4afb5ceSopenharmony_ci union lws_tls_cert_info_results *buf, size_t len) 291d4afb5ceSopenharmony_ci{ 292d4afb5ceSopenharmony_ci mbedtls_x509_crt *x509; 293d4afb5ceSopenharmony_ci 294d4afb5ceSopenharmony_ci wsi = lws_get_network_wsi(wsi); 295d4afb5ceSopenharmony_ci 296d4afb5ceSopenharmony_ci x509 = ssl_get_peer_mbedtls_x509_crt(wsi->tls.ssl); 297d4afb5ceSopenharmony_ci 298d4afb5ceSopenharmony_ci if (!x509) 299d4afb5ceSopenharmony_ci return -1; 300d4afb5ceSopenharmony_ci 301d4afb5ceSopenharmony_ci switch (type) { 302d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_VERIFIED: 303d4afb5ceSopenharmony_ci buf->verified = SSL_get_verify_result(wsi->tls.ssl) == X509_V_OK; 304d4afb5ceSopenharmony_ci return 0; 305d4afb5ceSopenharmony_ci default: 306d4afb5ceSopenharmony_ci return lws_tls_mbedtls_cert_info(x509, type, buf, len); 307d4afb5ceSopenharmony_ci } 308d4afb5ceSopenharmony_ci 309d4afb5ceSopenharmony_ci return -1; 310d4afb5ceSopenharmony_ci} 311d4afb5ceSopenharmony_ci#endif 312d4afb5ceSopenharmony_ci 313d4afb5ceSopenharmony_ciint 314d4afb5ceSopenharmony_cilws_x509_info(struct lws_x509_cert *x509, enum lws_tls_cert_info type, 315d4afb5ceSopenharmony_ci union lws_tls_cert_info_results *buf, size_t len) 316d4afb5ceSopenharmony_ci{ 317d4afb5ceSopenharmony_ci return lws_tls_mbedtls_cert_info(&x509->cert, type, buf, len); 318d4afb5ceSopenharmony_ci} 319d4afb5ceSopenharmony_ci 320d4afb5ceSopenharmony_ciint 321d4afb5ceSopenharmony_cilws_x509_create(struct lws_x509_cert **x509) 322d4afb5ceSopenharmony_ci{ 323d4afb5ceSopenharmony_ci *x509 = lws_malloc(sizeof(**x509), __func__); 324d4afb5ceSopenharmony_ci 325d4afb5ceSopenharmony_ci return !(*x509); 326d4afb5ceSopenharmony_ci} 327d4afb5ceSopenharmony_ci 328d4afb5ceSopenharmony_ci/* 329d4afb5ceSopenharmony_ci * Parse one DER-encoded or one or more concatenated PEM-encoded certificates 330d4afb5ceSopenharmony_ci * and add them to the chained list. 331d4afb5ceSopenharmony_ci */ 332d4afb5ceSopenharmony_ci 333d4afb5ceSopenharmony_ciint 334d4afb5ceSopenharmony_cilws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len) 335d4afb5ceSopenharmony_ci{ 336d4afb5ceSopenharmony_ci int ret; 337d4afb5ceSopenharmony_ci 338d4afb5ceSopenharmony_ci mbedtls_x509_crt_init(&x509->cert); 339d4afb5ceSopenharmony_ci 340d4afb5ceSopenharmony_ci ret = mbedtls_x509_crt_parse(&x509->cert, pem, len); 341d4afb5ceSopenharmony_ci if (ret) { 342d4afb5ceSopenharmony_ci if (ret > 0) 343d4afb5ceSopenharmony_ci mbedtls_x509_crt_free(&x509->cert); 344d4afb5ceSopenharmony_ci lwsl_err("%s: unable to parse PEM cert: -0x%x\n", 345d4afb5ceSopenharmony_ci __func__, -ret); 346d4afb5ceSopenharmony_ci 347d4afb5ceSopenharmony_ci return -1; 348d4afb5ceSopenharmony_ci } 349d4afb5ceSopenharmony_ci 350d4afb5ceSopenharmony_ci return 0; 351d4afb5ceSopenharmony_ci} 352d4afb5ceSopenharmony_ci 353d4afb5ceSopenharmony_ciint 354d4afb5ceSopenharmony_cilws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted, 355d4afb5ceSopenharmony_ci const char *common_name) 356d4afb5ceSopenharmony_ci{ 357d4afb5ceSopenharmony_ci uint32_t flags = 0; 358d4afb5ceSopenharmony_ci int ret; 359d4afb5ceSopenharmony_ci 360d4afb5ceSopenharmony_ci ret = mbedtls_x509_crt_verify_with_profile(&x509->cert, &trusted->cert, 361d4afb5ceSopenharmony_ci NULL, 362d4afb5ceSopenharmony_ci &mbedtls_x509_crt_profile_next, 363d4afb5ceSopenharmony_ci common_name, &flags, NULL, 364d4afb5ceSopenharmony_ci NULL); 365d4afb5ceSopenharmony_ci 366d4afb5ceSopenharmony_ci if (ret) { 367d4afb5ceSopenharmony_ci lwsl_err("%s: unable to parse PEM cert: -0x%x\n", 368d4afb5ceSopenharmony_ci __func__, -ret); 369d4afb5ceSopenharmony_ci 370d4afb5ceSopenharmony_ci return -1; 371d4afb5ceSopenharmony_ci } 372d4afb5ceSopenharmony_ci 373d4afb5ceSopenharmony_ci return 0; 374d4afb5ceSopenharmony_ci} 375d4afb5ceSopenharmony_ci 376d4afb5ceSopenharmony_ci#if defined(LWS_WITH_JOSE) 377d4afb5ceSopenharmony_ci 378d4afb5ceSopenharmony_ciint 379d4afb5ceSopenharmony_cilws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509, 380d4afb5ceSopenharmony_ci const char *curves, int rsa_min_bits) 381d4afb5ceSopenharmony_ci{ 382d4afb5ceSopenharmony_ci int kt = (int)mbedtls_pk_get_type(&x509->cert.MBEDTLS_PRIVATE_V30_ONLY(pk)), 383d4afb5ceSopenharmony_ci n, count = 0, ret = -1; 384d4afb5ceSopenharmony_ci mbedtls_rsa_context *rsactx; 385d4afb5ceSopenharmony_ci mbedtls_ecp_keypair *ecpctx; 386d4afb5ceSopenharmony_ci mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT]; 387d4afb5ceSopenharmony_ci 388d4afb5ceSopenharmony_ci memset(jwk, 0, sizeof(*jwk)); 389d4afb5ceSopenharmony_ci 390d4afb5ceSopenharmony_ci switch (kt) { 391d4afb5ceSopenharmony_ci case MBEDTLS_PK_RSA: 392d4afb5ceSopenharmony_ci lwsl_notice("%s: RSA key\n", __func__); 393d4afb5ceSopenharmony_ci jwk->kty = LWS_GENCRYPTO_KTY_RSA; 394d4afb5ceSopenharmony_ci rsactx = mbedtls_pk_rsa(x509->cert.MBEDTLS_PRIVATE_V30_ONLY(pk)); 395d4afb5ceSopenharmony_ci 396d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = &rsactx->MBEDTLS_PRIVATE(E); 397d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = &rsactx->MBEDTLS_PRIVATE(N); 398d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = &rsactx->MBEDTLS_PRIVATE(D); 399d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_RSA_KEYEL_P] = &rsactx->MBEDTLS_PRIVATE(P); 400d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_RSA_KEYEL_Q] = &rsactx->MBEDTLS_PRIVATE(Q); 401d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_RSA_KEYEL_DP] = &rsactx->MBEDTLS_PRIVATE(DP); 402d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_RSA_KEYEL_DQ] = &rsactx->MBEDTLS_PRIVATE(DQ); 403d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_RSA_KEYEL_QI] = &rsactx->MBEDTLS_PRIVATE(QP); 404d4afb5ceSopenharmony_ci 405d4afb5ceSopenharmony_ci count = LWS_GENCRYPTO_RSA_KEYEL_QI + 1; 406d4afb5ceSopenharmony_ci n = LWS_GENCRYPTO_RSA_KEYEL_E; 407d4afb5ceSopenharmony_ci break; 408d4afb5ceSopenharmony_ci 409d4afb5ceSopenharmony_ci case MBEDTLS_PK_ECKEY: 410d4afb5ceSopenharmony_ci lwsl_notice("%s: EC key\n", __func__); 411d4afb5ceSopenharmony_ci jwk->kty = LWS_GENCRYPTO_KTY_EC; 412d4afb5ceSopenharmony_ci ecpctx = mbedtls_pk_ec(x509->cert.MBEDTLS_PRIVATE_V30_ONLY(pk)); 413d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_EC_KEYEL_X] = &ecpctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X); 414d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_EC_KEYEL_D] = &ecpctx->MBEDTLS_PRIVATE(d); 415d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = &ecpctx->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y); 416d4afb5ceSopenharmony_ci 417d4afb5ceSopenharmony_ci if (lws_genec_confirm_curve_allowed_by_tls_id(curves, 418d4afb5ceSopenharmony_ci (int)ecpctx->MBEDTLS_PRIVATE(grp).id, jwk)) 419d4afb5ceSopenharmony_ci /* already logged */ 420d4afb5ceSopenharmony_ci goto bail; 421d4afb5ceSopenharmony_ci 422d4afb5ceSopenharmony_ci count = LWS_GENCRYPTO_EC_KEYEL_COUNT; 423d4afb5ceSopenharmony_ci n = LWS_GENCRYPTO_EC_KEYEL_X; 424d4afb5ceSopenharmony_ci break; 425d4afb5ceSopenharmony_ci default: 426d4afb5ceSopenharmony_ci lwsl_err("%s: key type %d not supported\n", __func__, kt); 427d4afb5ceSopenharmony_ci 428d4afb5ceSopenharmony_ci return -1; 429d4afb5ceSopenharmony_ci } 430d4afb5ceSopenharmony_ci 431d4afb5ceSopenharmony_ci for (; n < count; n++) { 432d4afb5ceSopenharmony_ci if (!mbedtls_mpi_size(mpi[n])) 433d4afb5ceSopenharmony_ci continue; 434d4afb5ceSopenharmony_ci 435d4afb5ceSopenharmony_ci jwk->e[n].buf = lws_malloc(mbedtls_mpi_size(mpi[n]), "certjwk"); 436d4afb5ceSopenharmony_ci if (!jwk->e[n].buf) 437d4afb5ceSopenharmony_ci goto bail; 438d4afb5ceSopenharmony_ci jwk->e[n].len = (uint32_t)mbedtls_mpi_size(mpi[n]); 439d4afb5ceSopenharmony_ci mbedtls_mpi_write_binary(mpi[n], jwk->e[n].buf, jwk->e[n].len); 440d4afb5ceSopenharmony_ci } 441d4afb5ceSopenharmony_ci 442d4afb5ceSopenharmony_ci ret = 0; 443d4afb5ceSopenharmony_ci 444d4afb5ceSopenharmony_cibail: 445d4afb5ceSopenharmony_ci /* jwk destroy will clean up partials */ 446d4afb5ceSopenharmony_ci if (ret) 447d4afb5ceSopenharmony_ci lws_jwk_destroy(jwk); 448d4afb5ceSopenharmony_ci 449d4afb5ceSopenharmony_ci return ret; 450d4afb5ceSopenharmony_ci} 451d4afb5ceSopenharmony_ci 452d4afb5ceSopenharmony_ciint 453d4afb5ceSopenharmony_cilws_x509_jwk_privkey_pem(struct lws_context *cx, struct lws_jwk *jwk, 454d4afb5ceSopenharmony_ci void *pem, size_t len, const char *passphrase) 455d4afb5ceSopenharmony_ci{ 456d4afb5ceSopenharmony_ci mbedtls_rsa_context *rsactx; 457d4afb5ceSopenharmony_ci mbedtls_ecp_keypair *ecpctx; 458d4afb5ceSopenharmony_ci mbedtls_pk_context pk; 459d4afb5ceSopenharmony_ci mbedtls_mpi *mpi[LWS_GENCRYPTO_RSA_KEYEL_COUNT]; 460d4afb5ceSopenharmony_ci int n, ret = -1, count = 0; 461d4afb5ceSopenharmony_ci 462d4afb5ceSopenharmony_ci mbedtls_pk_init(&pk); 463d4afb5ceSopenharmony_ci 464d4afb5ceSopenharmony_ci n = 0; 465d4afb5ceSopenharmony_ci if (passphrase) 466d4afb5ceSopenharmony_ci n = (int)strlen(passphrase); 467d4afb5ceSopenharmony_ci n = mbedtls_pk_parse_key(&pk, pem, len, (uint8_t *)passphrase, (unsigned int)n 468d4afb5ceSopenharmony_ci#if defined(MBEDTLS_VERSION_NUMBER) && MBEDTLS_VERSION_NUMBER >= 0x03000000 469d4afb5ceSopenharmony_ci , mbedtls_ctr_drbg_random, &cx->mcdc 470d4afb5ceSopenharmony_ci#endif 471d4afb5ceSopenharmony_ci ); 472d4afb5ceSopenharmony_ci if (n) { 473d4afb5ceSopenharmony_ci lwsl_err("%s: parse PEM key failed: -0x%x\n", __func__, -n); 474d4afb5ceSopenharmony_ci 475d4afb5ceSopenharmony_ci return -1; 476d4afb5ceSopenharmony_ci } 477d4afb5ceSopenharmony_ci 478d4afb5ceSopenharmony_ci /* the incoming private key type */ 479d4afb5ceSopenharmony_ci switch (mbedtls_pk_get_type(&pk)) { 480d4afb5ceSopenharmony_ci case MBEDTLS_PK_RSA: 481d4afb5ceSopenharmony_ci if (jwk->kty != LWS_GENCRYPTO_KTY_RSA) { 482d4afb5ceSopenharmony_ci lwsl_err("%s: RSA privkey, non-RSA jwk\n", __func__); 483d4afb5ceSopenharmony_ci goto bail; 484d4afb5ceSopenharmony_ci } 485d4afb5ceSopenharmony_ci rsactx = mbedtls_pk_rsa(pk); 486d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = &rsactx->MBEDTLS_PRIVATE(D); 487d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_RSA_KEYEL_P] = &rsactx->MBEDTLS_PRIVATE(P); 488d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_RSA_KEYEL_Q] = &rsactx->MBEDTLS_PRIVATE(Q); 489d4afb5ceSopenharmony_ci n = LWS_GENCRYPTO_RSA_KEYEL_D; 490d4afb5ceSopenharmony_ci count = LWS_GENCRYPTO_RSA_KEYEL_Q + 1; 491d4afb5ceSopenharmony_ci break; 492d4afb5ceSopenharmony_ci case MBEDTLS_PK_ECKEY: 493d4afb5ceSopenharmony_ci if (jwk->kty != LWS_GENCRYPTO_KTY_EC) { 494d4afb5ceSopenharmony_ci lwsl_err("%s: EC privkey, non-EC jwk\n", __func__); 495d4afb5ceSopenharmony_ci goto bail; 496d4afb5ceSopenharmony_ci } 497d4afb5ceSopenharmony_ci ecpctx = mbedtls_pk_ec(pk); 498d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_EC_KEYEL_D] = &ecpctx->MBEDTLS_PRIVATE(d); 499d4afb5ceSopenharmony_ci n = LWS_GENCRYPTO_EC_KEYEL_D; 500d4afb5ceSopenharmony_ci count = n + 1; 501d4afb5ceSopenharmony_ci break; 502d4afb5ceSopenharmony_ci default: 503d4afb5ceSopenharmony_ci lwsl_err("%s: unusable key type %d\n", __func__, 504d4afb5ceSopenharmony_ci mbedtls_pk_get_type(&pk)); 505d4afb5ceSopenharmony_ci goto bail; 506d4afb5ceSopenharmony_ci } 507d4afb5ceSopenharmony_ci 508d4afb5ceSopenharmony_ci for (; n < count; n++) { 509d4afb5ceSopenharmony_ci if (!mbedtls_mpi_size(mpi[n])) { 510d4afb5ceSopenharmony_ci lwsl_err("%s: empty privkey\n", __func__); 511d4afb5ceSopenharmony_ci goto bail; 512d4afb5ceSopenharmony_ci } 513d4afb5ceSopenharmony_ci 514d4afb5ceSopenharmony_ci jwk->e[n].buf = lws_malloc(mbedtls_mpi_size(mpi[n]), "certjwk"); 515d4afb5ceSopenharmony_ci if (!jwk->e[n].buf) 516d4afb5ceSopenharmony_ci goto bail; 517d4afb5ceSopenharmony_ci jwk->e[n].len = (uint32_t)mbedtls_mpi_size(mpi[n]); 518d4afb5ceSopenharmony_ci mbedtls_mpi_write_binary(mpi[n], jwk->e[n].buf, jwk->e[n].len); 519d4afb5ceSopenharmony_ci } 520d4afb5ceSopenharmony_ci 521d4afb5ceSopenharmony_ci ret = 0; 522d4afb5ceSopenharmony_ci 523d4afb5ceSopenharmony_cibail: 524d4afb5ceSopenharmony_ci mbedtls_pk_free(&pk); 525d4afb5ceSopenharmony_ci 526d4afb5ceSopenharmony_ci return ret; 527d4afb5ceSopenharmony_ci} 528d4afb5ceSopenharmony_ci#endif 529d4afb5ceSopenharmony_ci 530d4afb5ceSopenharmony_civoid 531d4afb5ceSopenharmony_cilws_x509_destroy(struct lws_x509_cert **x509) 532d4afb5ceSopenharmony_ci{ 533d4afb5ceSopenharmony_ci if (!*x509) 534d4afb5ceSopenharmony_ci return; 535d4afb5ceSopenharmony_ci 536d4afb5ceSopenharmony_ci mbedtls_x509_crt_free(&(*x509)->cert); 537d4afb5ceSopenharmony_ci 538d4afb5ceSopenharmony_ci lws_free_set_NULL(*x509); 539d4afb5ceSopenharmony_ci} 540