/*
 * Copyright (c) 2015, Google Inc.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

#include "mkimage.h"
#include <stdio.h>
#include <string.h>
#include <image.h>
#include <time.h>
#include <linux/limits.h>
#include <curl/curl.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/evp.h>

#if OPENSSL_VERSION_NUMBER >= 0x10000000L
#define HAVE_ERR_REMOVE_THREAD_STATE
#endif

#define SIGNATURE_LEN		(2048 / 8) // Size of a 2048-bit RSA key
#define SIGNING_URL_LEN_MAX	1024
#define LOCAL_MACHINE_AUTH_ENV	"auth"

/* To test the remote signing service, define TEST_LOCAL_SIGNING_KEY and point it to a locally
   stored key. This will cause mkimage to use both and compare the results
 */
// #define TEST_LOCAL_SIGNING_KEY	"/home/vanvugt/workspace/sapphire/kernel-signing-keys/diamond3-01.key"

static int rsa_err(const char *msg)
{
	unsigned long sslErr = ERR_get_error();

	fprintf(stderr, "%s", msg);
	fprintf(stderr, ": %s\n",
		ERR_error_string(sslErr, 0));

	return -1;
}

/**
 * rsa_get_priv_key() - read a private key from a .key file
 *
 * @keydir:	Path to the key
 * @name	Name of the key in the control FDT
 * @rsap	Returns RSA object, or NULL on failure
 * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
 */
static int rsa_get_priv_key(const char *keydir, const char *name, RSA **rsap)
{
	RSA *rsa;
	char path[1024];
	FILE *f;

	*rsap = NULL;
	/* snprintf(path, sizeof(path), "%s/%s.key", keydir, name); */
	strncpy(path, keydir, sizeof(path));
	path[sizeof(path) - 1] = 0;
	f = fopen(path, "r");
	if (!f) {
		fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
			path, strerror(errno));
		return -ENOENT;
	}

	rsa = PEM_read_RSAPrivateKey(f, 0, NULL, path);
	fclose(f);
	if (!rsa) {
		rsa_err("Failure reading private key");
		return -EPROTO;
	}
	*rsap = rsa;

	return 0;
}

#if defined(TEST_LOCAL_SIGNING_KEY)
static int rsa_init(void)
{
	int ret;

	ret = SSL_library_init();
	if (!ret) {
		fprintf(stderr, "Failure to init SSL library\n");
		return -1;
	}
	SSL_load_error_strings();

	OpenSSL_add_all_algorithms();
	OpenSSL_add_all_digests();
	OpenSSL_add_all_ciphers();

	return 0;
}

static void rsa_remove(void)
{
	CRYPTO_cleanup_all_ex_data();
	ERR_free_strings();
#ifdef HAVE_ERR_REMOVE_THREAD_STATE
	ERR_remove_thread_state(NULL);
#else
	ERR_remove_state(0);
#endif
	EVP_cleanup();
}

static int rsa_sign_with_key(RSA *rsa, const struct image_region region[],
		int region_count, uint8_t **sigp, uint *sig_size)
{
	EVP_PKEY *key;
	EVP_MD_CTX *context;
	int size, ret = 0;
	uint8_t *sig;
	int i;

	key = EVP_PKEY_new();
	if (!key)
		return rsa_err("EVP_PKEY object creation failed");

	if (!EVP_PKEY_set1_RSA(key, rsa)) {
		ret = rsa_err("EVP key setup failed");
		goto err_set;
	}

	size = EVP_PKEY_size(key);
	sig = malloc(size);
	if (!sig) {
		fprintf(stderr, "Out of memory for signature (%d bytes)\n",
			size);
		ret = -ENOMEM;
		goto err_alloc;
	}

	context = EVP_MD_CTX_create();
	if (!context) {
		ret = rsa_err("EVP context creation failed");
		goto err_create;
	}
	EVP_MD_CTX_init(context);
	if (!EVP_SignInit(context, EVP_sha256())) {
		ret = rsa_err("Signer setup failed");
		goto err_sign;
	}

	for (i = 0; i < region_count; i++) {
		if (!EVP_SignUpdate(context, region[i].data, region[i].size)) {
			ret = rsa_err("Signing data failed");
			goto err_sign;
		}
	}

	if (!EVP_SignFinal(context, sig, sig_size, key)) {
		ret = rsa_err("Could not obtain signature");
		goto err_sign;
	}
	EVP_MD_CTX_cleanup(context);
	EVP_MD_CTX_destroy(context);
	EVP_PKEY_free(key);

	debug("Got signature: %d bytes, expected %d\n", *sig_size, size);
	*sigp = sig;
	*sig_size = size;

	return 0;

err_sign:
	EVP_MD_CTX_destroy(context);
err_create:
	free(sig);
err_alloc:
err_set:
	EVP_PKEY_free(key);
	return ret;
}
#endif // if defined(TEST_LOCAL_SIGNING_KEY)

