/*
	rsatest.c - a test for the RSA validator.

For this test a few files are required:

   rsa.pub.der    The RSA public key in DER format
   message.sha1   The SHA-1 hash of the signed data
   message.rsa    The RSA signature of the data


They can be created by executing the following steps:

1) echo "this is the message to be signed" > message

 Creates the message


2) openssl dgst -sha1 -binary -out message.sha1 message

 Creates the SHA-1 hash of the message


3) openssl genrsa -out rsa.key 2048

 Creates the 2048 bit private key for signing


4) openssl rsa -in rsa.key -out rsa.pub.der -outform der -pubout

 Creates the public DER key


5) openssl dgst -sha1 -sign rsa.key -binary -out message.rsa message

 Signs the message


*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "rsavalidator.h"

int readDer(unsigned char **modulo, int *mlen, unsigned int *exp);

int main(int argc, char **argv) {
	unsigned char *s;
	int slen;
	unsigned char *message;
	int mlen;
	unsigned char *n;
	int nlen;
	unsigned int e;

	FILE *mfile, *sfile;

	// Read the message (SHA-1)
	mfile = fopen("message.sha1", "r");
	fseek(mfile, 0, SEEK_END);
	mlen = ftell(mfile);
	fseek(mfile, 0, SEEK_SET);
	message = (unsigned char *)malloc(mlen);
	fread(message, mlen, 1, mfile);
	fclose(mfile);

	// Read the signature
	sfile = fopen("message.rsa", "r");
	fseek(sfile, 0, SEEK_END);
	slen = ftell(sfile);
	fseek(sfile, 0, SEEK_SET);
	s = (unsigned char *)malloc(slen);
	fread(s, slen, 1, sfile);
	fclose(sfile);

	// Read the public key
	readDer(&n, &nlen, &e);

	// Verify the message
	if (RSAverify(e, nlen, n, slen, s, mlen, message)) {
		printf("Verified!\n");
	} else {
		printf("Invalid!\n");
	}

	exit(0);
}

// DER file handling below this line

static int getLen(FILE *der) {
	int len;
	len = fgetc(der);
	if (len != 0x82) { return len; }
	len = fgetc(der) << 8;
	len |= fgetc(der);
	return len;
}

static int skipSeq(FILE *der) {
	if (fgetc(der) != 0x30) { return 0; }
	return getLen(der);
}

int readDer(unsigned char **modulo, int *mlen, unsigned int *exp) {
	FILE *der;
	int code;
	int len;
	int i;
	int e;

	// Read the public key
	der = fopen("rsa.pub.der", "r");
	if (!der) { printf("Error opening rsa.pub.der\n"); return 0; }
	if (skipSeq(der) == 0) { printf("Invalid der format.\n"); return 0; }

	// Find the bit string
	while (1) {
		code = fgetc(der);
		if (code != 0x03) {
			ungetc(0x30, der);
			len = skipSeq(der);
			fseek(der, len, SEEK_CUR);
		} else break;
	}
	getLen(der);

	// Skip leading 0
	fgetc(der);
	if (skipSeq(der) == 0) { printf("Invalid bit string.\n"); return 0; }

	// Get modulus
	code = fgetc(der);
	*mlen = getLen(der);
	if (code != 0x02 || *mlen <= 0) { printf("Invalid modulus.\n"); return 0; }
	*modulo = (unsigned char *)malloc(*mlen);
	fread(*modulo, *mlen, 1, der);

	// Get exponent
	code = fgetc(der);
	len = getLen(der);
	if (code != 0x02 || len <= 0 || len > 4) { printf("Invalid exponent.\n"); return 0; }
	e = 0;
	for (i = 0; i < len; i++) {
		e |= fgetc(der) << (8 * (len - 1 - i));
	}
	fclose(der);

	*exp = e;
	return 1;
}


