#include "storage.h"

#ifndef BORING_SSL
#include <openssl/opensslconf.h>
#include "unistd.h"
#endif

#include <tee_internal_api.h>

#include "stdlib.h"
#include <string.h>

#include "openssl/rsa.h"
#ifndef OPENSSL_NO_ECDSA
#include <openssl/ecdsa.h>
#endif
#ifndef OPENSSL_NO_DSA
#include <openssl/dsa.h>
#endif
#ifndef OPENSSL_NO_DH
#include <openssl/dh.h>
#endif

#ifdef USE_SCRYPTO_VER2_4
#include <openssl/bn.h>
#endif

#include <misc_defs.h>

void free_transient_object(TEE_ObjectHandle object)
{
	struct TransientObject * tr = &object->tr;

	switch(tr->info.objectType)
	{
	case TEE_TYPE_RSA_PUBLIC_KEY:
	case TEE_TYPE_RSA_KEYPAIR:
		{
		RSA *rsa = (RSA *)tr->attr.buffer;
		RSA_free(rsa);
		tr->attr.buf_len = 0;
		tr->attr.buffer = NULL;
		}
		break;
#ifndef OPENSSL_NO_DSA
	case TEE_TYPE_DSA_PUBLIC_KEY:
	case TEE_TYPE_DSA_KEYPAIR:
	{
		DSA *dsa = (DSA *)tr->attr.buffer;
		DSA_free(dsa);
		tr->attr.buf_len = 0;
		tr->attr.buffer = NULL;
		break;
	}
#endif /* OPENSSL_NO_DSA */
#ifndef OPENSSL_NO_DH
	case TEE_TYPE_DH_KEYPAIR:
	{
		DH *dh = (DH *)tr->attr.buffer;
		DH_free(dh);
		tr->attr.buf_len = 0;
		tr->attr.buffer = NULL;
		break;
	}
#endif /* OPENSSL_NO_DH */

#ifndef OPENSSL_NO_EC
#ifdef ECC_IMPLEMENTATION
	case TEE_TYPE_ECDSA_PUBLIC_KEY:
	case TEE_TYPE_ECDSA_KEYPAIR:
	case TEE_TYPE_ECDH_PUBLIC_KEY:
	case TEE_TYPE_ECDH_KEYPAIR: {
		int i = 0;
		EC_KEY *ec_key = (EC_KEY *)tr->attr.buffer;
		EC_KEY_free(ec_key);
		tr->attr.buf_len = 0;
		tr->attr.buffer = NULL;
		for (i = 0; i < min(tr->attr.attr_number, MAX_ATTRIBUTE_NUMBER); i++) {
			uint32_t id;
			id = tr->attr.attr_array[i].attributeID;
			tr->attr.attr_array[i].attributeID = 0;
			switch (id) {
				case TEE_ATTR_ECC_PRIVATE_VALUE: {
					BIGNUM *bn;
					unsigned long ptr;
					ptr = (unsigned long)tr->attr.attr_array[i].content.ref.buffer;
					bn = (BIGNUM *)ptr;
					BN_clear_free(bn);
					tr->attr.attr_array[i].content.ref.buffer = NULL;
					tr->attr.attr_array[i].content.ref.length = 0;
					break;
				}
				case TEE_ATTR_ECC_PUBLIC_VALUE_X:
				case TEE_ATTR_ECC_PUBLIC_VALUE_Y: {
                                       	BIGNUM *bn;
					unsigned long ptr;
					ptr = (unsigned long)tr->attr.attr_array[i].content.ref.buffer;
					bn = (BIGNUM *)ptr;
					BN_free(bn);
					tr->attr.attr_array[i].content.ref.buffer = NULL;
					tr->attr.attr_array[i].content.ref.length = 0;
					break;
				}
				case TEE_ATTR_ECC_CURVE: {
					tr->attr.attr_array[i].content.value.a = 0;
					continue;
				}
			}
		}
		tr->attr.attr_number = 0;
        	break;
	}
#endif // ECC_IMPLEMENTATION
#endif /* OPENSSL_NO_EC */

    	default:
		break;
	}

	if (tr->attr.buffer) {
		TEE_Free(tr->attr.buffer);
	}
	TEE_MemFill(&tr->attr, 0, sizeof(tr->attr)) ;
}

void TEE_FreeTransientObject(TEE_ObjectHandle object)
{
	struct TransientObject * tr;

	if (object == TEE_HANDLE_NULL) return;

	tr = &object->tr;

	free_transient_object(object);
	TEE_Free(tr);
}