// We communicate with the signing service via curl HTTPS+GET
// If we return anything other than size * nmemb, curl_easy_perform() will error out
static size_t parse_response(char *ptr, size_t size, size_t nmemb, char *userdata)
{
	int i;
	size_t retval = (size * nmemb);

	debug("Recv from service %i * %i B\n", (int)size, (int)nmemb);

	if ((size * nmemb) != (2 * SIGNATURE_LEN)) {
		fprintf(stderr, "Signing host response length (%i * %i) is invalid, expected %i\n", (int)size, (int)nmemb, (2 * SIGNATURE_LEN));
		return 0;
	}

	for (i = 0; i < SIGNATURE_LEN; i++) {
		int val;
		if (sscanf(&ptr[2 * i], "%02x", &val) != 1) {
			fprintf(stderr, "Failed parsing signing host response @ %i\n", i);
			return 0;
		} else {
			userdata[i] = val;
		}
	}

	return retval;
}

static int rsa_sign_with_service(const char *signing_url, const struct image_region region[], int region_count,
		uint8_t **sigp, uint *sig_size)
{
	int i, url_len;
	SHA256_CTX ctx;
	unsigned char md[SHA256_DIGEST_LENGTH];
	uint8_t *signature;
	char errbuf[CURL_ERROR_SIZE],
	     signing_url_complete[SIGNING_URL_LEN_MAX];
	char *auth;
	CURL *handle;
	CURLcode curlRes;
	int ret = 0;

	// Get the local machine's credentials from the environment
	auth = getenv(LOCAL_MACHINE_AUTH_ENV);
	if (auth == NULL) {
		ret = rsa_err("Local machine credential env variable '" LOCAL_MACHINE_AUTH_ENV "' undefined.\n"
		              "Set with 'export " LOCAL_MACHINE_AUTH_ENV "=\"<user>:<password>\"'.\n");
		goto err_noalloc;
	}

	// Start building the complete URL with the hash. Check that the URL will fit.
	url_len = snprintf(signing_url_complete, SIGNING_URL_LEN_MAX, "%s&hash=", signing_url);
	if ((url_len + (2 * SHA256_DIGEST_LENGTH) + 1) >= SIGNING_URL_LEN_MAX) {
		ret = rsa_err("URL too long for buffer");
		goto err_noalloc;
	} else if (url_len < 0) {
		ret = rsa_err("Encoding error generating URL");
		goto err_noalloc;
	}

	signature = malloc(SIGNATURE_LEN);
	if (!signature) {
		fprintf(stderr, "Out of memory for signature\n");
		ret = -ENOMEM;
		goto err_noalloc;
	}

	curl_global_init(CURL_GLOBAL_DEFAULT);

	// Generate the SHA-256 hash of the configuration
	if (!SHA256_Init(&ctx)) {
		ret = rsa_err("SHA setup failed");
		goto err_dealloc;
	}

	for (i = 0; i < region_count; i++) {
		if (!SHA256_Update(&ctx, region[i].data, region[i].size)) {
			ret = rsa_err("SHA calculation failed");
			goto err_dealloc;
		}
	}

	if (!SHA256_Final(md, &ctx)) {
		ret = rsa_err("Could not obtain SHA");
		goto err_dealloc;
	}

	// Convert the hash to ASCII hex and append it to the URL
	for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
		sprintf(&signing_url_complete[url_len + (2 * i)], "%02x", md[i]);
	}
	signing_url_complete[url_len + (2 * SHA256_DIGEST_LENGTH)] = 0;
	debug("Signing with URL: '%s'\n", signing_url_complete);

	// Prepare a HTTP GET to the signing host, with a buffer for error responses
	handle = curl_easy_init();
	curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, errbuf);
	curl_easy_setopt(handle, CURLOPT_URL, signing_url_complete);
#ifdef ALLOW_SELF_SIGNED_CERTS
	curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0L);             // The test signing server uses a self-signed cert
