/* Copyright 2023 The ChromiumOS Authors
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <dlfcn.h>

#include <nss/pkcs11.h>

#include "2common.h"
#include "host_p11.h"
#include "vboot_host.h"
#include "util_misc.h"

// We only maintain one global p11 module at a time.
static CK_FUNCTION_LIST_PTR p11 = NULL;

static void *pkcs11_load(const char *mspec, CK_FUNCTION_LIST_PTR_PTR funcs)
{
	void *mod;
	CK_RV rv;
	CK_RV (*c_get_function_list)(CK_FUNCTION_LIST_PTR_PTR p11);

	if (mspec == NULL)
		return NULL;

	mod = dlopen(mspec, RTLD_LAZY);
	if (mod == NULL) {
		fprintf(stderr, "dlopen failed: %s\n", dlerror());
		return NULL;
	}

	/* Get the list of function pointers */
	c_get_function_list =
		(CK_RV(*)(CK_FUNCTION_LIST_PTR_PTR))dlsym(mod, "C_GetFunctionList");
	if (!c_get_function_list)
		goto err;
	rv = c_get_function_list(funcs);
	if (rv == CKR_OK)
		return mod;
	fprintf(stderr, "C_GetFunctionList failed 0x%lx", rv);
err:
	dlclose(mod);
	return NULL;
}

static vb2_error_t pkcs11_find(CK_SESSION_HANDLE session, CK_ATTRIBUTE attributes[],
			       CK_ULONG num_attributes, CK_OBJECT_HANDLE *object)
{
	CK_RV result = p11->C_FindObjectsInit(session, attributes, num_attributes);
	if (result != CKR_OK)
		return VB2_ERROR_UNKNOWN;

	CK_ULONG object_count = 1;
	result = p11->C_FindObjects(session, object, 1, &object_count);
	if (result != CKR_OK || object_count == 0)
		return VB2_ERROR_UNKNOWN;

	result = p11->C_FindObjectsFinal(session);
	if (result != CKR_OK)
		return VB2_ERROR_UNKNOWN;

	return VB2_SUCCESS;
}

static enum vb2_hash_algorithm
pkcs11_mechanism_type_to_hash_alg(CK_MECHANISM_TYPE p11_mechanism)
{
	switch (p11_mechanism) {
	case CKM_SHA1_RSA_PKCS:
		return VB2_HASH_SHA1;
	case CKM_SHA256_RSA_PKCS:
		return VB2_HASH_SHA256;
	case CKM_SHA512_RSA_PKCS:
		return VB2_HASH_SHA512;
	}
	return VB2_HASH_INVALID;
}

vb2_error_t pkcs11_init(const char *pkcs11_lib)
{
	static char *loaded_pkcs11_lib = NULL;
	static void *pkcs11_mod = NULL;
	if (pkcs11_lib == NULL) {
		fprintf(stderr, "Missing the path of pkcs11 library\n");
		return VB2_ERROR_UNKNOWN;
	}
	if (loaded_pkcs11_lib) {
		/* Return success if the same pkcs11 library is already loaded */
		if (strcmp(loaded_pkcs11_lib, pkcs11_lib) == 0)
			return VB2_SUCCESS;
		fprintf(stderr, "Pkcs11 module is already loaded\n");
		return VB2_ERROR_UNKNOWN;
	}

	pkcs11_mod = pkcs11_load(pkcs11_lib, &p11);
	if (pkcs11_mod == NULL) {
		fprintf(stderr, "Failed to load pkcs11 library '%s'\n", pkcs11_lib);
		return VB2_ERROR_UNKNOWN;
	}

	CK_RV result = p11->C_Initialize(NULL);
	if (result != CKR_OK) {
		fprintf(stderr, "Failed to C_Initialize\n");
		dlclose(pkcs11_mod);
		pkcs11_mod = NULL;
		return VB2_ERROR_UNKNOWN;
	}
	loaded_pkcs11_lib = strdup(pkcs11_lib);
	return VB2_SUCCESS;
}

vb2_error_t pkcs11_get_key(int slot_id, char *label, struct pkcs11_key *p11_key)
{
	if (!p11) {
		fprintf(stderr, "pkcs11 is not loaded\n");
		return VB2_ERROR_UNKNOWN;
	}

	CK_RV result = p11->C_OpenSession(slot_id, CKF_SERIAL_SESSION | CKF_RW_SESSION, NULL,
					  NULL, &p11_key->session);
	if (result != CKR_OK) {
		fprintf(stderr, "Failed to open session with slot id %d\n", slot_id);
		return VB2_ERROR_UNKNOWN;
	}

	/* Find the private key */
	CK_OBJECT_CLASS class_value = CKO_PRIVATE_KEY;
	CK_ATTRIBUTE attributes[] = {
		{CKA_CLASS, &class_value, sizeof(class_value)},
		{CKA_LABEL, label, strlen(label)},
	};
	if (pkcs11_find(p11_key->session, attributes, ARRAY_SIZE(attributes),
			&p11_key->handle) != VB2_SUCCESS) {
		fprintf(stderr, "Failed to find the key with label '%s'\n", label);
		return VB2_ERROR_UNKNOWN;
	}

	return VB2_SUCCESS;
}

