/*
 * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <openssl/conf.h>
#include <openssl/err.h>
#include <openssl/opensslv.h>
#include <openssl/pem.h>
#include <openssl/sha.h>
#include <openssl/x509v3.h>

#include "cert.h"
#include "cmd_opt.h"
#include "debug.h"
#include "key.h"
#include "sha.h"

#define SERIAL_RAND_BITS	64

cert_t *certs;
unsigned int num_certs;

int rand_serial(BIGNUM *b, ASN1_INTEGER *ai)
{
	BIGNUM *btmp;
	int ret = 0;
	if (b)
		btmp = b;
	else
		btmp = BN_new();

	if (!btmp)
		return 0;

#if USING_OPENSSL3
	if (!BN_rand(btmp, SERIAL_RAND_BITS, 0, 0))
#else
	if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0))
#endif
		goto error;
	if (ai && !BN_to_ASN1_INTEGER(btmp, ai))
		goto error;

	ret = 1;

error:

	if (!b)
		BN_free(btmp);

	return ret;
}
const EVP_MD *get_digest(int alg)
{
	switch (alg) {
	case HASH_ALG_SHA256:
		return EVP_sha256();
	case HASH_ALG_SHA384:
		return EVP_sha384();
	case HASH_ALG_SHA512:
		return EVP_sha512();
	default:
		return NULL;
	}
}

int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value)
{
	X509_EXTENSION *ex;
	X509V3_CTX ctx;

	/* No configuration database */
	X509V3_set_ctx_nodb(&ctx);

	/* Set issuer and subject certificates in the context */
	X509V3_set_ctx(&ctx, issuer, subject, NULL, NULL, 0);
	ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
	if (!ex) {
		ERR_print_errors_fp(stdout);
		return 0;
	}

	X509_add_ext(subject, ex, -1);
	X509_EXTENSION_free(ex);

	return 1;
}

int cert_new(
	int md_alg,
	cert_t *cert,
	int days,
	int ca,
	STACK_OF(X509_EXTENSION) * sk)
{
	EVP_PKEY *pkey = keys[cert->key].key;
	cert_t *issuer_cert = &certs[cert->issuer];
	EVP_PKEY *ikey = keys[issuer_cert->key].key;
	X509 *issuer = issuer_cert->x;
	X509 *x;
	X509_EXTENSION *ex;
	X509_NAME *name;
	ASN1_INTEGER *sno;
	int i, num, rc = 0;
	EVP_MD_CTX *mdCtx;
	EVP_PKEY_CTX *pKeyCtx = NULL;

	/* Create the certificate structure */
	x = X509_new();
	if (!x) {
		return 0;
	}

	/* If we do not have a key, use the issuer key (the certificate will
	 * become self signed). This happens in content certificates. */
	if (!pkey) {
		pkey = ikey;
	}

	/* If we do not have an issuer certificate, use our own (the certificate
	 * will become self signed) */
	if (!issuer) {
		issuer = x;
	}

	mdCtx = EVP_MD_CTX_create();
	if (mdCtx == NULL) {
		ERR_print_errors_fp(stdout);
		goto END;
	}

	/* Sign the certificate with the issuer key */
	if (!EVP_DigestSignInit(mdCtx, &pKeyCtx, get_digest(md_alg), NULL, ikey)) {
		ERR_print_errors_fp(stdout);
		goto END;
	}

	/*
	 * Set additional parameters if issuing public key algorithm is RSA.
	 * This is not required for ECDSA.
	 */
	if (EVP_PKEY_base_id(ikey) == EVP_PKEY_RSA) {
		if (!EVP_PKEY_CTX_set_rsa_padding(pKeyCtx, RSA_PKCS1_PSS_PADDING)) {
			ERR_print_errors_fp(stdout);
			goto END;
		}

		if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pKeyCtx, EVP_MD_size(get_digest(md_alg)))) {
			ERR_print_errors_fp(stdout);
			goto END;
		}

		if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pKeyCtx, get_digest(md_alg))) {
			ERR_print_errors_fp(stdout);
			goto END;
		}
	}

	/* x509.v3 */
	X509_set_version(x, 2);

	/* Random serial number */
	sno = ASN1_INTEGER_new();
	rand_serial(NULL, sno);
	X509_set_serialNumber(x, sno);
	ASN1_INTEGER_free(sno);

	X509_gmtime_adj(X509_get_notBefore(x), 0);
	X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days);
	X509_set_pubkey(x, pkey);

	/* Subject name */
	name = X509_get_subject_name(x);
	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
			(const unsigned char *)cert->cn, -1, -1, 0);
	X509_set_subject_name(x, name);

	/* Issuer name */
	name = X509_get_issuer_name(x);
	X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC,
			(const unsigned char *)issuer_cert->cn, -1, -1, 0);
	X509_set_issuer_name(x, name);

	/* Add various extensions: standard extensions */
	cert_add_ext(issuer, x, NID_subject_key_identifier, "hash");
	cert_add_ext(issuer, x, NID_authority_key_identifier, "keyid:always");
	if (ca) {
		cert_add_ext(issuer, x, NID_basic_constraints, "CA:TRUE");
		cert_add_ext(issuer, x, NID_key_usage, "keyCertSign");
	} else {
		cert_add_ext(issuer, x, NID_basic_constraints, "CA:FALSE");
	}

	/* Add custom extensions */
	if (sk != NULL) {
		num = sk_X509_EXTENSION_num(sk);
		for (i = 0; i < num; i++) {
			ex = sk_X509_EXTENSION_value(sk, i);
			X509_add_ext(x, ex, -1);
		}
	}

	if (!X509_sign_ctx(x, mdCtx)) {
		ERR_print_errors_fp(stdout);
		goto END;
	}

	/* X509 certificate signed successfully */
	rc = 1;
	cert->x = x;

