/*
 * 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);
	curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0L);             // The current signing server uses a self-signed cert
	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;
}
