/*
 utils.c

 Copyright NTT MCL, 2000.

 Duncan S Wong
 Security Group, NTT MCL
 July 2000
*/

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <gmp.h>
#include "esign.h"
#include "utils.h"

/*
 Read public key info from a file

 Return 1 if succeed, otherwise 0
*/
int get_pubKey(ESIGN_PUB_KEY *publicKey, FILE *fp)
{
char one_line[2*MAX_MODULUS_LEN/8+15];
char field_id[10];
char field_body[2*MAX_MODULUS_LEN/8+2];
char **endptr = NULL;
unsigned char sign;
long digits;

	if ( fgets(one_line, 2*MAX_MODULUS_LEN/8+14, fp) == NULL ) {
		fprintf(stderr, "get_pubKey cannot read n: %s\n", strerror(errno));
		return 0;
	}

	if ( !parse_field(one_line, field_id, field_body) ) return 0;
	mpz_set_str(publicKey->n, field_body, 0);

	/*
	printf("get_pubKey: publicKey->n =\n\t");
	printf("%s\n", mpz_get_str(NULL, 16, publicKey->n));
	*/

	if ( fgets(one_line, 2*MAX_MODULUS_LEN/8+14, fp) == NULL ) {
		fprintf(stderr, "get_pubKey cannot read e: %s\n", strerror(errno));
		return 0;
	}
	if ( !parse_field(one_line, field_id, field_body) ) return 0;
	mpz_set_str(publicKey->e, field_body, 0);

	/*
	printf("get_pubKey: publicKey->e =\n\t");
	printf("%s\n", mpz_get_str(NULL, 16, publicKey->e));
	*/

	if ( fgets(one_line, 2*MAX_MODULUS_LEN/8+14, fp) == NULL ) {
		fprintf(stderr, "get_pubKey cannot read Hid: %s\n", strerror(errno));
		return 0;
	}
	if ( !parse_field(one_line, field_id, field_body) ) return 0;
	publicKey->Hid = atoi(field_body);

	if ( fgets(one_line, 2*MAX_MODULUS_LEN/8+14, fp) == NULL ) {
		fprintf(stderr, "get_pubKey cannot read pLen: %s\n", strerror(errno));
		return 0;
	}
	if ( !parse_field(one_line, field_id, field_body) ) return 0;
	publicKey->pLen = strtoul(field_body, endptr, 10);

	return 1;
}


/*
 Read private key info from a file

 Return 1 if succeed, otherwise 0
*/
int get_privKey(ESIGN_PRIV_KEY *privateKey, FILE *fp)
{
char one_line[2*MAX_PRIME_LEN/8+15];
char field_id[10];
char field_body[2*MAX_PRIME_LEN/8+2];
char **endptr = NULL;
unsigned char sign;
long digits;

	if ( fgets(one_line, 2*MAX_PRIME_LEN/8+14, fp) == NULL ) {
		fprintf(stderr, "get_privkey cannot read p: %s\n", strerror(errno));
		return 0;
	}

	if ( !parse_field(one_line, field_id, field_body) ) return 0;
	mpz_set_str(privateKey->p, field_body, 0);

	/*
	printf("get_privKey: privateKey->p =\n\t");
	printf("%s\n", mpz_get_str(NULL, 16, privateKey->p));
	*/

	if ( fgets(one_line, 2*MAX_PRIME_LEN/8+14, fp) == NULL ) {
		fprintf(stderr, "get_privKey cannot read q: %s\n", strerror(errno));
		return 0;
	}
	if ( !parse_field(one_line, field_id, field_body) ) return 0;
	mpz_set_str(privateKey->q, field_body, 0);

	/*
	printf("get_privKey: privateKey->q =\n\t");
	printf("%s\n", mpz_get_str(NULL, 16, privateKey->q));
	*/

	return 1;
}


/*
 Open filename for read, return NULL if problem
*/
FILE *open_input(const char *filename)
{
FILE *fp;
errno = 0;

	if(filename == NULL) filename = "\0";
	fp = fopen(filename,"r");
	if (fp == NULL)
		fprintf(stderr, "open_input(\"%s\") failed: %s\n",
		        filename, strerror(errno));

	return fp;
}


/*
 Open filenmae for write, return NULL if problem
*/
FILE *open_output(const char *filename)
{
FILE *fp;
errno = 0;

	if(filename == NULL) filename = "\0";
   fp = fopen(filename,"w+");
   if (fp == NULL)
      fprintf(stderr, "open_output(\"%s\") failed: %s\n",
              filename, strerror(errno));

   return fp;
}


/*
 Parse a line in the format "field_id = field_body"
*/
int parse_field(char *one_line, char *field_id, char *field_body)
{
const char SEPCHARS[] = " \n";
char *tmp1, *tmp2, *tmp3;

	tmp1 = strtok(one_line, SEPCHARS);
	tmp2 = strtok(NULL, " ");
	tmp3 = strtok(NULL, SEPCHARS);
	if(tmp1 == NULL || tmp2 == NULL || tmp3 == NULL) {
		fprintf(stderr, "parse_field finds unrecognized line structure: %s\n",
		        strerror(errno));
		return 0;
	}
	strcpy(field_id, tmp1);
	strcpy(field_body, tmp3);
	/*
	printf("parse_field: field_id = %s\n",field_id);
	printf("parse_field: field_body = %s\n",field_body);
	*/

	return 1;
}


/*
 Copy len BYTEs from from to to
*/
void assignBYTE(BYTE *to, BYTE *from, WORD len)
{
WORD i;

   for(i=0; i<len; i++)
      to[i] = from[i];
}


/*
 Convert (mp_srcptr) xp to a sequence of bytes in big-endian, (BYTE *) xp_raw
*/
void WORD2BYTE(BYTE *xp_raw, mp_srcptr xp, mp_size_t xsize)
{
long i;
BYTE *tmp_p;

	tmp_p = xp_raw;
	for(i=xsize-1; i>=0; i--) {
		tmp_p[0] = xp[i] >> 24;
		tmp_p[1] = (xp[i] >> 16) & 0xff;
		tmp_p[2] = (xp[i] >> 8) & 0xff;
		tmp_p[3] = xp[i] & 0xff;
		tmp_p += 4;
	}
}


/*
 Convert (BYTE *) raw to (mpz_ptr) x
*/
mp_size_t BYTE2WORD(mpz_ptr x, BYTE *raw, mp_size_t size)
{
long i;
BYTE *raw_ascii, *tmp_p;

	raw_ascii = (BYTE *) malloc (size*2+1);
	tmp_p = raw_ascii;

	for(i=0; i<size; i++) {
		sprintf(tmp_p,"%02x", raw[i]);
		tmp_p+=2;
	}
	/* printf("BYTE2WORD: raw_ascii =\n\t%s\n\n", raw_ascii); */

	mpz_set_str(x, raw_ascii, 16);

	memset(raw_ascii, 0, size*2+1);
	free(raw_ascii);

	return mpz_size(x);
}
