/*
 * Copyright (c) 2017-2023 ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <stddef.h>
#include <string.h>

#include <mbedtls/oid.h>
#include <mbedtls/x509.h>

#include <drivers/arm/cryptocell/713/bsv_api.h>
#include <drivers/arm/cryptocell/713/bsv_crypto_asym_api.h>
#include <drivers/auth/crypto_mod.h>

#include <platform_def.h>

#define LIB_NAME		"CryptoCell 713 SBROM"
#define RSA_SALT_LEN		32
#define RSA_EXPONENT		65537

/*
 * AlgorithmIdentifier  ::=  SEQUENCE  {
 *     algorithm            OBJECT IDENTIFIER,
 *     parameters           ANY DEFINED BY algorithm OPTIONAL
 * }
 *
 * SubjectPublicKeyInfo  ::=  SEQUENCE  {
 *     algorithm            AlgorithmIdentifier,
 *     subjectPublicKey     BIT STRING
 * }
 *
 * DigestInfo ::= SEQUENCE {
 *     digestAlgorithm      AlgorithmIdentifier,
 *     digest               OCTET STRING
 * }
 *
 *  RSASSA-PSS-params ::= SEQUENCE {
 *     hashAlgorithm        [0] HashAlgorithm,
 *     maskGenAlgorithm     [1] MaskGenAlgorithm,
 *     saltLength           [2] INTEGER,
 *     trailerField         [3] TrailerField    DEFAULT trailerFieldBC
 * }
 */

/*
 * Initialize the library and export the descriptor
 */
static void init(void)
{
	CCError_t ret;
	uint32_t lcs;

	/* Initialize CC SBROM */
	ret = CC_BsvInit((uintptr_t)PLAT_CRYPTOCELL_BASE);
	if (ret != CC_OK) {
		ERROR("CryptoCell CC_BsvInit() error %x\n", ret);
		panic();
	}

	/* Initialize lifecycle state */
	ret = CC_BsvGetAndInitLcs((uintptr_t)PLAT_CRYPTOCELL_BASE, &lcs);
	if (ret != CC_OK) {
		ERROR("CryptoCell CC_BsvGetAndInitLcs() error %x\n", ret);
		panic();
	}
}

/*
 * Verify a signature.
 *
 * Parameters are passed using the DER encoding format following the ASN.1
 * structures detailed above.
 */
