#if (EASYMESH_VERSION >= 3)
#ifdef USE_LIBDPP
#ifdef ZEROTOUCH_DPP

#include "zt.h"

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <sys/time.h>
#include <dlfcn.h>
#include <time.h>

#include <openssl/bio.h>
#include <openssl/evp.h>
#include <openssl/x509.h>

#include <libubox/blob.h>
#include <libubox/blobmsg.h>
#include <libubox/blobmsg_json.h>

#include "utils/debug.h"

#define LIBZTDPP_SOFILE         "/usr/lib/libztdpp.so"
#define PUBKEY_FILE		"/root/pub.der"
#define PASSPHRASE_FILE		"/etc/board.json"

static struct blob_attr *blobmsg_find_attr(struct blob_attr *attr, const char *name)
{
	struct blob_attr *cur;
	int rem;

	if (!attr)
		return NULL;

	blobmsg_for_each_attr(cur, attr, rem) {
		if (strcmp(blobmsg_name(cur), name) == 0)
			return cur;
	}
	return NULL;
}

char *zt_load_passphrase(void)
{
	static struct blob_buf b;
	struct blob_attr *tb_wlan, *tb_defaults, *tb_ssids, *tb_all;
	struct blob_attr *cur;
	char *key = NULL;

	blob_buf_init(&b, 0);

	if (!blobmsg_add_json_from_file(&b, PASSPHRASE_FILE) != 0) {
		fprintf(stderr, "Failed to parse JSON file: %s\n", PASSPHRASE_FILE);
		blob_buf_free(&b);
		return NULL;
	}

	tb_wlan = blobmsg_find_attr(b.head, "wlan");
	if (!tb_wlan)
		goto out;

	tb_defaults = blobmsg_find_attr(tb_wlan, "defaults");
	if (!tb_defaults)
		goto out;

	tb_ssids = blobmsg_find_attr(tb_defaults, "ssids");
	if (!tb_ssids)
		goto out;

	tb_all = blobmsg_find_attr(tb_ssids, "all");
	if (!tb_all)
		goto out;

	cur = blobmsg_find_attr(tb_all, "key");
	if (cur)
		key = strdup(blobmsg_get_string(cur));

out:
	blob_buf_free(&b);
	return key;
}

void *zt_load_pubkey(void)
{
	EVP_PKEY *pubkey;
	BIO *bio;

	bio = BIO_new_file(PUBKEY_FILE, "rb");
	if (!bio) {
		dbg("%s: Zero-touch public key missing.\n", __func__);
		return NULL;
	}

	pubkey = d2i_PUBKEY_bio(bio, NULL);
	BIO_free(bio);

	if (!pubkey) {
		dbg("%s: Reading public key failed\n", __func__);
		return NULL;
	}

	return (void *)pubkey;
}


int libztdpp_open(struct zt_context *zt)
{
	int ret = 0;

	if (zt->libztdpp || zt->dpp_gen_encoded_uri_payload)
		return -1;

	zt->libztdpp = dlopen(LIBZTDPP_SOFILE, RTLD_NOW | RTLD_GLOBAL);
	if (!zt->libztdpp)
		return errno;

	zt->dpp_gen_encoded_uri_payload = dlsym(zt->libztdpp, "dpp_gen_encoded_uri_payload");
	if (!zt->dpp_gen_encoded_uri_payload) {
		ret = -1;
		goto out_error;
	}

	zt->dpp_gen_pa_vsie_frame = dlsym(zt->libztdpp, "dpp_gen_pa_vsie_frame");
	if (!zt->dpp_gen_pa_vsie_frame) {
		ret = -1;
		goto out_error;
	}

	zt->dpp_gen_encoded_uri_payload2 = dlsym(zt->libztdpp, "dpp_gen_encoded_uri_payload2");
	if (!zt->dpp_gen_encoded_uri_payload) {
		ret = -1;
		goto out_error;
	}

	zt->dpp_gen_pa_vsie_frame2 = dlsym(zt->libztdpp, "dpp_gen_pa_vsie_frame2");
	if (!zt->dpp_gen_pa_vsie_frame) {
		ret = -1;
		goto out_error;
	}

	return 0;

out_error:
	dlclose(zt->libztdpp);
	zt->libztdpp = NULL;
	return ret;
}

void libztdpp_close(struct zt_context *zt)
{
	if (zt && zt->dpp_gen_encoded_uri_payload) {
		zt->dpp_gen_encoded_uri_payload = NULL;
		dlclose(zt->libztdpp);
		zt->libztdpp = NULL;
	}
}

int zt_init(struct zt_context *zt, char *bi_key, char *uri)
{
	uint8_t *msg;
	size_t msglen;

	trace("%s: =====>\n", __func__);

	zt->pubkey = zt_load_pubkey();
	if (zt->pubkey) {
		msg = zt->dpp_gen_encoded_uri_payload(zt->pubkey, bi_key, uri,
						      &msglen);
		if (!msg) {
			warn("%s: Error generating EVP Key zero-touch payload\n",
				__func__);
		} else {
			zt->encoded_frame = zt->dpp_gen_pa_vsie_frame(msg, msglen, &zt->encoded_framelen);
			if (!zt->encoded_frame)
				warn("%s: Error generating EVP Key zero-touch encoded frame\n", __func__);
			else
				info("%s: Zero-touch EVP Key based onboarding initialized\n", __func__);
		}
	}

	zt->passphrase = zt_load_passphrase();
	if (zt->passphrase) {
		msg = zt->dpp_gen_encoded_uri_payload2(zt->passphrase, uri, &msglen);
		if (!msg) {
			warn("%s: Error generating passphrase zero-touch payload\n",
				__func__);
		} else {
			zt->encoded_frame2 = zt->dpp_gen_pa_vsie_frame2(msg, msglen, &zt->encoded_framelen2);
			if (!zt->encoded_frame2)
				warn("%s: Error generating passphrase zero-touch encoded frame\n", __func__);
			else
				info("%s: Zero-touch passphrase based onboarding initialized\n", __func__);
		}
	}

	return (zt->encoded_frame || zt->encoded_frame2) ? 0 : -1;
}
#endif
#endif
#endif