enum vb2_hash_algorithm pkcs11_get_hash_alg(struct pkcs11_key *p11_key)
{
	/* For PKCS#11 modules that support CKA_ALLOWED_MECHANISMS, we'll use the attribute
	 * to determine the correct mechanism to use. However, not all PKCS#11 modules
	 * support CKA_ALLOWED_MECHANISMS. In the event that we need to support such a
	 * module, we'll then need to determine the the mechanism to use from the key type
	 * and key size. That probably involves assuming we'll use PKCS#1 v1.5 padding for
	 * RSA. */
	CK_ATTRIBUTE mechanism_attr = {CKA_ALLOWED_MECHANISMS, NULL, 0};
	if (p11->C_GetAttributeValue(p11_key->session, p11_key->handle, &mechanism_attr, 1) !=
	    CKR_OK) {
		fprintf(stderr, "Failed to get mechanisum attribute length\n");
		return VB2_HASH_INVALID;
	}
	mechanism_attr.pValue = malloc(mechanism_attr.ulValueLen);
	if (p11->C_GetAttributeValue(p11_key->session, p11_key->handle, &mechanism_attr, 1) !=
	    CKR_OK) {
		fprintf(stderr, "Failed to get mechanisum attribute value\n");
		free(mechanism_attr.pValue);
		return VB2_HASH_INVALID;
	}
	CK_MECHANISM_TYPE *mechanisms = mechanism_attr.pValue;
	uint32_t mechanism_count = mechanism_attr.ulValueLen / sizeof(CK_MECHANISM_TYPE);
	enum vb2_hash_algorithm hash_alg = VB2_HASH_INVALID;
	for (int i = 0; i < mechanism_count; ++i) {
		hash_alg = pkcs11_mechanism_type_to_hash_alg(mechanisms[i]);
		if (hash_alg != VB2_HASH_INVALID)
			break;
	}
	free(mechanism_attr.pValue);
	return hash_alg;
}

enum vb2_signature_algorithm pkcs11_get_sig_alg(struct pkcs11_key *p11_key)
{
	if (!p11) {
		fprintf(stderr, "pkcs11 is not loaded\n");
		return VB2_SIG_INVALID;
	}
	CK_ULONG modulus_bits = 0;
	CK_ATTRIBUTE modulus_attr = {CKA_MODULUS_BITS, &modulus_bits, sizeof(modulus_bits)};
	if (p11->C_GetAttributeValue(p11_key->session, p11_key->handle, &modulus_attr, 1) !=
	    CKR_OK) {
		fprintf(stderr, "Failed to get modulus bits\n");
		return VB2_SIG_INVALID;
	}

	CK_ATTRIBUTE exponent_attr = {CKA_PUBLIC_EXPONENT, NULL, 0};
	if (p11->C_GetAttributeValue(p11_key->session, p11_key->handle, &exponent_attr, 1) !=
	    CKR_OK) {
		fprintf(stderr, "Failed to get exponent attribute length\n");
		return VB2_SIG_INVALID;
	}
	CK_ULONG exp_size = exponent_attr.ulValueLen;
	if (exp_size > 4) {
		fprintf(stderr, "Exponent size is too large\n");
		return VB2_SIG_INVALID;
	}
	exponent_attr.pValue = malloc(exp_size);
	if (p11->C_GetAttributeValue(p11_key->session, p11_key->handle, &exponent_attr, 1) !=
	    CKR_OK) {
		fprintf(stderr, "Failed to get exponent attribute value\n");
		free(exponent_attr.pValue);
		return VB2_SIG_INVALID;
	}
	// Parse the CKA_PUBLIC_EXPONENT in Big-endian.
	CK_BYTE *exp_value = exponent_attr.pValue;
	uint32_t exp = 0;
	for (int i = 0; i < exp_size; ++i)
		exp = (exp << 8) + exp_value[i];
	free(exponent_attr.pValue);

	return vb2_get_sig_alg(exp, modulus_bits);
}

vb2_error_t pkcs11_sign(struct pkcs11_key *p11_key, enum vb2_hash_algorithm hash_alg,
			const uint8_t *data, int data_size, uint8_t *sig, CK_ULONG sig_size)
{
	if (!p11) {
		fprintf(stderr, "pkcs11 is not loaded\n");
		return VB2_ERROR_UNKNOWN;
	}

	CK_MECHANISM mechanism;
	switch (hash_alg) {
	case VB2_HASH_SHA1:
		mechanism.mechanism = CKM_SHA1_RSA_PKCS;
		break;
	case VB2_HASH_SHA256:
		mechanism.mechanism = CKM_SHA256_RSA_PKCS;
		break;
	case VB2_HASH_SHA512:
		mechanism.mechanism = CKM_SHA512_RSA_PKCS;
		break;
	default:
		fprintf(stderr, "Unsupported hash algorithm %d\n", hash_alg);
		return VB2_ERROR_UNKNOWN;
	}
	mechanism.pParameter = NULL;
	mechanism.ulParameterLen = 0;

	CK_RV result = p11->C_SignInit(p11_key->session, &mechanism, p11_key->handle);
	if (result != CKR_OK) {
		fprintf(stderr, "Failed to sign init\n");
		return VB2_ERROR_UNKNOWN;
	}
	result =
		p11->C_Sign(p11_key->session, (unsigned char *)data, data_size, sig, &sig_size);
	if (result != CKR_OK) {
		fprintf(stderr, "Failed to sign\n");
		return VB2_ERROR_UNKNOWN;
	}
	return VB2_SUCCESS;
}

void pkcs11_free_key(struct pkcs11_key *p11_key)
{
	if (!p11) {
		fprintf(stderr, "pkcs11 is not loaded\n");
		return;
	}
	CK_RV result = p11->C_CloseSession(p11_key->session);
	if (result != CKR_OK)
		fprintf(stderr, "Failed to close session\n");
	free(p11_key);
}