#endif
	curl_easy_setopt(handle, CURLOPT_FAILONERROR, 1);                 // Fail on all HTTP error responses
	curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, parse_response);
	curl_easy_setopt(handle, CURLOPT_WRITEDATA, signature);
	curl_easy_setopt(handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);         // The current service doesn't support hash-based auth
	curl_easy_setopt(handle, CURLOPT_USERPWD, auth);

	errbuf[0] = 0;

	// Send the HTTP GET and handle the response via the callback
	curlRes = curl_easy_perform(handle);

	curl_easy_cleanup(handle);

	// Check whether the HTTP GET and the parsing of the response succeeded
	if (curlRes != CURLE_OK) {
		if (strlen(errbuf) > 0) {
			fprintf(stderr, "GET failed: %s\n", errbuf);
		} else {
			fprintf(stderr, "GET failed: %s\n", curl_easy_strerror(curlRes));
		}
		ret = -EIO;
		goto err_dealloc;
	}

	*sigp = signature;
	*sig_size = SIGNATURE_LEN;

	curl_global_cleanup();

	return 0;

err_dealloc:
	curl_global_cleanup();
	free(signature);
err_noalloc:
	*sigp = NULL;
	*sig_size = 0;

	return ret;
}

int rsa_imx_sign(struct image_sign_info *info,
	     const struct image_region region[], int region_count,
	     uint8_t **sigp, uint *sig_len)
{
	int ret;

	printf("Signing with '%s'\n", info->keydir);
	ret = rsa_sign_with_service(info->keydir, region, region_count, sigp, sig_len);
	if (ret)
		goto err_out;

#if defined(TEST_LOCAL_SIGNING_KEY)
	RSA *rsa;
	uint8_t *sigp2 = NULL;
	uint sig_len2;

	ret = rsa_init();
	if (ret)
		return ret;

	printf("Signing with '%s'\n", TEST_LOCAL_SIGNING_KEY);
	ret = rsa_get_priv_key(TEST_LOCAL_SIGNING_KEY, info->keyname, &rsa);
	if (ret)
		goto err_priv;
	ret = rsa_sign_with_key(rsa, region, region_count, &sigp2, &sig_len2);
	if (ret)
		goto err_sign;

	int i;
	if (*sig_len != sig_len2) {
		printf("Error: signature lengths different\n");
	} else if (memcmp(*sigp, sigp2, *sig_len) != 0) {
		printf("Error: signature data different\n");
	} else {
		printf("Success: signatures match\n");
	}

	RSA_free(rsa);
	rsa_remove();
#endif // if defined(TEST_LOCAL_SIGNING_KEY)

	return ret;

#if defined(TEST_LOCAL_SIGNING_KEY)
err_sign:
	RSA_free(rsa);
err_priv:
	rsa_remove();
#endif // if defined(TEST_LOCAL_SIGNING_KEY)
err_out:

	return ret;
}

/*
 * rsa_imx_get_params(): - Get the important parameters of an RSA public key
 */
static int rsa_imx_get_params(RSA *key, uint32_t *n0_invp, BIGNUM **modulusp,
                              BIGNUM **r_squaredp)
{
	BIGNUM *big1, *big2, *big32, *big2_32;
	BIGNUM *n, *r, *r_squared, *tmp;
	BN_CTX *bn_ctx = BN_CTX_new();
	int ret = 0;

	/* Initialize BIGNUMs */
	big1 = BN_new();
	big2 = BN_new();
	big32 = BN_new();
	r = BN_new();
	r_squared = BN_new();
	tmp = BN_new();
	big2_32 = BN_new();
	n = BN_new();
	if (!big1 || !big2 || !big32 || !r || !r_squared || !tmp || !big2_32 ||
	    !n) {
		fprintf(stderr, "Out of memory (bignum)\n");
		return -ENOMEM;
	}

	if (!BN_copy(n, key->n) || !BN_set_word(big1, 1L) ||
	    !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L))
		ret = -1;

	/* big2_32 = 2^32 */
	if (!BN_exp(big2_32, big2, big32, bn_ctx))
		ret = -1;

	/* Calculate n0_inv = -1 / n[0] mod 2^32 */
	if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) ||
	    !BN_sub(tmp, big2_32, tmp))
		ret = -1;
	*n0_invp = BN_get_word(tmp);

	/* Calculate R = 2^(# of key bits) */
	if (!BN_set_word(tmp, BN_num_bits(n)) ||
	    !BN_exp(r, big2, tmp, bn_ctx))
		ret = -1;

	/* Calculate r_squared = R^2 mod n */
	if (!BN_copy(r_squared, r) ||
	    !BN_mul(tmp, r_squared, r, bn_ctx) ||
	    !BN_mod(r_squared, tmp, n, bn_ctx))
		ret = -1;

	*modulusp = n;
	*r_squaredp = r_squared;

	BN_free(big1);
	BN_free(big2);
	BN_free(big32);
	BN_free(r);
	BN_free(tmp);
	BN_free(big2_32);
	if (ret) {
		fprintf(stderr, "Bignum operations failed\n");
		return -ENOMEM;
	}

	return ret;
}

