2 * libwebsockets - OpenSSL-specific lws apis
4 * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation:
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 #include "core/private.h"
23 #include "tls/openssl/private.h"
25 #if !defined(LWS_PLAT_OPTEE)
34 lws_tls_openssl_asn1time_to_unix(ASN1_TIME *as)
36 #if !defined(LWS_PLAT_OPTEE)
38 const char *p = (const char *)as->data;
41 /* [YY]YYMMDDHHMMSSZ */
43 memset(&t, 0, sizeof(t));
45 if (strlen(p) == 13) {
46 t.tm_year = (dec(p[0]) * 10) + dec(p[1]) + 100;
49 t.tm_year = (dec(p[0]) * 1000) + (dec(p[1]) * 100) +
50 (dec(p[2]) * 10) + dec(p[3]);
53 t.tm_mon = (dec(p[0]) * 10) + dec(p[1]) - 1;
55 t.tm_mday = (dec(p[0]) * 10) + dec(p[1]) - 1;
57 t.tm_hour = (dec(p[0]) * 10) + dec(p[1]);
59 t.tm_min = (dec(p[0]) * 10) + dec(p[1]);
61 t.tm_sec = (dec(p[0]) * 10) + dec(p[1]);
71 lws_tls_openssl_cert_info(X509 *x509, enum lws_tls_cert_info type,
72 union lws_tls_cert_info_results *buf, size_t len)
75 #if !defined(LWS_PLAT_OPTEE)
82 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(X509_get_notBefore)
83 #define X509_get_notBefore(x) X509_getm_notBefore(x)
84 #define X509_get_notAfter(x) X509_getm_notAfter(x)
88 case LWS_TLS_CERT_INFO_VALIDITY_FROM:
89 buf->time = lws_tls_openssl_asn1time_to_unix(
90 X509_get_notBefore(x509));
91 if (buf->time == (time_t)-1)
95 case LWS_TLS_CERT_INFO_VALIDITY_TO:
96 buf->time = lws_tls_openssl_asn1time_to_unix(
97 X509_get_notAfter(x509));
98 if (buf->time == (time_t)-1)
102 case LWS_TLS_CERT_INFO_COMMON_NAME:
103 #if defined(LWS_PLAT_OPTEE)
106 xn = X509_get_subject_name(x509);
109 X509_NAME_oneline(xn, buf->ns.name, (int)len - 2);
110 p = strstr(buf->ns.name, "/CN=");
112 memmove(buf->ns.name, p + 4, strlen(p + 4) + 1);
113 buf->ns.len = (int)strlen(buf->ns.name);
116 case LWS_TLS_CERT_INFO_ISSUER_NAME:
117 xn = X509_get_issuer_name(x509);
120 X509_NAME_oneline(xn, buf->ns.name, (int)len - 1);
121 buf->ns.len = (int)strlen(buf->ns.name);
124 case LWS_TLS_CERT_INFO_USAGE:
125 #if defined(LWS_HAVE_X509_get_key_usage)
126 buf->usage = X509_get_key_usage(x509);
132 case LWS_TLS_CERT_INFO_OPAQUE_PUBLIC_KEY:
135 size_t klen = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x509), NULL);
138 if (!klen || klen > len)
141 tmp = (uint8_t *)OPENSSL_malloc(klen);
147 X509_get_X509_PUBKEY(x509), &ptmp) != (int)klen ||
148 !ptmp || lws_ptr_diff(ptmp, tmp) != (int)klen) {
149 lwsl_info("%s: cert public key extraction failed\n",
157 buf->ns.len = (int)klen;
158 memcpy(buf->ns.name, tmp, klen);
171 lws_x509_info(struct lws_x509_cert *x509, enum lws_tls_cert_info type,
172 union lws_tls_cert_info_results *buf, size_t len)
174 return lws_tls_openssl_cert_info(x509->cert, type, buf, len);
177 #if defined(LWS_WITH_NETWORK)
179 lws_tls_vhost_cert_info(struct lws_vhost *vhost, enum lws_tls_cert_info type,
180 union lws_tls_cert_info_results *buf, size_t len)
182 #if defined(LWS_HAVE_SSL_CTX_get0_certificate)
183 X509 *x509 = SSL_CTX_get0_certificate(vhost->tls.ssl_ctx);
185 return lws_tls_openssl_cert_info(x509, type, buf, len);
187 lwsl_notice("openssl is too old to support %s\n", __func__);
196 lws_tls_peer_cert_info(struct lws *wsi, enum lws_tls_cert_info type,
197 union lws_tls_cert_info_results *buf, size_t len)
202 wsi = lws_get_network_wsi(wsi);
204 x509 = SSL_get_peer_certificate(wsi->tls.ssl);
207 lwsl_debug("no peer cert\n");
213 case LWS_TLS_CERT_INFO_VERIFIED:
214 buf->verified = SSL_get_verify_result(wsi->tls.ssl) ==
218 rc = lws_tls_openssl_cert_info(x509, type, buf, len);
228 lws_x509_create(struct lws_x509_cert **x509)
230 *x509 = lws_malloc(sizeof(**x509), __func__);
232 (*x509)->cert = NULL;
238 lws_x509_parse_from_pem(struct lws_x509_cert *x509, const void *pem, size_t len)
240 BIO* bio = BIO_new(BIO_s_mem());
242 BIO_write(bio, pem, len);
243 x509->cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
246 lwsl_err("%s: unable to parse PEM cert\n", __func__);
247 lws_tls_err_describe_clear();
256 lws_x509_verify(struct lws_x509_cert *x509, struct lws_x509_cert *trusted,
257 const char *common_name)
263 X509_NAME *xn = X509_get_subject_name(x509->cert);
266 X509_NAME_oneline(xn, c, (int)sizeof(c) - 2);
267 p = strstr(c, "/CN=");
273 if (strcmp(p, common_name)) {
274 lwsl_err("%s: common name mismatch\n", __func__);
279 ret = X509_check_issued(trusted->cert, x509->cert);
280 if (ret != X509_V_OK) {
281 lwsl_err("%s: unable to verify cert relationship\n", __func__);
282 lws_tls_err_describe_clear();
290 #if defined(LWS_WITH_JOSE)
292 lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509,
293 const char *curves, int rsa_min_bits)
295 int id, n, ret = -1, count;
296 ASN1_OBJECT *obj = NULL;
297 const EC_POINT *ecpoint;
298 const EC_GROUP *ecgroup;
299 EC_KEY *ecpub = NULL;
305 memset(jwk, 0, sizeof(*jwk));
307 pubkey = X509_get_X509_PUBKEY(x509->cert);
309 lwsl_err("%s: missing pubkey alg in cert\n", __func__);
314 if (X509_PUBKEY_get0_param(&obj, NULL, NULL, NULL, pubkey) != 1) {
315 lwsl_err("%s: missing pubkey alg in cert\n", __func__);
320 id = OBJ_obj2nid(obj);
321 if (id == NID_undef) {
322 lwsl_err("%s: missing pubkey alg in cert\n", __func__);
327 lwsl_debug("%s: key type %d \"%s\"\n", __func__, id, OBJ_nid2ln(id));
329 pkey = X509_get_pubkey(x509->cert);
331 lwsl_notice("%s: unable to extract pubkey", __func__);
337 case NID_X9_62_id_ecPublicKey:
338 lwsl_debug("%s: EC key\n", __func__);
339 jwk->kty = LWS_GENCRYPTO_KTY_EC;
342 lwsl_err("%s: ec curves not allowed\n", __func__);
347 ecpub = EVP_PKEY_get1_EC_KEY(pkey);
349 lwsl_notice("%s: missing EC pubkey\n", __func__);
354 ecpoint = EC_KEY_get0_public_key(ecpub);
356 lwsl_err("%s: EC_KEY_get0_public_key failed\n", __func__);
360 ecgroup = EC_KEY_get0_group(ecpub);
362 lwsl_err("%s: EC_KEY_get0_group failed\n", __func__);
366 /* validate the curve against ones we allow */
368 if (lws_genec_confirm_curve_allowed_by_tls_id(curves,
369 EC_GROUP_get_curve_name(ecgroup), jwk))
373 mpi[LWS_GENCRYPTO_EC_KEYEL_CRV] = NULL;
374 mpi[LWS_GENCRYPTO_EC_KEYEL_X] = BN_new(); /* X */
375 mpi[LWS_GENCRYPTO_EC_KEYEL_D] = NULL;
376 mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = BN_new(); /* Y */
378 #if defined(LWS_HAVE_EC_POINT_get_affine_coordinates)
379 if (EC_POINT_get_affine_coordinates(ecgroup, ecpoint,
381 if (EC_POINT_get_affine_coordinates_GFp(ecgroup, ecpoint,
383 mpi[LWS_GENCRYPTO_EC_KEYEL_X],
384 mpi[LWS_GENCRYPTO_EC_KEYEL_Y],
386 BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
387 BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
388 lwsl_err("%s: EC_POINT_get_aff failed\n", __func__);
391 count = LWS_GENCRYPTO_EC_KEYEL_COUNT;
392 n = LWS_GENCRYPTO_EC_KEYEL_X;
395 case NID_rsaEncryption:
396 lwsl_debug("%s: rsa key\n", __func__);
397 jwk->kty = LWS_GENCRYPTO_KTY_RSA;
399 rsapub = EVP_PKEY_get1_RSA(pkey);
401 lwsl_notice("%s: missing RSA pubkey\n", __func__);
406 if ((size_t)RSA_size(rsapub) * 8 < (size_t)rsa_min_bits) {
407 lwsl_err("%s: key bits %d less than minimum %d\n",
408 __func__, RSA_size(rsapub) * 8, rsa_min_bits);
413 #if defined(LWS_HAVE_RSA_SET0_KEY)
414 /* we don't need d... but the api wants to write it */
416 (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_N],
417 (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_E],
418 (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_D]);
420 mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = rsapub->e;
421 mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = rsapub->n;
422 mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = NULL;
424 count = LWS_GENCRYPTO_RSA_KEYEL_D;
425 n = LWS_GENCRYPTO_RSA_KEYEL_E;
428 lwsl_err("%s: unknown NID\n", __func__);
432 for (; n < count; n++) {
435 jwk->e[n].len = BN_num_bytes(mpi[n]);
436 jwk->e[n].buf = lws_malloc(jwk->e[n].len, "certkeyimp");
437 if (!jwk->e[n].buf) {
438 if (id == NID_X9_62_id_ecPublicKey) {
439 BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
440 BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
444 BN_bn2bin(mpi[n], jwk->e[n].buf);
447 if (id == NID_X9_62_id_ecPublicKey) {
448 BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]);
449 BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]);
455 if (id == NID_X9_62_id_ecPublicKey)
463 /* jwk destroy will clean any partial state */
465 lws_jwk_destroy(jwk);
471 lws_x509_jwk_privkey_pem_pp_cb(char *buf, int size, int rwflag, void *u)
473 const char *pp = (const char *)u;
479 memcpy(buf, pp, n + 1);
485 lws_x509_jwk_privkey_pem(struct lws_jwk *jwk, void *pem, size_t len,
486 const char *passphrase)
488 BIO* bio = BIO_new(BIO_s_mem());
489 BIGNUM *mpi, *dummy[6];
490 EVP_PKEY *pkey = NULL;
491 EC_KEY *ecpriv = NULL;
496 BIO_write(bio, pem, len);
497 PEM_read_bio_PrivateKey(bio, &pkey, lws_x509_jwk_privkey_pem_pp_cb,
500 lws_explicit_bzero((void *)pem, len);
502 lwsl_err("%s: unable to parse PEM privkey\n", __func__);
503 lws_tls_err_describe_clear();
508 /* confirm the key type matches the existing jwk situation */
511 case LWS_GENCRYPTO_KTY_EC:
512 if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) {
513 lwsl_err("%s: jwk is EC but privkey isn't\n", __func__);
517 ecpriv = EVP_PKEY_get1_EC_KEY(pkey);
519 lwsl_notice("%s: missing EC key\n", __func__);
524 cmpi = EC_KEY_get0_private_key(ecpriv);
526 /* quick size check first */
528 n = BN_num_bytes(cmpi);
529 if (jwk->e[LWS_GENCRYPTO_EC_KEYEL_Y].len != (uint32_t)n) {
530 lwsl_err("%s: jwk key size doesn't match\n", __func__);
535 /* TODO.. check public curve / group + point */
537 jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len = n;
538 jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf = lws_malloc(n, "ec");
539 if (!jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf)
542 m = BN_bn2binpad(cmpi, jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].buf,
543 jwk->e[LWS_GENCRYPTO_EC_KEYEL_D].len);
544 if ((unsigned int)m != (unsigned int)BN_num_bytes(cmpi))
549 case LWS_GENCRYPTO_KTY_RSA:
550 if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_RSA) {
551 lwsl_err("%s: RSA jwk, non-RSA privkey\n", __func__);
555 rsapriv = EVP_PKEY_get1_RSA(pkey);
557 lwsl_notice("%s: missing RSA key\n", __func__);
562 #if defined(LWS_HAVE_RSA_SET0_KEY)
563 RSA_get0_key(rsapriv, (const BIGNUM **)&dummy[0], /* n */
564 (const BIGNUM **)&dummy[1], /* e */
565 (const BIGNUM **)&mpi); /* d */
566 RSA_get0_factors(rsapriv, (const BIGNUM **)&dummy[4], /* p */
567 (const BIGNUM **)&dummy[5]); /* q */
569 dummy[0] = rsapriv->n;
570 dummy[1] = rsapriv->e;
571 dummy[4] = rsapriv->p;
572 dummy[5] = rsapriv->q;
576 /* quick size check first */
578 n = BN_num_bytes(mpi);
579 if (jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len != (uint32_t)n) {
580 lwsl_err("%s: jwk key size doesn't match\n", __func__);
585 /* then check that n & e match what we got from the cert */
587 dummy[2] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].buf,
588 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_N].len,
590 dummy[3] = BN_bin2bn(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].buf,
591 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_E].len,
594 m = BN_cmp(dummy[2], dummy[0]) | BN_cmp(dummy[3], dummy[1]);
595 BN_clear_free(dummy[2]);
596 BN_clear_free(dummy[3]);
598 lwsl_err("%s: privkey doesn't match jwk pubkey\n",
604 /* accept d from the PEM privkey into the JWK */
606 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].len = n;
607 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf = lws_malloc(n, "privjk");
608 if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf)
611 BN_bn2bin(mpi, jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
613 /* accept p and q from the PEM privkey into the JWK */
615 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].len = BN_num_bytes(dummy[4]);
616 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf = lws_malloc(n, "privjk");
617 if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf) {
618 lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
621 BN_bn2bin(dummy[4], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf);
623 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].len = BN_num_bytes(dummy[5]);
624 jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf = lws_malloc(n, "privjk");
625 if (!jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf) {
626 lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_D].buf);
627 lws_free_set_NULL(jwk->e[LWS_GENCRYPTO_RSA_KEYEL_P].buf);
630 BN_bn2bin(dummy[5], jwk->e[LWS_GENCRYPTO_RSA_KEYEL_Q].buf);
633 lwsl_err("%s: JWK has unknown kty %d\n", __func__, jwk->kty);
640 if (jwk->kty == LWS_GENCRYPTO_KTY_EC)
653 lws_x509_destroy(struct lws_x509_cert **x509)
659 X509_free((*x509)->cert);
660 (*x509)->cert = NULL;
663 lws_free_set_NULL(*x509);