#include "com_example_demoactivity_NameActivity.h"

#include <Library/UniMate_Android.h>
#include "VerifySign.h"
#include <string.h>
#include <stdio.h>

/*
 * Class:     com_example_demoactivity_NameActivity
 * Method:    sign
 * Signature: ([B[BJJ[B)J
 */
JNIEXPORT jlong JNICALL Java_com_example_demoactivity_NameActivity_sign
  (JNIEnv *env, jclass cls, jbyteArray jpin, jlong jpinLen, jbyteArray jsrc, jlong jsrcLen, jbyteArray jcert, jlong jcertLen, jlong jhashOid, jbyteArray joutData, jlongArray joutDataLen)
{
	unsigned char *pin;
	unsigned char *srcData;
	unsigned char *cert;
	unsigned char hashOid = jhashOid;
	unsigned char *outData;
	long *outDataLen;
	char OID[100];
	int i;

	jboolean result;
	pin=(unsigned char *)env->GetByteArrayElements(jpin, &result);
	cert=(unsigned char *)env->GetByteArrayElements(jcert, &result);
	srcData=(unsigned char *)env->GetByteArrayElements(jsrc, &result);
	outData=(unsigned char *)env->GetByteArrayElements(joutData, &result);

	unsigned char resultData[256];
	long resultDataLen = 0;

	char message[128];
	long srcLen = jsrcLen;
	long certLen = jcertLen;
	long pinLen = jpinLen;
	pin[pinLen] = 0x00;
	srcData[srcLen] = 0x00;

	if(hashOid == 0)//MD5
	{
		strcpy(OID, "1.2.840.113549.2.5");
	}
	else if(hashOid == 1)//SHA1
	{
		strcpy(OID, "1.3.14.3.2.26");
	}
	else if(hashOid == 2)//SHA224
	{
		strcpy(OID, "2.16.840.1.101.3.4.2.4");
	}
	else if(hashOid == 3)//SHA256
	{
		strcpy(OID, "2.16.840.1.101.3.4.2.1");
	}
	else if(hashOid == 4)//SHA384
	{
		strcpy(OID, "2.16.840.1.101.3.4.2.2");
	}
	else if(hashOid == 5)//SHA512
	{
		strcpy(OID, "2.16.840.1.101.3.4.2.3");
	}
	else
	{
		env->ReleaseByteArrayElements(joutData, (jbyte*)outData, 0);
		env->ReleaseByteArrayElements(jcert, (jbyte*)cert, 0);
		env->ReleaseByteArrayElements(jsrc, (jbyte*)srcData, 0);
		env->ReleaseByteArrayElements(jpin, (jbyte*)pin, 0);
		return 0x887;
	}

	//DB_WARNING("sign params: OID : %s", OID);
	//DB_WARNING("pub text = %s", srcData);
	//DB_WARNING("pub text len = %d", srcLen);
	//DB_WARNING("pin = %s, pinlen = %d", pin, pinLen);

	int ret;
	ret = SignData((pbyte)cert, certLen, (char*)pin, srcData, srcLen, OID, resultData, &resultDataLen);
	if (ret != 0)
	{
		//DB_ERROR("JNI:SignData()error! return %04x", ret);
		env->ReleaseByteArrayElements(joutData, (jbyte*)outData, 0);
		env->ReleaseByteArrayElements(jcert, (jbyte*)cert, 0);
		env->ReleaseByteArrayElements(jsrc, (jbyte*)srcData, 0);
		env->ReleaseByteArrayElements(jpin, (jbyte*)pin, 0);
		return ret;
	}

	for (i=0; i<resultDataLen; ++i)
	{
		sprintf(message, "%02X", resultData[i]);
		strcat((char*)outData, message);
	}
	//DB_WARNING("JNI:sign result = %s", outData);

	outDataLen = (long*)env->GetLongArrayElements(joutDataLen, &result);
	outDataLen[0] = resultDataLen*2;
	env->ReleaseLongArrayElements(joutDataLen, (jlong*)outDataLen, 0);


	env->ReleaseByteArrayElements(joutData, (jbyte*)outData, 0);
	env->ReleaseByteArrayElements(jcert, (jbyte*)cert, 0);
	env->ReleaseByteArrayElements(jsrc, (jbyte*)srcData, 0);
	env->ReleaseByteArrayElements(jpin, (jbyte*)pin, 0);

	return 0;
}

/*
 * Class:     com_example_demoactivity_NameActivity
 * Method:    verifySignStatic
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL Java_com_example_demoactivity_NameActivity_verifySignStatic
(JNIEnv *env, jclass cls, jlong jhashOid, jbyteArray jpubText, jlong jpubTextLen, jbyteArray jcert, jlong jcertLen, jbyteArray jsignedData, jlong jsignedDataLen)
{
	int signType = jhashOid;
	unsigned char *pubText, *cert, *signedData;
	unsigned long pubTextLen = jpubTextLen;
	unsigned long certLen = jcertLen;
	unsigned long signedDataLen = jsignedDataLen;	
	long ret;
	jboolean result;

	pubText=(unsigned char *)env->GetByteArrayElements(jpubText, &result);
	cert=(unsigned char *)env->GetByteArrayElements(jcert, &result);
	signedData=(unsigned char *)env->GetByteArrayElements(jsignedData, &result);


	ret = VerifySign(signType,
					 cert, certLen,
					 pubText, pubTextLen,
					 signedData, signedDataLen);

	env->ReleaseByteArrayElements(jpubText, (jbyte*)pubText, 0);
	env->ReleaseByteArrayElements(jcert, (jbyte*)cert, 0);
	env->ReleaseByteArrayElements(jsignedData, (jbyte*)signedData, 0);

	return ret;
}