END:
	EVP_MD_CTX_destroy(mdCtx);
	return rc;
}

int cert_init(void)
{
	cmd_opt_t cmd_opt;
	cert_t *cert;
	unsigned int i;

	certs = malloc((num_def_certs * sizeof(def_certs[0]))
#ifdef PDEF_CERTS
		       + (num_pdef_certs * sizeof(pdef_certs[0]))
#endif
		       );
	if (certs == NULL) {
		ERROR("%s:%d Failed to allocate memory.\n", __func__, __LINE__);
		return 1;
	}

	memcpy(&certs[0], &def_certs[0],
	       (num_def_certs * sizeof(def_certs[0])));

#ifdef PDEF_CERTS
	memcpy(&certs[num_def_certs], &pdef_certs[0],
	       (num_pdef_certs * sizeof(pdef_certs[0])));

	num_certs = num_def_certs + num_pdef_certs;
#else
	num_certs = num_def_certs;
#endif

	for (i = 0; i < num_certs; i++) {
		cert = &certs[i];
		cmd_opt.long_opt.name = cert->opt;
		cmd_opt.long_opt.has_arg = required_argument;
		cmd_opt.long_opt.flag = NULL;
		cmd_opt.long_opt.val = CMD_OPT_CERT;
		cmd_opt.help_msg = cert->help_msg;
		cmd_opt_add(&cmd_opt);
	}

	return 0;
}

cert_t *cert_get_by_opt(const char *opt)
{
	cert_t *cert;
	unsigned int i;

	for (i = 0; i < num_certs; i++) {
		cert = &certs[i];
		if (0 == strcmp(cert->opt, opt)) {
			return cert;
		}
	}

	return NULL;
}

void cert_cleanup(void)
{
	unsigned int i;

	for (i = 0; i < num_certs; i++) {
		if (certs[i].fn != NULL) {
			void *ptr = (void *)certs[i].fn;

			certs[i].fn = NULL;
			free(ptr);
		}
	}
	free(certs);
}