static int fdt_add_bignum(void *blob, int noffset, const char *prop_name,
			  BIGNUM *num, int num_bits)
{
	int nwords = num_bits / 32;
	int size;
	uint32_t *buf, *ptr;
	BIGNUM *tmp, *big2, *big32, *big2_32;
	BN_CTX *ctx;
	int ret;

	tmp = BN_new();
	big2 = BN_new();
	big32 = BN_new();
	big2_32 = BN_new();
	if (!tmp || !big2 || !big32 || !big2_32) {
		fprintf(stderr, "Out of memory (bignum)\n");
		return -ENOMEM;
	}
	ctx = BN_CTX_new();
	if (!tmp) {
		fprintf(stderr, "Out of memory (bignum context)\n");
		return -ENOMEM;
	}
	BN_set_word(big2, 2L);
	BN_set_word(big32, 32L);
	BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */

	size = nwords * sizeof(uint32_t);
	buf = malloc(size);
	if (!buf) {
		fprintf(stderr, "Out of memory (%d bytes)\n", size);
		return -ENOMEM;
	}

	/* Write out modulus as big endian array of integers */
	for (ptr = buf + nwords - 1; ptr >= buf; ptr--) {
		BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */
		*ptr = cpu_to_fdt32(BN_get_word(tmp));
		BN_rshift(num, num, 32); /*  N = N/B */
	}

	ret = fdt_setprop(blob, noffset, prop_name, buf, size);
	if (ret) {
		fprintf(stderr, "Failed to write public key to FIT\n");
		return -ENOSPC;
	}
	free(buf);
	BN_free(tmp);
	BN_free(big2);
	BN_free(big32);
	BN_free(big2_32);

	return ret;
}

int rsa_imx_add_verify_data(struct image_sign_info *info, void *keydest)
{
	BIGNUM *modulus, *r_squared;
	uint32_t n0_inv;
	int parent, node;
	char name[100];
	int ret;
	int bits;
	RSA *rsa;

	debug("%s: Getting verification data\n", __func__);
	ret = rsa_get_priv_key(info->keydir, info->keyname, &rsa);
	if (ret)
		return ret;
	ret = rsa_imx_get_params(rsa, &n0_inv, &modulus, &r_squared);
	if (ret)
		return ret;
	bits = BN_num_bits(modulus);
	parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME);
	if (parent == -FDT_ERR_NOTFOUND) {
		parent = fdt_add_subnode(keydest, 0, FIT_SIG_NODENAME);
		if (parent < 0) {
			fprintf(stderr, "Couldn't create signature node: %s\n",
				fdt_strerror(parent));
			return -EINVAL;
		}
	}

	/* Either create or overwrite the named key node */
	snprintf(name, sizeof(name), "key-%s", info->keyname);
	node = fdt_subnode_offset(keydest, parent, name);
	if (node == -FDT_ERR_NOTFOUND) {
		node = fdt_add_subnode(keydest, parent, name);
		if (node < 0) {
			fprintf(stderr, "Could not create key subnode: %s\n",
				fdt_strerror(node));
			return -EINVAL;
		}
	} else if (node < 0) {
		fprintf(stderr, "Cannot select keys parent: %s\n",
			fdt_strerror(node));
		return -ENOSPC;
	}

	ret = fdt_setprop_string(keydest, node, "key-name-hint",
				 info->keyname);
	ret |= fdt_setprop_u32(keydest, node, "rsa,num-bits", bits);
	ret |= fdt_setprop_u32(keydest, node, "rsa,n0-inverse", n0_inv);
	ret |= fdt_add_bignum(keydest, node, "rsa,modulus", modulus, bits);
	ret |= fdt_add_bignum(keydest, node, "rsa,r-squared", r_squared, bits);
	ret |= fdt_setprop_string(keydest, node, FIT_ALGO_PROP,
				  info->algo->name);
	if (info->require_keys) {
		fdt_setprop_string(keydest, node, "required",
				   info->require_keys);
	}
	BN_free(modulus);
	BN_free(r_squared);
	if (ret)
		return -EIO;

	return 0;
}
