static void lws_acme_finished(struct per_vhost_data__lws_acme_client *vhd) { lwsl_debug("%s\n", __func__); if (vhd->ac) { if (vhd->ac->vhost) lws_vhost_destroy(vhd->ac->vhost); if (vhd->ac->alloc_privkey_pem) free(vhd->ac->alloc_privkey_pem); free(vhd->ac); } lws_genrsa_destroy(&vhd->rsactx); lws_jwk_destroy(&vhd->jwk); vhd->ac = NULL; #if defined(LWS_WITH_ESP32) lws_esp32.acme = 0; /* enable scanning */ #endif }
int lws_x509_public_to_jwk(struct lws_jwk *jwk, struct lws_x509_cert *x509, const char *curves, int rsa_min_bits) { int id, n, ret = -1, count; ASN1_OBJECT *obj = NULL; const EC_POINT *ecpoint; const EC_GROUP *ecgroup; EC_KEY *ecpub = NULL; X509_PUBKEY *pubkey; RSA *rsapub = NULL; BIGNUM *mpi[4]; EVP_PKEY *pkey; memset(jwk, 0, sizeof(*jwk)); pubkey = X509_get_X509_PUBKEY(x509->cert); if (!pubkey) { lwsl_err("%s: missing pubkey alg in cert\n", __func__); goto bail; } if (X509_PUBKEY_get0_param(&obj, NULL, NULL, NULL, pubkey) != 1) { lwsl_err("%s: missing pubkey alg in cert\n", __func__); goto bail; } id = OBJ_obj2nid(obj); if (id == NID_undef) { lwsl_err("%s: missing pubkey alg in cert\n", __func__); goto bail; } lwsl_debug("%s: key type %d \"%s\"\n", __func__, id, OBJ_nid2ln(id)); pkey = X509_get_pubkey(x509->cert); if (!pkey) { lwsl_notice("%s: unable to extract pubkey", __func__); goto bail; } switch (id) { case NID_X9_62_id_ecPublicKey: lwsl_debug("%s: EC key\n", __func__); jwk->kty = LWS_GENCRYPTO_KTY_EC; if (!curves) { lwsl_err("%s: ec curves not allowed\n", __func__); goto bail1; } ecpub = EVP_PKEY_get1_EC_KEY(pkey); if (!ecpub) { lwsl_notice("%s: missing EC pubkey\n", __func__); goto bail1; } ecpoint = EC_KEY_get0_public_key(ecpub); if (!ecpoint) { lwsl_err("%s: EC_KEY_get0_public_key failed\n", __func__); goto bail2; } ecgroup = EC_KEY_get0_group(ecpub); if (!ecgroup) { lwsl_err("%s: EC_KEY_get0_group failed\n", __func__); goto bail2; } /* validate the curve against ones we allow */ if (lws_genec_confirm_curve_allowed_by_tls_id(curves, EC_GROUP_get_curve_name(ecgroup), jwk)) /* already logged */ goto bail2; mpi[LWS_GENCRYPTO_EC_KEYEL_CRV] = NULL; mpi[LWS_GENCRYPTO_EC_KEYEL_X] = BN_new(); /* X */ mpi[LWS_GENCRYPTO_EC_KEYEL_D] = NULL; mpi[LWS_GENCRYPTO_EC_KEYEL_Y] = BN_new(); /* Y */ #if defined(LWS_HAVE_EC_POINT_get_affine_coordinates) if (EC_POINT_get_affine_coordinates(ecgroup, ecpoint, #else if (EC_POINT_get_affine_coordinates_GFp(ecgroup, ecpoint, #endif mpi[LWS_GENCRYPTO_EC_KEYEL_X], mpi[LWS_GENCRYPTO_EC_KEYEL_Y], NULL) != 1) { BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]); BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]); lwsl_err("%s: EC_POINT_get_aff failed\n", __func__); goto bail2; } count = LWS_GENCRYPTO_EC_KEYEL_COUNT; n = LWS_GENCRYPTO_EC_KEYEL_X; break; case NID_rsaEncryption: lwsl_debug("%s: rsa key\n", __func__); jwk->kty = LWS_GENCRYPTO_KTY_RSA; rsapub = EVP_PKEY_get1_RSA(pkey); if (!rsapub) { lwsl_notice("%s: missing RSA pubkey\n", __func__); goto bail1; } if (RSA_size(rsapub) * 8 < rsa_min_bits) { lwsl_err("%s: key bits %d less than minimum %d\n", __func__, RSA_size(rsapub) * 8, rsa_min_bits); goto bail2; } #if defined(LWS_HAVE_RSA_SET0_KEY) /* we don't need d... but the api wants to write it */ RSA_get0_key(rsapub, (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_N], (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_E], (const BIGNUM **)&mpi[LWS_GENCRYPTO_RSA_KEYEL_D]); #else mpi[LWS_GENCRYPTO_RSA_KEYEL_E] = rsapub->e; mpi[LWS_GENCRYPTO_RSA_KEYEL_N] = rsapub->n; mpi[LWS_GENCRYPTO_RSA_KEYEL_D] = NULL; #endif count = LWS_GENCRYPTO_RSA_KEYEL_D; n = LWS_GENCRYPTO_RSA_KEYEL_E; break; default: lwsl_err("%s: unknown NID\n", __func__); goto bail2; } for (; n < count; n++) { if (!mpi[n]) continue; jwk->e[n].len = BN_num_bytes(mpi[n]); jwk->e[n].buf = lws_malloc(jwk->e[n].len, "certkeyimp"); if (!jwk->e[n].buf) { if (id == NID_X9_62_id_ecPublicKey) { BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]); BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]); } goto bail2; } BN_bn2bin(mpi[n], jwk->e[n].buf); } if (id == NID_X9_62_id_ecPublicKey) { BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_X]); BN_clear_free(mpi[LWS_GENCRYPTO_EC_KEYEL_Y]); } ret = 0; bail2: if (id == NID_X9_62_id_ecPublicKey) EC_KEY_free(ecpub); else RSA_free(rsapub); bail1: EVP_PKEY_free(pkey); bail: /* jwk destroy will clean any partial state */ if (ret) lws_jwk_destroy(jwk); return ret; }