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
}
Esempio n. 2
0
LWS_VISIBLE int
lws_tls_acme_sni_cert_create(struct lws_vhost *vhost, const char *san_a,
			     const char *san_b)
{
	int buflen = 0x560;
	uint8_t *buf = lws_malloc(buflen, "tmp cert buf"), *p = buf, *pkey_asn1;
	struct lws_genrsa_ctx ctx;
	struct lws_genrsa_elements el;
	uint8_t digest[32];
	struct lws_genhash_ctx hash_ctx;
	int pkey_asn1_len = 3 * 1024;
	int n, keybits = lws_plat_recommended_rsa_bits(), adj;

	if (!buf)
		return 1;

	n = lws_genrsa_new_keypair(vhost->context, &ctx, &el, keybits);
	if (n < 0) {
		lws_jwk_destroy_genrsa_elements(&el);
		goto bail1;
	}

	n = sizeof(ss_cert_leadin);
	memcpy(p, ss_cert_leadin, n);
	p += n;

	adj = (0x0556 - 0x401) + (keybits / 4) + 1;
	buf[2] = adj >> 8;
	buf[3] = adj & 0xff;

	adj = (0x033e - 0x201) + (keybits / 8) + 1;
	buf[6] = adj >> 8;
	buf[7] = adj & 0xff;

	adj = (0x0222 - 0x201) + (keybits / 8) + 1;
	buf[0xc3] = adj >> 8;
	buf[0xc4] = adj & 0xff;

	adj = (0x020f - 0x201) + (keybits / 8) + 1;
	buf[0xd6] = adj >> 8;
	buf[0xd7] = adj & 0xff;

	adj = (0x020a - 0x201) + (keybits / 8) + 1;
	buf[0xdb] = adj >> 8;
	buf[0xdc] = adj & 0xff;

	*p++ = ((keybits / 8) + 1) >> 8;
	*p++ = ((keybits / 8) + 1) & 0xff;

	/* we need to drop 1 + (keybits / 8) bytes of n in here, 00 + key */

	*p++ = 0x00;
	memcpy(p, el.e[JWK_KEY_N].buf, el.e[JWK_KEY_N].len);
	p += el.e[JWK_KEY_N].len;

	memcpy(p, ss_cert_san_leadin, sizeof(ss_cert_san_leadin));
	p += sizeof(ss_cert_san_leadin);

	/* drop in 78 bytes of san_a */

	memcpy(p, san_a, SAN_A_LENGTH);
	p += SAN_A_LENGTH;
	memcpy(p, ss_cert_sig_leadin, sizeof(ss_cert_sig_leadin));

	p[17] = ((keybits / 8) + 1) >> 8;
	p[18] = ((keybits / 8) + 1) & 0xff;

	p += sizeof(ss_cert_sig_leadin);

	/* hash the cert plaintext */

	if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256))
		goto bail2;

	if (lws_genhash_update(&hash_ctx, buf, lws_ptr_diff(p, buf))) {
		lws_genhash_destroy(&hash_ctx, NULL);

		goto bail2;
	}
	if (lws_genhash_destroy(&hash_ctx, digest))
		goto bail2;

	/* sign the hash */

	n = lws_genrsa_public_sign(&ctx, digest, LWS_GENHASH_TYPE_SHA256, p,
				 buflen - lws_ptr_diff(p, buf));
	if (n < 0)
		goto bail2;
	p += n;

	pkey_asn1 = lws_malloc(pkey_asn1_len, "mbed crt tmp");
	if (!pkey_asn1)
		goto bail2;

	n = lws_genrsa_render_pkey_asn1(&ctx, 1, pkey_asn1, pkey_asn1_len);
	if (n < 0) {
		lws_free(pkey_asn1);
		goto bail2;
	}
	lwsl_debug("private key\n");
	lwsl_hexdump_level(LLL_DEBUG, pkey_asn1, n);

	/* and to use our generated private key */
	n = SSL_CTX_use_PrivateKey_ASN1(0, vhost->ssl_ctx, pkey_asn1, n);
	lws_free(pkey_asn1);
	if (n != 1) {
		lwsl_notice("%s: SSL_CTX_use_PrivateKey_ASN1 failed\n",
			    __func__);
	}

	lws_genrsa_destroy(&ctx);
	lws_jwk_destroy_genrsa_elements(&el);

	if (n == 1) {
		lwsl_hexdump_level(LLL_DEBUG, buf, lws_ptr_diff(p, buf));

		n = SSL_CTX_use_certificate_ASN1(vhost->ssl_ctx,
					 lws_ptr_diff(p, buf), buf);
		if (n != 1)
			lwsl_notice("%s: generated cert failed to load 0x%x\n",
					__func__, -n);
	}

	lws_free(buf);

	return n != 1;

bail2:
	lws_genrsa_destroy(&ctx);
	lws_jwk_destroy_genrsa_elements(&el);
bail1:
	lws_free(buf);

	return -1;
}