/**
* \file rsa_wrapper.c
* \brief RSA wrapper for CryptoCore/own crypto.
* \author Roman Pasechnik (r.pasechnik@samsung.com)
* \version 0.1
* \date Created Jan 14, 2014
* \par In Samsung Ukraine R&D Center (SURC) under a contract between
* \par LLC "Samsung Electronics Ukraine Company" (Kiev, Ukraine) and
* \par "Samsung Elecrtronics Co", Ltd (Seoul, Republic of Korea)
* \par Copyright: (c) Samsung Electronics Co, Ltd 2014. All rights reserved.
**/

#include "rsa/rsa_wrapper.h"
#include "CommLayerData.h"
#include "log.h"


#ifdef USE_CRYPTOCORE
#include "openssl/objects/objects.h"

static unsigned long mldap_rsa_exponent = RSA_EXPONENT;

void mldap_rsa_set_exponent(unsigned long exp)
{
	mldap_rsa_exponent = exp;
}

unsigned long mldap_rsa_get_exponent(void)
{
	return mldap_rsa_exponent;
}

int mldap_rsa_gen_key(RSA *rsa, int bits, unsigned long e)
{
	BIGNUM *pubExp = NULL;
	int ret = 0;
	pubExp = BN_new();
	if (!pubExp) {
		return PLATFORM_INTERNAL_ERROR;
	}
	BN_set_word(pubExp, e);
	ret = RSA_generate_key_ex(rsa, bits, pubExp, NULL);
	BN_clear_free(pubExp);

	if (ret == 1) {
		return NO_ERROR;
	} else {
		LOGE("mldap_rsa_gen_key failed");
		return PLATFORM_INTERNAL_ERROR;
	}
}

int mldap_rsa_pkcs1_sign(RSA *rsa, int hash_id, int hashlen, unsigned char *hash, unsigned char *sig)
{
	unsigned int siglen = BN_num_bytes(rsa->n);

	if (hash_id == RSA_SHA1)
		hash_id = NID_sha1;
	else if (hash_id == RSA_SHA256)
		hash_id = NID_sha256;
	else if (hash_id == RSA_SHA512)
		hash_id = NID_sha512;

	if (RSA_sign(hash_id, hash, hashlen, sig, &siglen, rsa) == 1) {
		return NO_ERROR;
	} else {
		LOGE("mldap_rsa_pkcs1_sign failed");
		return PLATFORM_INTERNAL_ERROR;
	}
}

int mldap_rsa_pkcs1_verify(RSA *rsa, int hash_id, int hashlen, unsigned char *hash, unsigned char *sig)
{
	if (hash_id == RSA_SHA1)
		hash_id = NID_sha1;
	else if (hash_id == RSA_SHA256)
		hash_id = NID_sha256;
	else if (hash_id == RSA_SHA512)
		hash_id = NID_sha512;

	if (RSA_verify(hash_id, hash, hashlen, sig, BN_num_bytes(rsa->n), rsa) == 1) {
		return NO_ERROR;
	} else {
		LOGE("mldap_rsa_pkcs1_verify failed");
		return PLATFORM_INTERNAL_ERROR;
	}
}

int mldap_rsa_check_keypair(RSA *rsa)
{
	if (RSA_check_key(rsa) == 1) {
		return NO_ERROR;
	} else {
		LOGE("mldap_rsa_check_keypair failed");
		return PLATFORM_INTERNAL_ERROR;
	}
}

#else

void mldap_rsa_set_exponent(unsigned long exp)
{
	rsa_set_exponent(exp);
}

unsigned long mldap_rsa_get_exponent(void)
{
	return rsa_get_exponent();
}

int mldap_rsa_gen_key(RSA *rsa, int bits, unsigned long e)
{
	return rsa_gen_key_mldap(rsa, bits, e);
}

int mldap_rsa_pkcs1_sign(RSA *rsa, int hash_id, int hashlen, unsigned char *hash, unsigned char *sig)
{
	return rsa_pkcs1_sign_mldap(rsa, hash_id, hashlen, hash, sig);
}

int mldap_rsa_pkcs1_verify(RSA *rsa, int hash_id, int hashlen, unsigned char *hash, unsigned char *sig)
{
	return rsa_pkcs1_verify_mldap(rsa, hash_id, hashlen, hash, sig);
}

int mldap_rsa_check_keypair(RSA *rsa)
{
	return rsa_check_keypair(rsa);
}

#endif

RSA* mldap_RSA_new(void)
{
	return RSA_new();
}

void mldap_RSA_free(RSA *r)
{
	RSA_free(r);
}