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#define WIN32_LEAN_AND_MEAN 26d4afb5ceSopenharmony_ci#include "private-lib-core.h" 27d4afb5ceSopenharmony_ci#include "private-lib-tls-openssl.h" 28d4afb5ceSopenharmony_ci 29d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_OPTEE) 30d4afb5ceSopenharmony_cistatic int 31d4afb5ceSopenharmony_cidec(char c) 32d4afb5ceSopenharmony_ci{ 33d4afb5ceSopenharmony_ci return c - '0'; 34d4afb5ceSopenharmony_ci} 35d4afb5ceSopenharmony_ci#endif 36d4afb5ceSopenharmony_ci 37d4afb5ceSopenharmony_cistatic time_t 38d4afb5ceSopenharmony_cilws_tls_openssl_asn1time_to_unix(ASN1_TIME *as) 39d4afb5ceSopenharmony_ci{ 40d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_OPTEE) 41d4afb5ceSopenharmony_ci 42d4afb5ceSopenharmony_ci const char *p = (const char *)as->data; 43d4afb5ceSopenharmony_ci struct tm t; 44d4afb5ceSopenharmony_ci 45d4afb5ceSopenharmony_ci /* [YY]YYMMDDHHMMSSZ */ 46d4afb5ceSopenharmony_ci 47d4afb5ceSopenharmony_ci memset(&t, 0, sizeof(t)); 48d4afb5ceSopenharmony_ci 49d4afb5ceSopenharmony_ci if (strlen(p) == 13) { 50d4afb5ceSopenharmony_ci t.tm_year = (dec(p[0]) * 10) + dec(p[1]) + 100; 51d4afb5ceSopenharmony_ci p += 2; 52d4afb5ceSopenharmony_ci } else { 53d4afb5ceSopenharmony_ci t.tm_year = (dec(p[0]) * 1000) + (dec(p[1]) * 100) + 54d4afb5ceSopenharmony_ci (dec(p[2]) * 10) + dec(p[3]); 55d4afb5ceSopenharmony_ci p += 4; 56d4afb5ceSopenharmony_ci } 57d4afb5ceSopenharmony_ci t.tm_mon = (dec(p[0]) * 10) + dec(p[1]) - 1; 58d4afb5ceSopenharmony_ci p += 2; 59d4afb5ceSopenharmony_ci t.tm_mday = (dec(p[0]) * 10) + dec(p[1]) - 1; 60d4afb5ceSopenharmony_ci p += 2; 61d4afb5ceSopenharmony_ci t.tm_hour = (dec(p[0]) * 10) + dec(p[1]); 62d4afb5ceSopenharmony_ci p += 2; 63d4afb5ceSopenharmony_ci t.tm_min = (dec(p[0]) * 10) + dec(p[1]); 64d4afb5ceSopenharmony_ci p += 2; 65d4afb5ceSopenharmony_ci t.tm_sec = (dec(p[0]) * 10) + dec(p[1]); 66d4afb5ceSopenharmony_ci t.tm_isdst = 0; 67d4afb5ceSopenharmony_ci 68d4afb5ceSopenharmony_ci return mktime(&t); 69d4afb5ceSopenharmony_ci#else 70d4afb5ceSopenharmony_ci return (time_t)-1; 71d4afb5ceSopenharmony_ci#endif 72d4afb5ceSopenharmony_ci} 73d4afb5ceSopenharmony_ci 74d4afb5ceSopenharmony_ci#if defined(USE_WOLFSSL) 75d4afb5ceSopenharmony_ci#define AUTHORITY_KEYID WOLFSSL_AUTHORITY_KEYID 76d4afb5ceSopenharmony_ci#endif 77d4afb5ceSopenharmony_ci 78d4afb5ceSopenharmony_ciint 79d4afb5ceSopenharmony_cilws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type, 80d4afb5ceSopenharmony_ci union lws_tls_cert_info_results *buf, size_t len) 81d4afb5ceSopenharmony_ci{ 82d4afb5ceSopenharmony_ci#ifndef USE_WOLFSSL 83d4afb5ceSopenharmony_ci const unsigned char *dp; 84d4afb5ceSopenharmony_ci ASN1_OCTET_STRING *val; 85d4afb5ceSopenharmony_ci AUTHORITY_KEYID *akid; 86d4afb5ceSopenharmony_ci X509_EXTENSION *ext; 87d4afb5ceSopenharmony_ci int tag, xclass, r = 1; 88d4afb5ceSopenharmony_ci long xlen, loc; 89d4afb5ceSopenharmony_ci#endif 90d4afb5ceSopenharmony_ci X509_NAME *xn; 91d4afb5ceSopenharmony_ci#if !defined(LWS_PLAT_OPTEE) 92d4afb5ceSopenharmony_ci char *p; 93d4afb5ceSopenharmony_ci#endif 94d4afb5ceSopenharmony_ci 95d4afb5ceSopenharmony_ci buf->ns.len = 0; 96d4afb5ceSopenharmony_ci 97d4afb5ceSopenharmony_ci if (!x509) 98d4afb5ceSopenharmony_ci return -1; 99d4afb5ceSopenharmony_ci if (!len) 100d4afb5ceSopenharmony_ci len = sizeof(buf->ns.name); 101d4afb5ceSopenharmony_ci 102d4afb5ceSopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(X509_get_notBefore) 103d4afb5ceSopenharmony_ci#define X509_get_notBefore(x) X509_getm_notBefore(x) 104d4afb5ceSopenharmony_ci#define X509_get_notAfter(x) X509_getm_notAfter(x) 105d4afb5ceSopenharmony_ci#endif 106d4afb5ceSopenharmony_ci 107d4afb5ceSopenharmony_ci switch (type) { 108d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_VALIDITY_FROM: 109d4afb5ceSopenharmony_ci buf->time = lws_tls_openssl_asn1time_to_unix( 110d4afb5ceSopenharmony_ci X509_get_notBefore(x509)); 111d4afb5ceSopenharmony_ci if (buf->time == (time_t)-1) 112d4afb5ceSopenharmony_ci return -1; 113d4afb5ceSopenharmony_ci break; 114d4afb5ceSopenharmony_ci 115d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_VALIDITY_TO: 116d4afb5ceSopenharmony_ci buf->time = lws_tls_openssl_asn1time_to_unix( 117d4afb5ceSopenharmony_ci X509_get_notAfter(x509)); 118d4afb5ceSopenharmony_ci if (buf->time == (time_t)-1) 119d4afb5ceSopenharmony_ci return -1; 120d4afb5ceSopenharmony_ci break; 121d4afb5ceSopenharmony_ci 122d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_COMMON_NAME: 123d4afb5ceSopenharmony_ci#if defined(LWS_PLAT_OPTEE) 124d4afb5ceSopenharmony_ci return -1; 125d4afb5ceSopenharmony_ci#else 126d4afb5ceSopenharmony_ci xn = X509_get_subject_name(x509); 127d4afb5ceSopenharmony_ci if (!xn) 128d4afb5ceSopenharmony_ci return -1; 129d4afb5ceSopenharmony_ci X509_NAME_oneline(xn, buf->ns.name, (int)len - 2); 130d4afb5ceSopenharmony_ci p = strstr(buf->ns.name, "/CN="); 131d4afb5ceSopenharmony_ci if (p) 132d4afb5ceSopenharmony_ci memmove(buf->ns.name, p + 4, strlen(p + 4) + 1); 133d4afb5ceSopenharmony_ci buf->ns.len = (int)strlen(buf->ns.name); 134d4afb5ceSopenharmony_ci return 0; 135d4afb5ceSopenharmony_ci#endif 136d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_ISSUER_NAME: 137d4afb5ceSopenharmony_ci xn = X509_get_issuer_name(x509); 138d4afb5ceSopenharmony_ci if (!xn) 139d4afb5ceSopenharmony_ci return -1; 140d4afb5ceSopenharmony_ci X509_NAME_oneline(xn, buf->ns.name, (int)len - 1); 141d4afb5ceSopenharmony_ci buf->ns.len = (int)strlen(buf->ns.name); 142d4afb5ceSopenharmony_ci return 0; 143d4afb5ceSopenharmony_ci 144d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_USAGE: 145d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_X509_get_key_usage) 146d4afb5ceSopenharmony_ci buf->usage = X509_get_key_usage(x509); 147d4afb5ceSopenharmony_ci break; 148d4afb5ceSopenharmony_ci#else 149d4afb5ceSopenharmony_ci return -1; 150d4afb5ceSopenharmony_ci#endif 151d4afb5ceSopenharmony_ci 152d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY: 153d4afb5ceSopenharmony_ci { 154d4afb5ceSopenharmony_ci#ifndef USE_WOLFSSL 155d4afb5ceSopenharmony_ci size_t klen = (unsigned int)i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x509), NULL); 156d4afb5ceSopenharmony_ci uint8_t *tmp, *ptmp; 157d4afb5ceSopenharmony_ci 158d4afb5ceSopenharmony_ci if (!klen || klen > len) 159d4afb5ceSopenharmony_ci return -1; 160d4afb5ceSopenharmony_ci 161d4afb5ceSopenharmony_ci tmp = (uint8_t *)OPENSSL_malloc(klen); 162d4afb5ceSopenharmony_ci if (!tmp) 163d4afb5ceSopenharmony_ci return -1; 164d4afb5ceSopenharmony_ci 165d4afb5ceSopenharmony_ci ptmp = tmp; 166d4afb5ceSopenharmony_ci if (i2d_X509_PUBKEY( 167d4afb5ceSopenharmony_ci X509_get_X509_PUBKEY(x509), &ptmp) != (int)klen || 168d4afb5ceSopenharmony_ci !ptmp || lws_ptr_diff(ptmp, tmp) != (int)klen) { 169d4afb5ceSopenharmony_ci lwsl_info("%s: cert public key extraction failed\n", 170d4afb5ceSopenharmony_ci __func__); 171d4afb5ceSopenharmony_ci if (ptmp) 172d4afb5ceSopenharmony_ci OPENSSL_free(tmp); 173d4afb5ceSopenharmony_ci 174d4afb5ceSopenharmony_ci return -1; 175d4afb5ceSopenharmony_ci } 176d4afb5ceSopenharmony_ci 177d4afb5ceSopenharmony_ci buf->ns.len = (int)klen; 178d4afb5ceSopenharmony_ci memcpy(buf->ns.name, tmp, klen); 179d4afb5ceSopenharmony_ci OPENSSL_free(tmp); 180d4afb5ceSopenharmony_ci#endif 181d4afb5ceSopenharmony_ci return 0; 182d4afb5ceSopenharmony_ci } 183d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_DER_RAW: 184d4afb5ceSopenharmony_ci { 185d4afb5ceSopenharmony_ci int der_len = i2d_X509(x509, NULL); 186d4afb5ceSopenharmony_ci uint8_t *tmp = (uint8_t *)buf->ns.name; 187d4afb5ceSopenharmony_ci 188d4afb5ceSopenharmony_ci buf->ns.len = der_len < 0 ? 0 : der_len; 189d4afb5ceSopenharmony_ci 190d4afb5ceSopenharmony_ci if (der_len < 0 || (size_t)der_len > len) 191d4afb5ceSopenharmony_ci return -1; 192d4afb5ceSopenharmony_ci 193d4afb5ceSopenharmony_ci der_len = i2d_X509(x509, &tmp); 194d4afb5ceSopenharmony_ci if (der_len < 0) 195d4afb5ceSopenharmony_ci return -1; 196d4afb5ceSopenharmony_ci 197d4afb5ceSopenharmony_ci return 0; 198d4afb5ceSopenharmony_ci } 199d4afb5ceSopenharmony_ci 200d4afb5ceSopenharmony_ci#ifndef USE_WOLFSSL 201d4afb5ceSopenharmony_ci 202d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID: 203d4afb5ceSopenharmony_ci loc = X509_get_ext_by_NID(x509, NID_authority_key_identifier, -1); 204d4afb5ceSopenharmony_ci if (loc < 0) 205d4afb5ceSopenharmony_ci return 1; 206d4afb5ceSopenharmony_ci 207d4afb5ceSopenharmony_ci ext = X509_get_ext(x509, (int)loc); 208d4afb5ceSopenharmony_ci if (!ext) 209d4afb5ceSopenharmony_ci return 1; 210d4afb5ceSopenharmony_ci#ifndef USE_WOLFSSL 211d4afb5ceSopenharmony_ci akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext); 212d4afb5ceSopenharmony_ci#else 213d4afb5ceSopenharmony_ci akid = (AUTHORITY_KEYID *)wolfSSL_X509V3_EXT_d2i(ext); 214d4afb5ceSopenharmony_ci#endif 215d4afb5ceSopenharmony_ci if (!akid || !akid->keyid) 216d4afb5ceSopenharmony_ci return 1; 217d4afb5ceSopenharmony_ci val = akid->keyid; 218d4afb5ceSopenharmony_ci dp = (const unsigned char *)val->data; 219d4afb5ceSopenharmony_ci xlen = val->length; 220d4afb5ceSopenharmony_ci 221d4afb5ceSopenharmony_ci buf->ns.len = (int)xlen; 222d4afb5ceSopenharmony_ci if (len < (size_t)buf->ns.len) 223d4afb5ceSopenharmony_ci return -1; 224d4afb5ceSopenharmony_ci 225d4afb5ceSopenharmony_ci memcpy(buf->ns.name, dp, (size_t)buf->ns.len); 226d4afb5ceSopenharmony_ci 227d4afb5ceSopenharmony_ci AUTHORITY_KEYID_free(akid); 228d4afb5ceSopenharmony_ci break; 229d4afb5ceSopenharmony_ci 230d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_ISSUER: 231d4afb5ceSopenharmony_ci loc = X509_get_ext_by_NID(x509, NID_authority_key_identifier, -1); 232d4afb5ceSopenharmony_ci if (loc < 0) 233d4afb5ceSopenharmony_ci return 1; 234d4afb5ceSopenharmony_ci 235d4afb5ceSopenharmony_ci ext = X509_get_ext(x509, (int)loc); 236d4afb5ceSopenharmony_ci if (!ext) 237d4afb5ceSopenharmony_ci return 1; 238d4afb5ceSopenharmony_ci 239d4afb5ceSopenharmony_ci#ifndef USE_WOLFSSL 240d4afb5ceSopenharmony_ci akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext); 241d4afb5ceSopenharmony_ci#else 242d4afb5ceSopenharmony_ci akid = (AUTHORITY_KEYID *)wolfSSL_X509V3_EXT_d2i(ext); 243d4afb5ceSopenharmony_ci#endif 244d4afb5ceSopenharmony_ci if (!akid || !akid->issuer) 245d4afb5ceSopenharmony_ci return 1; 246d4afb5ceSopenharmony_ci 247d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_OPENSSL_STACK) 248d4afb5ceSopenharmony_ci { 249d4afb5ceSopenharmony_ci const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext); 250d4afb5ceSopenharmony_ci STACK_OF(CONF_VALUE) *cv; 251d4afb5ceSopenharmony_ci int j; 252d4afb5ceSopenharmony_ci 253d4afb5ceSopenharmony_ci cv = i2v_GENERAL_NAMES((X509V3_EXT_METHOD*)method, akid->issuer, NULL); 254d4afb5ceSopenharmony_ci if (!cv) 255d4afb5ceSopenharmony_ci goto bail_ak; 256d4afb5ceSopenharmony_ci 257d4afb5ceSopenharmony_ci for (j = 0; j < OPENSSL_sk_num((const OPENSSL_STACK *)&cv); j++) { 258d4afb5ceSopenharmony_ci CONF_VALUE *nval = OPENSSL_sk_value((const OPENSSL_STACK *)&cv, j); 259d4afb5ceSopenharmony_ci size_t ln = (nval->name ? strlen(nval->name) : 0), 260d4afb5ceSopenharmony_ci lv = (nval->value ? strlen(nval->value) : 0), 261d4afb5ceSopenharmony_ci l = ln + lv; 262d4afb5ceSopenharmony_ci 263d4afb5ceSopenharmony_ci if (len > l) { 264d4afb5ceSopenharmony_ci if (nval->name) 265d4afb5ceSopenharmony_ci memcpy(buf->ns.name + buf->ns.len, nval->name, ln); 266d4afb5ceSopenharmony_ci if (nval->value) 267d4afb5ceSopenharmony_ci memcpy(buf->ns.name + buf->ns.len + ln, nval->value, lv); 268d4afb5ceSopenharmony_ci buf->ns.len = (int)((size_t)buf->ns.len + l); 269d4afb5ceSopenharmony_ci len -= l; 270d4afb5ceSopenharmony_ci buf->ns.name[buf->ns.len] = '\0'; 271d4afb5ceSopenharmony_ci 272d4afb5ceSopenharmony_ci r = 0; 273d4afb5ceSopenharmony_ci } 274d4afb5ceSopenharmony_ci } 275d4afb5ceSopenharmony_ci } 276d4afb5ceSopenharmony_ci 277d4afb5ceSopenharmony_cibail_ak: 278d4afb5ceSopenharmony_ci#endif 279d4afb5ceSopenharmony_ci AUTHORITY_KEYID_free(akid); 280d4afb5ceSopenharmony_ci 281d4afb5ceSopenharmony_ci return r; 282d4afb5ceSopenharmony_ci 283d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_AUTHORITY_KEY_ID_SERIAL: 284d4afb5ceSopenharmony_ci loc = X509_get_ext_by_NID(x509, NID_authority_key_identifier, -1); 285d4afb5ceSopenharmony_ci if (loc < 0) 286d4afb5ceSopenharmony_ci return 1; 287d4afb5ceSopenharmony_ci 288d4afb5ceSopenharmony_ci ext = X509_get_ext(x509, (int)loc); 289d4afb5ceSopenharmony_ci if (!ext) 290d4afb5ceSopenharmony_ci return 1; 291d4afb5ceSopenharmony_ci akid = (AUTHORITY_KEYID *)X509V3_EXT_d2i(ext); 292d4afb5ceSopenharmony_ci if (!akid || !akid->serial) 293d4afb5ceSopenharmony_ci return 1; 294d4afb5ceSopenharmony_ci 295d4afb5ceSopenharmony_ci#if 0 296d4afb5ceSopenharmony_ci // need to handle blobs, and ASN1_INTEGER_get_uint64 not 297d4afb5ceSopenharmony_ci // available on older openssl 298d4afb5ceSopenharmony_ci { 299d4afb5ceSopenharmony_ci uint64_t res; 300d4afb5ceSopenharmony_ci if (ASN1_INTEGER_get_uint64(&res, akid->serial) != 1) 301d4afb5ceSopenharmony_ci break; 302d4afb5ceSopenharmony_ci buf->ns.len = lws_snprintf(buf->ns.name, len, "%llu", 303d4afb5ceSopenharmony_ci (unsigned long long)res); 304d4afb5ceSopenharmony_ci } 305d4afb5ceSopenharmony_ci#endif 306d4afb5ceSopenharmony_ci break; 307d4afb5ceSopenharmony_ci 308d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_SUBJECT_KEY_ID: 309d4afb5ceSopenharmony_ci 310d4afb5ceSopenharmony_ci loc = X509_get_ext_by_NID(x509, NID_subject_key_identifier, -1); 311d4afb5ceSopenharmony_ci if (loc < 0) 312d4afb5ceSopenharmony_ci return 1; 313d4afb5ceSopenharmony_ci 314d4afb5ceSopenharmony_ci ext = X509_get_ext(x509, (int)loc); 315d4afb5ceSopenharmony_ci if (!ext) 316d4afb5ceSopenharmony_ci return 1; 317d4afb5ceSopenharmony_ci 318d4afb5ceSopenharmony_ci val = X509_EXTENSION_get_data(ext); 319d4afb5ceSopenharmony_ci if (!val) 320d4afb5ceSopenharmony_ci return 1; 321d4afb5ceSopenharmony_ci 322d4afb5ceSopenharmony_ci#if defined(USE_WOLFSSL) 323d4afb5ceSopenharmony_ci return 1; 324d4afb5ceSopenharmony_ci#else 325d4afb5ceSopenharmony_ci dp = (const unsigned char *)val->data; 326d4afb5ceSopenharmony_ci 327d4afb5ceSopenharmony_ci if (ASN1_get_object(&dp, &xlen, 328d4afb5ceSopenharmony_ci &tag, &xclass, val->length) & 0x80) 329d4afb5ceSopenharmony_ci return -1; 330d4afb5ceSopenharmony_ci 331d4afb5ceSopenharmony_ci if (tag != V_ASN1_OCTET_STRING) { 332d4afb5ceSopenharmony_ci lwsl_notice("not octet string %d\n", (int)tag); 333d4afb5ceSopenharmony_ci return 1; 334d4afb5ceSopenharmony_ci } 335d4afb5ceSopenharmony_ci#endif 336d4afb5ceSopenharmony_ci buf->ns.len = (int)xlen; 337d4afb5ceSopenharmony_ci if (len < (size_t)buf->ns.len) 338d4afb5ceSopenharmony_ci return -1; 339d4afb5ceSopenharmony_ci 340d4afb5ceSopenharmony_ci memcpy(buf->ns.name, dp, (size_t)buf->ns.len); 341d4afb5ceSopenharmony_ci break; 342d4afb5ceSopenharmony_ci#endif 343d4afb5ceSopenharmony_ci 344d4afb5ceSopenharmony_ci default: 345d4afb5ceSopenharmony_ci return -1; 346d4afb5ceSopenharmony_ci } 347d4afb5ceSopenharmony_ci 348d4afb5ceSopenharmony_ci return 0; 349d4afb5ceSopenharmony_ci} 350d4afb5ceSopenharmony_ci 351d4afb5ceSopenharmony_ciint 352d4afb5ceSopenharmony_cilws_x509_info(struct lws_x509_cert *x509, enum lws_tls_cert_info type, 353d4afb5ceSopenharmony_ci union lws_tls_cert_info_results *buf, size_t len) 354d4afb5ceSopenharmony_ci{ 355d4afb5ceSopenharmony_ci return lws_tls_openssl_cert_info(x509->cert, type, buf, len); 356d4afb5ceSopenharmony_ci} 357d4afb5ceSopenharmony_ci 358d4afb5ceSopenharmony_ci#if defined(LWS_WITH_NETWORK) 359d4afb5ceSopenharmony_ciint 360d4afb5ceSopenharmony_cilws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type, 361d4afb5ceSopenharmony_ci union lws_tls_cert_info_results *buf, size_t len) 362d4afb5ceSopenharmony_ci{ 363d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_SSL_CTX_get0_certificate) 364d4afb5ceSopenharmony_ci X509 *x509 = SSL_CTX_get0_certificate(vhost->tls.ssl_ctx); 365d4afb5ceSopenharmony_ci 366d4afb5ceSopenharmony_ci return lws_tls_openssl_cert_info(x509, type, buf, len); 367d4afb5ceSopenharmony_ci#else 368d4afb5ceSopenharmony_ci lwsl_notice("openssl is too old to support %s\n", __func__); 369d4afb5ceSopenharmony_ci 370d4afb5ceSopenharmony_ci return -1; 371d4afb5ceSopenharmony_ci#endif 372d4afb5ceSopenharmony_ci} 373d4afb5ceSopenharmony_ci 374d4afb5ceSopenharmony_ci 375d4afb5ceSopenharmony_ci 376d4afb5ceSopenharmony_ciint 377d4afb5ceSopenharmony_cilws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type, 378d4afb5ceSopenharmony_ci union lws_tls_cert_info_results *buf, size_t len) 379d4afb5ceSopenharmony_ci{ 380d4afb5ceSopenharmony_ci int rc = 0; 381d4afb5ceSopenharmony_ci X509 *x509; 382d4afb5ceSopenharmony_ci 383d4afb5ceSopenharmony_ci wsi = lws_get_network_wsi(wsi); 384d4afb5ceSopenharmony_ci 385d4afb5ceSopenharmony_ci x509 = SSL_get_peer_certificate(wsi->tls.ssl); 386d4afb5ceSopenharmony_ci 387d4afb5ceSopenharmony_ci if (!x509) { 388d4afb5ceSopenharmony_ci lwsl_debug("no peer cert\n"); 389d4afb5ceSopenharmony_ci 390d4afb5ceSopenharmony_ci return -1; 391d4afb5ceSopenharmony_ci } 392d4afb5ceSopenharmony_ci 393d4afb5ceSopenharmony_ci switch (type) { 394d4afb5ceSopenharmony_ci case LWS_TLS_CERT_INFO_VERIFIED: 395d4afb5ceSopenharmony_ci buf->verified = SSL_get_verify_result(wsi->tls.ssl) == 396d4afb5ceSopenharmony_ci X509_V_OK; 397d4afb5ceSopenharmony_ci break; 398d4afb5ceSopenharmony_ci default: 399d4afb5ceSopenharmony_ci rc = lws_tls_openssl_cert_info(x509, type, buf, len); 400d4afb5ceSopenharmony_ci } 401d4afb5ceSopenharmony_ci 402d4afb5ceSopenharmony_ci X509_free(x509); 403d4afb5ceSopenharmony_ci 404d4afb5ceSopenharmony_ci return rc; 405d4afb5ceSopenharmony_ci} 406d4afb5ceSopenharmony_ci#endif 407d4afb5ceSopenharmony_ci 408d4afb5ceSopenharmony_ciint 409d4afb5ceSopenharmony_cilws_x509_create(struct lws_x509_cert **x509) 410d4afb5ceSopenharmony_ci{ 411d4afb5ceSopenharmony_ci *x509 = lws_malloc(sizeof(**x509), __func__); 412d4afb5ceSopenharmony_ci if (*x509) 413d4afb5ceSopenharmony_ci (*x509)->cert = NULL; 414d4afb5ceSopenharmony_ci 415d4afb5ceSopenharmony_ci return !(*x509); 416d4afb5ceSopenharmony_ci} 417d4afb5ceSopenharmony_ci 418d4afb5ceSopenharmony_ciint 419d4afb5ceSopenharmony_cilws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len) 420d4afb5ceSopenharmony_ci{ 421d4afb5ceSopenharmony_ci BIO* bio = BIO_new(BIO_s_mem()); 422d4afb5ceSopenharmony_ci 423d4afb5ceSopenharmony_ci BIO_write(bio, pem, (int)len); 424d4afb5ceSopenharmony_ci x509->cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); 425d4afb5ceSopenharmony_ci BIO_free(bio); 426d4afb5ceSopenharmony_ci if (!x509->cert) { 427d4afb5ceSopenharmony_ci lwsl_err("%s: unable to parse PEM cert\n", __func__); 428d4afb5ceSopenharmony_ci lws_tls_err_describe_clear(); 429d4afb5ceSopenharmony_ci 430d4afb5ceSopenharmony_ci return -1; 431d4afb5ceSopenharmony_ci } 432d4afb5ceSopenharmony_ci 433d4afb5ceSopenharmony_ci return 0; 434d4afb5ceSopenharmony_ci} 435d4afb5ceSopenharmony_ci 436d4afb5ceSopenharmony_ciint 437d4afb5ceSopenharmony_cilws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted, 438d4afb5ceSopenharmony_ci const char *common_name) 439d4afb5ceSopenharmony_ci{ 440d4afb5ceSopenharmony_ci char c[32], *p; 441d4afb5ceSopenharmony_ci int ret; 442d4afb5ceSopenharmony_ci 443d4afb5ceSopenharmony_ci if (common_name) { 444d4afb5ceSopenharmony_ci X509_NAME *xn = X509_get_subject_name(x509->cert); 445d4afb5ceSopenharmony_ci if (!xn) 446d4afb5ceSopenharmony_ci return -1; 447d4afb5ceSopenharmony_ci X509_NAME_oneline(xn, c, (int)sizeof(c) - 2); 448d4afb5ceSopenharmony_ci p = strstr(c, "/CN="); 449d4afb5ceSopenharmony_ci if (p) 450d4afb5ceSopenharmony_ci p = p + 4; 451d4afb5ceSopenharmony_ci else 452d4afb5ceSopenharmony_ci p = c; 453d4afb5ceSopenharmony_ci 454d4afb5ceSopenharmony_ci if (strcmp(p, common_name)) { 455d4afb5ceSopenharmony_ci lwsl_err("%s: common name mismatch\n", __func__); 456d4afb5ceSopenharmony_ci return -1; 457d4afb5ceSopenharmony_ci } 458d4afb5ceSopenharmony_ci } 459d4afb5ceSopenharmony_ci 460d4afb5ceSopenharmony_ci ret = X509_check_issued(trusted->cert, x509->cert); 461d4afb5ceSopenharmony_ci if (ret != X509_V_OK) { 462d4afb5ceSopenharmony_ci lwsl_err("%s: unable to verify cert relationship\n", __func__); 463d4afb5ceSopenharmony_ci lws_tls_err_describe_clear(); 464d4afb5ceSopenharmony_ci 465d4afb5ceSopenharmony_ci return -1; 466d4afb5ceSopenharmony_ci } 467d4afb5ceSopenharmony_ci 468d4afb5ceSopenharmony_ci return 0; 469d4afb5ceSopenharmony_ci} 470d4afb5ceSopenharmony_ci 471d4afb5ceSopenharmony_ci#if defined(LWS_WITH_JOSE) 472d4afb5ceSopenharmony_ciint 473d4afb5ceSopenharmony_cilws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509, 474d4afb5ceSopenharmony_ci const char *curves, int rsa_min_bits) 475d4afb5ceSopenharmony_ci{ 476d4afb5ceSopenharmony_ci int id, n, ret = -1, count; 477d4afb5ceSopenharmony_ci ASN1_OBJECT *obj = NULL; 478d4afb5ceSopenharmony_ci const EC_POINT *ecpoint; 479d4afb5ceSopenharmony_ci const EC_GROUP *ecgroup; 480d4afb5ceSopenharmony_ci EC_KEY *ecpub = NULL; 481d4afb5ceSopenharmony_ci X509_PUBKEY *pubkey; 482d4afb5ceSopenharmony_ci RSA *rsapub = NULL; 483d4afb5ceSopenharmony_ci BIGNUM *mpi[4]; 484d4afb5ceSopenharmony_ci EVP_PKEY *pkey; 485d4afb5ceSopenharmony_ci 486d4afb5ceSopenharmony_ci memset(jwk, 0, sizeof(*jwk)); 487d4afb5ceSopenharmony_ci 488d4afb5ceSopenharmony_ci pubkey = X509_get_X509_PUBKEY(x509->cert); 489d4afb5ceSopenharmony_ci if (!pubkey) { 490d4afb5ceSopenharmony_ci lwsl_err("%s: missing pubkey alg in cert\n", __func__); 491d4afb5ceSopenharmony_ci 492d4afb5ceSopenharmony_ci goto bail; 493d4afb5ceSopenharmony_ci } 494d4afb5ceSopenharmony_ci 495d4afb5ceSopenharmony_ci if (X509_PUBKEY_get0_param(&obj, NULL, NULL, NULL, pubkey) != 1) { 496d4afb5ceSopenharmony_ci lwsl_err("%s: missing pubkey alg in cert\n", __func__); 497d4afb5ceSopenharmony_ci 498d4afb5ceSopenharmony_ci goto bail; 499d4afb5ceSopenharmony_ci } 500d4afb5ceSopenharmony_ci 501d4afb5ceSopenharmony_ci id = OBJ_obj2nid(obj); 502d4afb5ceSopenharmony_ci if (id == NID_undef) { 503d4afb5ceSopenharmony_ci lwsl_err("%s: missing pubkey alg in cert\n", __func__); 504d4afb5ceSopenharmony_ci 505d4afb5ceSopenharmony_ci goto bail; 506d4afb5ceSopenharmony_ci } 507d4afb5ceSopenharmony_ci 508d4afb5ceSopenharmony_ci lwsl_debug("%s: key type %d \"%s\"\n", __func__, id, OBJ_nid2ln(id)); 509d4afb5ceSopenharmony_ci 510d4afb5ceSopenharmony_ci pkey = X509_get_pubkey(x509->cert); 511d4afb5ceSopenharmony_ci if (!pkey) { 512d4afb5ceSopenharmony_ci lwsl_notice("%s: unable to extract pubkey", __func__); 513d4afb5ceSopenharmony_ci 514d4afb5ceSopenharmony_ci goto bail; 515d4afb5ceSopenharmony_ci } 516d4afb5ceSopenharmony_ci 517d4afb5ceSopenharmony_ci switch (id) { 518d4afb5ceSopenharmony_ci case NID_X9_62_id_ecPublicKey: 519d4afb5ceSopenharmony_ci lwsl_debug("%s: EC key\n", __func__); 520d4afb5ceSopenharmony_ci jwk->kty = LWS_GENCRYPTO_KTY_EC; 521d4afb5ceSopenharmony_ci 522d4afb5ceSopenharmony_ci if (!curves) { 523d4afb5ceSopenharmony_ci lwsl_err("%s: ec curves not allowed\n", __func__); 524d4afb5ceSopenharmony_ci 525d4afb5ceSopenharmony_ci goto bail1; 526d4afb5ceSopenharmony_ci } 527d4afb5ceSopenharmony_ci 528d4afb5ceSopenharmony_ci ecpub = EVP_PKEY_get1_EC_KEY(pkey); 529d4afb5ceSopenharmony_ci if (!ecpub) { 530d4afb5ceSopenharmony_ci lwsl_notice("%s: missing EC pubkey\n", __func__); 531d4afb5ceSopenharmony_ci 532d4afb5ceSopenharmony_ci goto bail1; 533d4afb5ceSopenharmony_ci } 534d4afb5ceSopenharmony_ci 535d4afb5ceSopenharmony_ci ecpoint = EC_KEY_get0_public_key(ecpub); 536d4afb5ceSopenharmony_ci if (!ecpoint) { 537d4afb5ceSopenharmony_ci lwsl_err("%s: EC_KEY_get0_public_key failed\n", __func__); 538d4afb5ceSopenharmony_ci goto bail2; 539d4afb5ceSopenharmony_ci } 540d4afb5ceSopenharmony_ci 541d4afb5ceSopenharmony_ci ecgroup = EC_KEY_get0_group(ecpub); 542d4afb5ceSopenharmony_ci if (!ecgroup) { 543d4afb5ceSopenharmony_ci lwsl_err("%s: EC_KEY_get0_group failed\n", __func__); 544d4afb5ceSopenharmony_ci goto bail2; 545d4afb5ceSopenharmony_ci } 546d4afb5ceSopenharmony_ci 547d4afb5ceSopenharmony_ci /* validate the curve against ones we allow */ 548d4afb5ceSopenharmony_ci 549d4afb5ceSopenharmony_ci if (lws_genec_confirm_curve_allowed_by_tls_id(curves, 550d4afb5ceSopenharmony_ci EC_GROUP_get_curve_name(ecgroup), jwk)) 551d4afb5ceSopenharmony_ci /* already logged */ 552d4afb5ceSopenharmony_ci goto bail2; 553d4afb5ceSopenharmony_ci 554d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_EC_KEYEL_CRV] = NULL; 555d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_EC_KEYEL_X] = BN_new(); /* X */ 556d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_EC_KEYEL_D] = NULL; 557d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = BN_new(); /* Y */ 558d4afb5ceSopenharmony_ci 559d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_EC_POINT_get_affine_coordinates) 560d4afb5ceSopenharmony_ci if (EC_POINT_get_affine_coordinates(ecgroup, ecpoint, 561d4afb5ceSopenharmony_ci#else 562d4afb5ceSopenharmony_ci if (EC_POINT_get_affine_coordinates_GFp(ecgroup, ecpoint, 563d4afb5ceSopenharmony_ci#endif 564d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_EC_KEYEL_X], 565d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_EC_KEYEL_Y], 566d4afb5ceSopenharmony_ci NULL) != 1) { 567d4afb5ceSopenharmony_ci BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]); 568d4afb5ceSopenharmony_ci BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]); 569d4afb5ceSopenharmony_ci lwsl_err("%s: EC_POINT_get_aff failed\n", __func__); 570d4afb5ceSopenharmony_ci goto bail2; 571d4afb5ceSopenharmony_ci } 572d4afb5ceSopenharmony_ci count = LWS_GENCRYPTO_EC_KEYEL_COUNT; 573d4afb5ceSopenharmony_ci n = LWS_GENCRYPTO_EC_KEYEL_X; 574d4afb5ceSopenharmony_ci break; 575d4afb5ceSopenharmony_ci 576d4afb5ceSopenharmony_ci case NID_rsaEncryption: 577d4afb5ceSopenharmony_ci lwsl_debug("%s: rsa key\n", __func__); 578d4afb5ceSopenharmony_ci jwk->kty = LWS_GENCRYPTO_KTY_RSA; 579d4afb5ceSopenharmony_ci 580d4afb5ceSopenharmony_ci rsapub = EVP_PKEY_get1_RSA(pkey); 581d4afb5ceSopenharmony_ci if (!rsapub) { 582d4afb5ceSopenharmony_ci lwsl_notice("%s: missing RSA pubkey\n", __func__); 583d4afb5ceSopenharmony_ci 584d4afb5ceSopenharmony_ci goto bail1; 585d4afb5ceSopenharmony_ci } 586d4afb5ceSopenharmony_ci 587d4afb5ceSopenharmony_ci if ((size_t)RSA_size(rsapub) * 8 < (size_t)rsa_min_bits) { 588d4afb5ceSopenharmony_ci lwsl_err("%s: key bits %d less than minimum %d\n", 589d4afb5ceSopenharmony_ci __func__, RSA_size(rsapub) * 8, rsa_min_bits); 590d4afb5ceSopenharmony_ci 591d4afb5ceSopenharmony_ci goto bail2; 592d4afb5ceSopenharmony_ci } 593d4afb5ceSopenharmony_ci 594d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_RSA_SET0_KEY) 595d4afb5ceSopenharmony_ci /* we don't need d... but the api wants to write it */ 596d4afb5ceSopenharmony_ci RSA_get0_key(rsapub, 597d4afb5ceSopenharmony_ci (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_N], 598d4afb5ceSopenharmony_ci (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_E], 599d4afb5ceSopenharmony_ci (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_D]); 600d4afb5ceSopenharmony_ci#else 601d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = rsapub->e; 602d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = rsapub->n; 603d4afb5ceSopenharmony_ci mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = NULL; 604d4afb5ceSopenharmony_ci#endif 605d4afb5ceSopenharmony_ci count = LWS_GENCRYPTO_RSA_KEYEL_D; 606d4afb5ceSopenharmony_ci n = LWS_GENCRYPTO_RSA_KEYEL_E; 607d4afb5ceSopenharmony_ci break; 608d4afb5ceSopenharmony_ci default: 609d4afb5ceSopenharmony_ci lwsl_err("%s: unknown NID\n", __func__); 610d4afb5ceSopenharmony_ci goto bail2; 611d4afb5ceSopenharmony_ci } 612d4afb5ceSopenharmony_ci 613d4afb5ceSopenharmony_ci for (; n < count; n++) { 614d4afb5ceSopenharmony_ci if (!mpi[n]) 615d4afb5ceSopenharmony_ci continue; 616d4afb5ceSopenharmony_ci jwk->e[n].len = (unsigned int)BN_num_bytes(mpi[n]); 617d4afb5ceSopenharmony_ci jwk->e[n].buf = lws_malloc(jwk->e[n].len, "certkeyimp"); 618d4afb5ceSopenharmony_ci if (!jwk->e[n].buf) { 619d4afb5ceSopenharmony_ci if (id == NID_X9_62_id_ecPublicKey) { 620d4afb5ceSopenharmony_ci BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]); 621d4afb5ceSopenharmony_ci BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]); 622d4afb5ceSopenharmony_ci } 623d4afb5ceSopenharmony_ci goto bail2; 624d4afb5ceSopenharmony_ci } 625d4afb5ceSopenharmony_ci BN_bn2bin(mpi[n], jwk->e[n].buf); 626d4afb5ceSopenharmony_ci } 627d4afb5ceSopenharmony_ci 628d4afb5ceSopenharmony_ci if (id == NID_X9_62_id_ecPublicKey) { 629d4afb5ceSopenharmony_ci BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]); 630d4afb5ceSopenharmony_ci BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]); 631d4afb5ceSopenharmony_ci } 632d4afb5ceSopenharmony_ci 633d4afb5ceSopenharmony_ci ret = 0; 634d4afb5ceSopenharmony_ci 635d4afb5ceSopenharmony_cibail2: 636d4afb5ceSopenharmony_ci if (id == NID_X9_62_id_ecPublicKey) 637d4afb5ceSopenharmony_ci EC_KEY_free(ecpub); 638d4afb5ceSopenharmony_ci else 639d4afb5ceSopenharmony_ci RSA_free(rsapub); 640d4afb5ceSopenharmony_ci 641d4afb5ceSopenharmony_cibail1: 642d4afb5ceSopenharmony_ci EVP_PKEY_free(pkey); 643d4afb5ceSopenharmony_cibail: 644d4afb5ceSopenharmony_ci /* jwk destroy will clean any partial state */ 645d4afb5ceSopenharmony_ci if (ret) 646d4afb5ceSopenharmony_ci lws_jwk_destroy(jwk); 647d4afb5ceSopenharmony_ci 648d4afb5ceSopenharmony_ci return ret; 649d4afb5ceSopenharmony_ci} 650d4afb5ceSopenharmony_ci 651d4afb5ceSopenharmony_cistatic int 652d4afb5ceSopenharmony_cilws_x509_jwk_privkey_pem_pp_cb(char *buf, int size, int rwflag, void *u) 653d4afb5ceSopenharmony_ci{ 654d4afb5ceSopenharmony_ci const char *pp = (const char *)u; 655d4afb5ceSopenharmony_ci size_t n = strlen(pp); 656d4afb5ceSopenharmony_ci 657d4afb5ceSopenharmony_ci if ((int)n > size - 1) 658d4afb5ceSopenharmony_ci return -1; 659d4afb5ceSopenharmony_ci 660d4afb5ceSopenharmony_ci memcpy(buf, pp, n + 1); 661d4afb5ceSopenharmony_ci 662d4afb5ceSopenharmony_ci return (int)n; 663d4afb5ceSopenharmony_ci} 664d4afb5ceSopenharmony_ci 665d4afb5ceSopenharmony_ciint 666d4afb5ceSopenharmony_cilws_x509_jwk_privkey_pem(struct lws_context *cx, struct lws_jwk *jwk, 667d4afb5ceSopenharmony_ci void *pem, size_t len, const char *passphrase) 668d4afb5ceSopenharmony_ci{ 669d4afb5ceSopenharmony_ci BIO* bio = BIO_new(BIO_s_mem()); 670d4afb5ceSopenharmony_ci BIGNUM *mpi, *dummy[6]; 671d4afb5ceSopenharmony_ci EVP_PKEY *pkey = NULL; 672d4afb5ceSopenharmony_ci EC_KEY *ecpriv = NULL; 673d4afb5ceSopenharmony_ci RSA *rsapriv = NULL; 674d4afb5ceSopenharmony_ci const BIGNUM *cmpi; 675d4afb5ceSopenharmony_ci int n, m, ret = -1; 676d4afb5ceSopenharmony_ci 677d4afb5ceSopenharmony_ci BIO_write(bio, pem, (int)len); 678d4afb5ceSopenharmony_ci PEM_read_bio_PrivateKey(bio, &pkey, lws_x509_jwk_privkey_pem_pp_cb, 679d4afb5ceSopenharmony_ci (void *)passphrase); 680d4afb5ceSopenharmony_ci BIO_free(bio); 681d4afb5ceSopenharmony_ci lws_explicit_bzero((void *)pem, len); 682d4afb5ceSopenharmony_ci if (!pkey) { 683d4afb5ceSopenharmony_ci lwsl_err("%s: unable to parse PEM privkey\n", __func__); 684d4afb5ceSopenharmony_ci lws_tls_err_describe_clear(); 685d4afb5ceSopenharmony_ci 686d4afb5ceSopenharmony_ci return -1; 687d4afb5ceSopenharmony_ci } 688d4afb5ceSopenharmony_ci 689d4afb5ceSopenharmony_ci /* confirm the key type matches the existing jwk situation */ 690d4afb5ceSopenharmony_ci 691d4afb5ceSopenharmony_ci switch (jwk->kty) { 692d4afb5ceSopenharmony_ci case LWS_GENCRYPTO_KTY_EC: 693d4afb5ceSopenharmony_ci if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) { 694d4afb5ceSopenharmony_ci lwsl_err("%s: jwk is EC but privkey isn't\n", __func__); 695d4afb5ceSopenharmony_ci 696d4afb5ceSopenharmony_ci goto bail; 697d4afb5ceSopenharmony_ci } 698d4afb5ceSopenharmony_ci ecpriv = EVP_PKEY_get1_EC_KEY(pkey); 699d4afb5ceSopenharmony_ci if (!ecpriv) { 700d4afb5ceSopenharmony_ci lwsl_notice("%s: missing EC key\n", __func__); 701d4afb5ceSopenharmony_ci 702d4afb5ceSopenharmony_ci goto bail; 703d4afb5ceSopenharmony_ci } 704d4afb5ceSopenharmony_ci 705d4afb5ceSopenharmony_ci cmpi = EC_KEY_get0_private_key(ecpriv); 706d4afb5ceSopenharmony_ci 707d4afb5ceSopenharmony_ci /* quick size check first */ 708d4afb5ceSopenharmony_ci 709d4afb5ceSopenharmony_ci n = BN_num_bytes(cmpi); 710d4afb5ceSopenharmony_ci if (jwk->e[LWS_GENCRYPTO_EC_KEYEL_Y].len != (uint32_t)n) { 711d4afb5ceSopenharmony_ci lwsl_err("%s: jwk key size doesn't match\n", __func__); 712d4afb5ceSopenharmony_ci 713d4afb5ceSopenharmony_ci goto bail1; 714d4afb5ceSopenharmony_ci } 715d4afb5ceSopenharmony_ci 716d4afb5ceSopenharmony_ci /* TODO.. check public curve / group + point */ 717d4afb5ceSopenharmony_ci 718d4afb5ceSopenharmony_ci jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len = (unsigned int)n; 719d4afb5ceSopenharmony_ci jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf = lws_malloc((unsigned int)n, "ec"); 720d4afb5ceSopenharmony_ci if (!jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf) 721d4afb5ceSopenharmony_ci goto bail1; 722d4afb5ceSopenharmony_ci 723d4afb5ceSopenharmony_ci m = BN_bn2binpad(cmpi, jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf, 724d4afb5ceSopenharmony_ci (int32_t)jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len); 725d4afb5ceSopenharmony_ci if ((unsigned int)m != (unsigned int)BN_num_bytes(cmpi)) 726d4afb5ceSopenharmony_ci goto bail1; 727d4afb5ceSopenharmony_ci 728d4afb5ceSopenharmony_ci break; 729d4afb5ceSopenharmony_ci 730d4afb5ceSopenharmony_ci case LWS_GENCRYPTO_KTY_RSA: 731d4afb5ceSopenharmony_ci if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_RSA) { 732d4afb5ceSopenharmony_ci lwsl_err("%s: RSA jwk, non-RSA privkey\n", __func__); 733d4afb5ceSopenharmony_ci 734d4afb5ceSopenharmony_ci goto bail; 735d4afb5ceSopenharmony_ci } 736d4afb5ceSopenharmony_ci rsapriv = EVP_PKEY_get1_RSA(pkey); 737d4afb5ceSopenharmony_ci if (!rsapriv) { 738d4afb5ceSopenharmony_ci lwsl_notice("%s: missing RSA key\n", __func__); 739d4afb5ceSopenharmony_ci 740d4afb5ceSopenharmony_ci goto bail; 741d4afb5ceSopenharmony_ci } 742d4afb5ceSopenharmony_ci 743d4afb5ceSopenharmony_ci#if defined(LWS_HAVE_RSA_SET0_KEY) && !defined(USE_WOLFSSL) 744d4afb5ceSopenharmony_ci RSA_get0_key(rsapriv, (const BIGNUM **)&dummy[0], /* n */ 745d4afb5ceSopenharmony_ci (const BIGNUM **)&dummy[1], /* e */ 746d4afb5ceSopenharmony_ci (const BIGNUM **)&mpi); /* d */ 747d4afb5ceSopenharmony_ci RSA_get0_factors(rsapriv, (const BIGNUM **)&dummy[4], /* p */ 748d4afb5ceSopenharmony_ci (const BIGNUM **)&dummy[5]); /* q */ 749d4afb5ceSopenharmony_ci#else 750d4afb5ceSopenharmony_ci dummy[0] = rsapriv->n; 751d4afb5ceSopenharmony_ci dummy[1] = rsapriv->e; 752d4afb5ceSopenharmony_ci dummy[4] = rsapriv->p; 753d4afb5ceSopenharmony_ci dummy[5] = rsapriv->q; 754d4afb5ceSopenharmony_ci mpi = rsapriv->d; 755d4afb5ceSopenharmony_ci#endif 756d4afb5ceSopenharmony_ci 757d4afb5ceSopenharmony_ci /* quick size check first */ 758d4afb5ceSopenharmony_ci 759d4afb5ceSopenharmony_ci n = BN_num_bytes(mpi); 760d4afb5ceSopenharmony_ci if (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len != (uint32_t)n) { 761d4afb5ceSopenharmony_ci lwsl_err("%s: jwk key size doesn't match\n", __func__); 762d4afb5ceSopenharmony_ci 763d4afb5ceSopenharmony_ci goto bail1; 764d4afb5ceSopenharmony_ci } 765d4afb5ceSopenharmony_ci 766d4afb5ceSopenharmony_ci /* then check that n & e match what we got from the cert */ 767d4afb5ceSopenharmony_ci 768d4afb5ceSopenharmony_ci dummy[2] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].buf, 769d4afb5ceSopenharmony_ci (int32_t)jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len, 770d4afb5ceSopenharmony_ci NULL); 771d4afb5ceSopenharmony_ci dummy[3] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].buf, 772d4afb5ceSopenharmony_ci (int32_t)jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].len, 773d4afb5ceSopenharmony_ci NULL); 774d4afb5ceSopenharmony_ci 775d4afb5ceSopenharmony_ci m = BN_cmp(dummy[2], dummy[0]) | BN_cmp(dummy[3], dummy[1]); 776d4afb5ceSopenharmony_ci BN_clear_free(dummy[2]); 777d4afb5ceSopenharmony_ci BN_clear_free(dummy[3]); 778d4afb5ceSopenharmony_ci if (m) { 779d4afb5ceSopenharmony_ci lwsl_err("%s: privkey doesn't match jwk pubkey\n", 780d4afb5ceSopenharmony_ci __func__); 781d4afb5ceSopenharmony_ci 782d4afb5ceSopenharmony_ci goto bail1; 783d4afb5ceSopenharmony_ci } 784d4afb5ceSopenharmony_ci 785d4afb5ceSopenharmony_ci /* accept d from the PEM privkey into the JWK */ 786d4afb5ceSopenharmony_ci 787d4afb5ceSopenharmony_ci jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].len = (unsigned int)n; 788d4afb5ceSopenharmony_ci jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf = lws_malloc((unsigned int)n, "privjk"); 789d4afb5ceSopenharmony_ci if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf) 790d4afb5ceSopenharmony_ci goto bail1; 791d4afb5ceSopenharmony_ci 792d4afb5ceSopenharmony_ci BN_bn2bin(mpi, jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf); 793d4afb5ceSopenharmony_ci 794d4afb5ceSopenharmony_ci /* accept p and q from the PEM privkey into the JWK */ 795d4afb5ceSopenharmony_ci 796d4afb5ceSopenharmony_ci jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].len = (unsigned int)BN_num_bytes(dummy[4]); 797d4afb5ceSopenharmony_ci jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf = lws_malloc((unsigned int)n, "privjk"); 798d4afb5ceSopenharmony_ci if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf) { 799d4afb5ceSopenharmony_ci lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf); 800d4afb5ceSopenharmony_ci goto bail1; 801d4afb5ceSopenharmony_ci } 802d4afb5ceSopenharmony_ci BN_bn2bin(dummy[4], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf); 803d4afb5ceSopenharmony_ci 804d4afb5ceSopenharmony_ci jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].len = (unsigned int)BN_num_bytes(dummy[5]); 805d4afb5ceSopenharmony_ci jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf = lws_malloc((unsigned int)n, "privjk"); 806d4afb5ceSopenharmony_ci if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf) { 807d4afb5ceSopenharmony_ci lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf); 808d4afb5ceSopenharmony_ci lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf); 809d4afb5ceSopenharmony_ci goto bail1; 810d4afb5ceSopenharmony_ci } 811d4afb5ceSopenharmony_ci BN_bn2bin(dummy[5], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf); 812d4afb5ceSopenharmony_ci break; 813d4afb5ceSopenharmony_ci default: 814d4afb5ceSopenharmony_ci lwsl_err("%s: JWK has unknown kty %d\n", __func__, jwk->kty); 815d4afb5ceSopenharmony_ci return -1; 816d4afb5ceSopenharmony_ci } 817d4afb5ceSopenharmony_ci 818d4afb5ceSopenharmony_ci ret = 0; 819d4afb5ceSopenharmony_ci 820d4afb5ceSopenharmony_cibail1: 821d4afb5ceSopenharmony_ci if (jwk->kty == LWS_GENCRYPTO_KTY_EC) 822d4afb5ceSopenharmony_ci EC_KEY_free(ecpriv); 823d4afb5ceSopenharmony_ci else 824d4afb5ceSopenharmony_ci RSA_free(rsapriv); 825d4afb5ceSopenharmony_ci 826d4afb5ceSopenharmony_cibail: 827d4afb5ceSopenharmony_ci EVP_PKEY_free(pkey); 828d4afb5ceSopenharmony_ci 829d4afb5ceSopenharmony_ci return ret; 830d4afb5ceSopenharmony_ci} 831d4afb5ceSopenharmony_ci#endif 832d4afb5ceSopenharmony_ci 833d4afb5ceSopenharmony_civoid 834d4afb5ceSopenharmony_cilws_x509_destroy(struct lws_x509_cert **x509) 835d4afb5ceSopenharmony_ci{ 836d4afb5ceSopenharmony_ci if (!*x509) 837d4afb5ceSopenharmony_ci return; 838d4afb5ceSopenharmony_ci 839d4afb5ceSopenharmony_ci if ((*x509)->cert) { 840d4afb5ceSopenharmony_ci X509_free((*x509)->cert); 841d4afb5ceSopenharmony_ci (*x509)->cert = NULL; 842d4afb5ceSopenharmony_ci } 843d4afb5ceSopenharmony_ci 844d4afb5ceSopenharmony_ci lws_free_set_NULL(*x509); 845d4afb5ceSopenharmony_ci} 846