static int verify_signature(void *data_ptr, unsigned int data_len,
			    void *sig_ptr, unsigned int sig_len,
			    void *sig_alg, unsigned int sig_alg_len,
			    void *pk_ptr, unsigned int pk_len)
{
	CCError_t error;
	CCBsvNBuff_t NBuff;
	CCBsvSignature_t signature;
	int rc, exp, expected_salt_len;
	mbedtls_asn1_buf sig_oid, alg_oid, params;
	mbedtls_md_type_t md_alg, mgf1_hash_id;
	mbedtls_pk_type_t pk_alg;

	size_t len;
	uint8_t *p, *end;
	CCHashResult_t digest;
	CCBool_t is_verified;
	/* This is a rather large array, we don't want it on stack */
	static uint32_t workspace[BSV_RSA_WORKSPACE_MIN_SIZE];

	/* Verify the signature algorithm */
	/* Get pointers to signature OID and parameters */
	p = sig_alg;
	end = p + sig_alg_len;
	rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &params);
	if (rc != 0) {
		return CRYPTO_ERR_SIGNATURE;
	}

	/* Get the actual signature algorithm (MD + PK) */
	rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg);
	if (rc != 0) {
		return CRYPTO_ERR_SIGNATURE;
	}

	/* The CryptoCell only supports RSASSA-PSS signature */
	if (pk_alg != MBEDTLS_PK_RSASSA_PSS || md_alg != MBEDTLS_MD_NONE) {
		return CRYPTO_ERR_SIGNATURE;
	}

	/* Verify the RSASSA-PSS params */
	/* The trailer field is verified to be 0xBC internally by this API */
	rc = mbedtls_x509_get_rsassa_pss_params(&params, &md_alg,
			&mgf1_hash_id,
			&expected_salt_len);
	if (rc != 0) {
		return CRYPTO_ERR_SIGNATURE;
	}

	/* The CryptoCell only supports SHA256 as hash algorithm */
	if (md_alg != MBEDTLS_MD_SHA256 ||
	    mgf1_hash_id != MBEDTLS_MD_SHA256) {
		return CRYPTO_ERR_SIGNATURE;
	}

	if (expected_salt_len != RSA_SALT_LEN) {
		return CRYPTO_ERR_SIGNATURE;
	}

	/* Parse the public key */
	p = pk_ptr;
	end = p + pk_len;
	rc = mbedtls_asn1_get_tag(&p, end, &len,
			MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
	if (rc != 0) {
		return CRYPTO_ERR_SIGNATURE;
	}

	end = p + len;
	rc = mbedtls_asn1_get_alg_null(&p, end, &alg_oid);
	if (rc != 0) {
		return CRYPTO_ERR_SIGNATURE;
	}

	if (mbedtls_oid_get_pk_alg(&alg_oid, &pk_alg) != 0) {
		return CRYPTO_ERR_SIGNATURE;
	}

	if (pk_alg != MBEDTLS_PK_RSA) {
		return CRYPTO_ERR_SIGNATURE;
	}

	rc = mbedtls_asn1_get_bitstring_null(&p, end, &len);
	if (rc != 0) {
		return CRYPTO_ERR_SIGNATURE;
	}

	rc = mbedtls_asn1_get_tag(&p, end, &len,
				MBEDTLS_ASN1_CONSTRUCTED |
				MBEDTLS_ASN1_SEQUENCE);
	if (rc != 0) {
		return CRYPTO_ERR_SIGNATURE;
	}

	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER);
	if (rc != 0) {
		return CRYPTO_ERR_SIGNATURE;
	}

	if (*p == 0) {
		p++; len--;
	}
	if (len != BSV_CERT_RSA_KEY_SIZE_IN_BYTES || ((p + len) > end)) {
		return CRYPTO_ERR_SIGNATURE;
	}

	/*
	 * Copy N from certificate.
	 */
	memcpy(NBuff, p, BSV_CERT_RSA_KEY_SIZE_IN_BYTES);

	/* Verify the RSA exponent */
	p += len;
	rc = mbedtls_asn1_get_int(&p, end, &exp);
	if (rc != 0) {
		return CRYPTO_ERR_SIGNATURE;
	}

	if (exp != RSA_EXPONENT) {
		return CRYPTO_ERR_SIGNATURE;
	}

	/* Get the signature (bitstring) */
	p = sig_ptr;
	end = p + sig_len;
	rc = mbedtls_asn1_get_bitstring_null(&p, end, &len);
	if (rc != 0) {
		return CRYPTO_ERR_SIGNATURE;
	}

	if (len != BSV_CERT_RSA_KEY_SIZE_IN_BYTES || ((p + len) > end)) {
		return CRYPTO_ERR_SIGNATURE;
	}

	/*
	 * Copy the signature (in BE format)
	 */
	memcpy((uint8_t *)signature, p, BSV_CERT_RSA_KEY_SIZE_IN_BYTES);

	error = CC_BsvSha256((uintptr_t)PLAT_CRYPTOCELL_BASE,
			     data_ptr, data_len, digest);
	if (error != CC_OK) {
		return CRYPTO_ERR_SIGNATURE;
	}

	/* Verify the signature */
	error = CC_BsvRsaPssVerify((uintptr_t)PLAT_CRYPTOCELL_BASE, NBuff,
				    NULL, signature, digest, workspace,
				    BSV_RSA_WORKSPACE_MIN_SIZE, &is_verified);
	if ((error != CC_OK) || (is_verified != CC_TRUE)) {
		return CRYPTO_ERR_SIGNATURE;
	}

	/* Signature verification success */
	return CRYPTO_SUCCESS;
}

/*
 * Match a hash
 *
 * Digest info is passed in DER format following the ASN.1 structure detailed
 * above.
 */
static int verify_hash(void *data_ptr, unsigned int data_len,
		       void *digest_info_ptr, unsigned int digest_info_len)
{
	mbedtls_asn1_buf hash_oid, params;
	mbedtls_md_type_t md_alg;
	uint8_t *p, *end, *hash;
	CCHashResult_t pubKeyHash;
	size_t len;
	int rc;
	CCError_t error;

	/* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
	p = digest_info_ptr;
	end = p + digest_info_len;
	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
				  MBEDTLS_ASN1_SEQUENCE);
	if (rc != 0) {
		return CRYPTO_ERR_HASH;
	}

	/* Get the hash algorithm */
	rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
	if (rc != 0) {
		return CRYPTO_ERR_HASH;
	}

	rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
	if (rc != 0) {
		return CRYPTO_ERR_HASH;
	}

	/* Verify that hash algorithm is SHA256 */
	if (md_alg != MBEDTLS_MD_SHA256) {
		return CRYPTO_ERR_HASH;
	}

	/* Hash should be octet string type */
	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
	if (rc != 0) {
		return CRYPTO_ERR_HASH;
	}

	/* Length of hash must match the algorithm's size */
	if (len != HASH_RESULT_SIZE_IN_BYTES) {
		return CRYPTO_ERR_HASH;
	}

	hash = p;
	error = CC_BsvSha256((uintptr_t)PLAT_CRYPTOCELL_BASE, data_ptr,
			     data_len, pubKeyHash);
	if (error != CC_OK) {
		return CRYPTO_ERR_HASH;
	}

	rc = memcmp(pubKeyHash, hash, HASH_RESULT_SIZE_IN_BYTES);
	if (rc != 0) {
		return CRYPTO_ERR_HASH;
	}

	return CRYPTO_SUCCESS;
}

/*
 * Register crypto library descriptor
 */
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
