#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#include "dx_exe_sign_app.h"
#include "CryptoEngine2.h"

/*------------------
    GLOBAL variables
---------------------*/

/* name of the sign section */
char dx_sign_section_name[] = "dx_sign_sct";


char sign_init[DX_DM_SIGN_LEN_IN_BYTES] = 
{
  0,
};

/* private exponent */
unsigned char   g_PrivExponent[DX_MAX_PK_EXPONENT_SIZE_IN_BYTES];

/* public exponent */
unsigned char   g_PubExponent[DX_MAX_PK_EXPONENT_SIZE_IN_BYTES];

/* modulus */
unsigned char   g_Modulus[DX_MAX_PK_MODULUS_SIZE_IN_BYTES];

/* key modulus size */
int             g_ModulusSize;

/* public exponent size */
int             g_ExponentSize;

/* signature offset in the new elf file */
int             g_SignOffset;

/*--------------------------------
    PROTOTYPES
-----------------------------------*/

/*
 This function insertes a sign section into the ELF file and updates the appropriate
 Input - file name of ELF file, the size of the file. 
*/
static int dx_add_elf_sign_section(char* elfFileName);

/* 
  this function inserts data from the data file into the sign section of the elf file
*/
static int dx_insert_sign_data(char* dataFilename_ptr);

/*
  updates the section table entry of the sign section with the length
*/
static int dx_update_section_table(int len);

/* check if the first range is fully before second range, fully after second range , or contains second range
   the options of second range containing first, or first containing second only partually are not checked, since they are not posiible
   Return: -1 if fully before
           0 if contains 
           1 if fully after
*/
static int dx_check_range_and_update(unsigned long firstRange,
                                     unsigned long firstRangeSize,
                                     unsigned long secondRange,
                                     unsigned long secondRangeSize);
                                     
/*
  this function reads the RSA public key - exponent, exponent size in bits, modulus and modulus size in bits, and then stores it into the elf file
*/
static int dx_read_and_store_rsa_key(FILE*      inputFile,
                                     int        fd,
                                     dx_pk_st*  rsaPKData_ptr,
                                     int*       totalStoredSize_ptr);
                                     
/*
  this function reads the RSA private key key - private exponent, private exponent size in bytes, modulus and modulus size in bits, public exponent, public exponent size in bytes, and then stores 
  the public part (public exponent, size, modulus, size) into the elf file
*/
static int dx_read_and_store_rsa_sign_key(FILE*           inputFile,
                                          int             fd,
                                          int*            totalStoredSize_ptr);
                                     
/*
  this function sign the new elf file, using thhe the SHA1 hash function and PSS
*/
static int dx_sign_data();


/*
  reads empty or comment lines from the input data file
*/
static int dx_read_empty_lines_title(FILE* file);


/*---------------------------
    FUNCTIONS
----------------------------*/

int main (int argc, char** argv)
{
  
  /*------------------
      CODE
  -------------------*/
  
  /* add sign section of appropriate length to the ELF file */
  if(dx_add_elf_sign_section(argv[1]) < 0)
  {
    return -1;
  }
  
  /* insert the sign section data - RSA public key, Caller ID String , etc */ 
  if(dx_insert_sign_data(argv[2]) < 0)
  {
    return -1;
  }
  
  /* sign the elf file */
  if(dx_sign_data() < 0)
  {
    return -1;
  }
  
  return 0;
}


/*
   This function insertes a sign section into the ELF file and updates the appropriate
   Input - mapped buffer of ELF file, the size of the file, file descriptor to the new elf file. Output - the offset of the sign section in the new elf file 
*/
static int dx_add_elf_sign_section(char* elfFileName)
{
  /* elf header */
  elf_hdr_st*     elfHdr_ptr;
  
  /* new elf header */
  elf_hdr_st*     newElfHdr_ptr;
  
  /* pointer to section table */
  elf32_shdr_st*  elfSctTbl_ptr;
  
  /* pointer to new section table */
  elf32_shdr_st*  newElfSctTbl_ptr;
  
  /* pointer to the entry of the names section */
  elf32_shdr_st*  elfNamesSctTblEnt_ptr;
  
  /* pointer to program header */
  elf32_phdr_st*  elfPrgTbl_ptr;
  
  /* pointer to new program header */
  elf32_phdr_st*  newElfPrgTbl_ptr;
  
  /* new names section pointer (with name for our signature section */
  char*           newNamesSection_ptr;
  
  /* new size of the names section */
  long            newNamesSectionSize;
  
  /* data on the file */
  struct stat     statData;
  
  /* pointer to the mapped elf file */
  char*           elfFile;
  
  /* elf file descriptor */
  int             fd;
  
  /* new elf file */
  int             newElfFD;
  
  /* return value */
  int             retVal;
  
  /* counter */
  int             i;
  
  /*----------------------------
      CODE
  -------------------------------*/
  
  /* input file */
  fd = open (elfFileName, O_RDONLY);

  if(fd < 0)
  {
    fprintf(stderr , "Could not open input ELF file\n");
    return -1;
  }
  
  if(fstat(fd , &statData) < 0)
  {
    fprintf(stderr , "fstat for input ELF file failed\n");
    return -1;
  }
  
  /* map the file */
  elfFile = mmap (NULL , statData.st_size , PROT_READ , MAP_FILE | MAP_PRIVATE , fd , 0);
  
  /* open the file that will be used for sign */
  newElfFD = open("dx_sign_elf_file" , O_CREAT | O_RDWR);
  if(newElfFD < 0)
  {
    fprintf(stderr , "Could not create file dx_sign_elf_file\n");
    return -1;
  }
  
  /* get the elf header */
  elfHdr_ptr = (elf_hdr_st*)elfFile;
  
  /* check the validity of the header */
  if(elfHdr_ptr->e_ehsize != sizeof(elf_hdr_st))
  {
    fprintf(stderr , "the input file is not in ELF format\n");
    return -1;
  }
  
  /* get elf sections table */
  elfSctTbl_ptr =  (elf32_shdr_st*)(elfFile + elfHdr_ptr->e_shoff);
  
  elfPrgTbl_ptr = 0;
  if(elfHdr_ptr->e_phoff)
  {
    /*if programs header exists - point to it  */
    elfPrgTbl_ptr =  (elf32_phdr_st*)(elfFile + elfHdr_ptr->e_phoff);
  }
  
  /* point to the entry of the names section in section table */ 
  elfNamesSctTblEnt_ptr = &elfSctTbl_ptr[elfHdr_ptr->e_shtrndx];
  
  /* allocate new names section */
  newNamesSection_ptr = (char*)malloc(elfNamesSctTblEnt_ptr->sh_size + sizeof(dx_sign_section_name));
  if(newNamesSection_ptr == NULL)
  {
    fprintf(stderr , "No names section in input ELF file\n");
    return -1;
  }
  
  /* copy the previous names section into the new one */
  memcpy(newNamesSection_ptr , (void*)(elfFile + elfNamesSctTblEnt_ptr->sh_offset) , elfNamesSctTblEnt_ptr->sh_size);
  
  /* copy our section name */
  memcpy(newNamesSection_ptr + elfNamesSctTblEnt_ptr->sh_size , dx_sign_section_name , sizeof(dx_sign_section_name));
  
  /* set new names section size, and round it to modulo 4 */
  newNamesSectionSize = (elfNamesSctTblEnt_ptr->sh_size + sizeof(dx_sign_section_name) + 3) & 0xfffffffC;
  
  /* allocate new elf header */
  newElfHdr_ptr = malloc(sizeof(elf_hdr_st));
  if(newElfHdr_ptr == 0)
  {
    fprintf(stderr , "Malloc failed\n");
    return -1;
  }
  
  /* copy the old header into the new one */
  memcpy(newElfHdr_ptr , elfHdr_ptr , sizeof(elf_hdr_st));
  
  /* the number of entries in section table must be updated to include sign section */
  newElfHdr_ptr->e_shnum += 1;
  
  
  /* allocate new section table - the same size of entries + 1 (signature section entry) */
  newElfSctTbl_ptr = malloc(elfHdr_ptr->e_shentsize * (elfHdr_ptr->e_shnum + 1));
  if(newElfSctTbl_ptr == NULL)
  {
    fprintf(stderr , "Malloc failed\n");
    return -1;
  }
  
  /* copy the old section table into the new */
  memcpy(newElfSctTbl_ptr , elfSctTbl_ptr , (elfHdr_ptr->e_shentsize * elfHdr_ptr->e_shnum));
  
  /* update the size of the names string section */
  newElfSctTbl_ptr[elfHdr_ptr->e_shtrndx].sh_size = newNamesSectionSize;
  
  /* allocate new program table, if needed */
  newElfPrgTbl_ptr = 0;
  if(elfHdr_ptr->e_phoff)
  {
    newElfPrgTbl_ptr = malloc(elfHdr_ptr->e_phentsize * (elfHdr_ptr->e_phnum + 1));
    if(newElfPrgTbl_ptr == NULL)
    {
      fprintf(stderr , "Malloc failed\n");
      return -1;
    }
    
    /* copy the old program table into the new */
    memcpy(newElfPrgTbl_ptr , elfPrgTbl_ptr , (elfHdr_ptr->e_phentsize * elfHdr_ptr->e_phnum));
  }
 
  /* the changes entries are
     header - needs to hold the new number of entries in the section table + 
                                new offset of program table(maybe) + 
                                new offset of the section table (maybe)
     program header - its location may be moved due to the enlargement of the section table and the enlargement of the names string section
     each program header entry - " " "
     section header - it has one more entry and the size of the string section name has changed and its location must be updated if the names string section is located before it
     names string section - its large and its location maybe updated if is was located after section table
     sign section - its new, and at the end of the file, so it may be place at the end of the new file
  */
  
  
  /* find the if the program headers location must be changed */
  if(elfHdr_ptr->e_phoff > elfHdr_ptr->e_shoff)
  {
    /* section header before program header - location is updated according to the section table entry size */
    newElfHdr_ptr->e_phoff += elfHdr_ptr->e_shentsize;
  }
  
  if(elfHdr_ptr->e_phoff > elfNamesSctTblEnt_ptr->sh_offset)
  {
    /* if the names string section if before program header - location is updated accroging to the difference between the new and old section sizes */
    newElfHdr_ptr->e_phoff += newNamesSectionSize - elfNamesSctTblEnt_ptr->sh_size;
  }
  
  /* find if the section header location must be changed */
  if(elfHdr_ptr->e_shoff > elfNamesSctTblEnt_ptr->sh_offset)
  {
    /* if the names string section if before section header - location is updated accroging to the difference between the new and old section sizes */
    newElfHdr_ptr->e_shoff += newNamesSectionSize - elfNamesSctTblEnt_ptr->sh_size;
  }
  
  /* do the same check for every program segment in the program header */
  for(i = 0; i < elfHdr_ptr->e_phnum; i++)
  {
    /* check the segment relative to section header */
    retVal = dx_check_range_and_update(elfPrgTbl_ptr[i].p_offset , 
                                       elfPrgTbl_ptr[i].p_filesz,
                                       elfHdr_ptr->e_shoff,
                                       elfHdr_ptr->e_shnum * elfHdr_ptr->e_shentsize);
    if(retVal == 1)
    {
      /* if it was before section header - update offset */
      newElfPrgTbl_ptr[i].p_offset += elfHdr_ptr->e_shentsize;
    }
    
    if(retVal == 0)
    {
      /* if it contained section header - update size */
      newElfPrgTbl_ptr[i].p_filesz += elfHdr_ptr->e_shentsize;
    }
    
    /* check the segment relative to names section */
    retVal = dx_check_range_and_update(elfPrgTbl_ptr[i].p_offset , 
                                       elfPrgTbl_ptr[i].p_filesz,
                                       elfNamesSctTblEnt_ptr->sh_offset,
                                       elfNamesSctTblEnt_ptr->sh_size);
    if(retVal == 1)
    {
      /* if it was before section header - update offset */
      newElfPrgTbl_ptr[i].p_offset += newNamesSectionSize - elfNamesSctTblEnt_ptr->sh_size;
    }
    
    if(retVal == 0)
    {
      /* if it contained section header - update size */
      newElfPrgTbl_ptr[i].p_filesz += newNamesSectionSize - elfNamesSctTblEnt_ptr->sh_size;
    }
  }
  
  /* do the same for every section in the section header (including names string section) */
  for(i = 0; i < elfHdr_ptr->e_shnum; i++)
  {
    if(elfSctTbl_ptr[i].sh_offset > elfHdr_ptr->e_shoff)
    {
      /* section header before program segment - location is updated according to the section table entry size */
      newElfSctTbl_ptr[i].sh_offset += elfHdr_ptr->e_shentsize;
    }
    
    if(elfSctTbl_ptr[i].sh_offset > elfNamesSctTblEnt_ptr->sh_offset)
    {
      /* if the names string section if before program segment - location is updated accroging to the difference between the new and old section sizes */
      newElfSctTbl_ptr[i].sh_offset += newNamesSectionSize - elfNamesSctTblEnt_ptr->sh_size;
    }
  }
  
  /* set the data about signature section in the new section header */
  memset(&newElfSctTbl_ptr[elfHdr_ptr->e_shnum] , 0 , sizeof(elfHdr_ptr->e_shentsize));
  
  /* the index into the names string section is aftre the last bytes of the old names string section */
  newElfSctTbl_ptr[elfHdr_ptr->e_shnum].sh_name = elfNamesSctTblEnt_ptr->sh_size;
  
  /* set the type */
  newElfSctTbl_ptr[elfHdr_ptr->e_shnum].sh_type = DX_SIGN_SECTION_TYPE;
  
  /* the section will be residing at the end of the new file */
  newElfSctTbl_ptr[elfHdr_ptr->e_shnum].sh_offset = statData.st_size + elfHdr_ptr->e_shentsize + (newNamesSectionSize - elfNamesSctTblEnt_ptr->sh_size);
  
  /* the size will be set after all the data is filled */
  newElfSctTbl_ptr[elfHdr_ptr->e_shnum].sh_size = 0;
  
  /*---------------------
      writing into new file
  -------------------------*/
  
  /* first write the elf header */
  retVal = write(newElfFD , newElfHdr_ptr , sizeof(elf_hdr_st));
  if(retVal != sizeof(elf_hdr_st))
  {
    fprintf(stderr , "Write failed\n");
    return -1;
  }
  
  /* write program header, if needed */
  if(newElfHdr_ptr->e_phoff != 0)
  {
    lseek(newElfFD , newElfHdr_ptr->e_phoff , SEEK_SET);
    retVal = write(newElfFD , newElfPrgTbl_ptr , newElfHdr_ptr->e_phentsize * newElfHdr_ptr->e_phnum);
    if(retVal != (newElfHdr_ptr->e_phentsize * newElfHdr_ptr->e_phnum))
    {
      fprintf(stderr , "Write failed\n");
      return -1;
    }
  }
  
  /* write section header */
  lseek(newElfFD , newElfHdr_ptr->e_shoff , SEEK_SET);
  retVal = write(newElfFD , newElfSctTbl_ptr , newElfHdr_ptr->e_shentsize * newElfHdr_ptr->e_shnum);
  if(retVal != (newElfHdr_ptr->e_shentsize * newElfHdr_ptr->e_shnum))
  {
    fprintf(stderr , "Write failed\n");
    return -1;
  }
  
  /* write the rest of the section, except the DX sign section, which should be the last */
  for(i = 0; i < newElfHdr_ptr->e_shnum - 1; i++)
  {
    lseek(newElfFD , newElfSctTbl_ptr[i].sh_offset , SEEK_SET);
    if(i == newElfHdr_ptr->e_shtrndx)
    {
      retVal = write(newElfFD , newNamesSection_ptr , newElfSctTbl_ptr[i].sh_size);
    }
    else
    {
      retVal = write(newElfFD , elfFile + elfSctTbl_ptr[i].sh_offset , newElfSctTbl_ptr[i].sh_size);
    }
    if(retVal != newElfSctTbl_ptr[i].sh_size)
    {
      return -1;
    }
  }
  
  /* close and unmap old elf file */
  munmap(elfFile , statData.st_size);
  
  /* close the original elf file */
  close(fd);
  
  /* close the signed elf file */
  close(newElfFD);
  
  return 0;
}


/* 
  this function inserts data from the data file into the sign section of the elf file
  
*/
static int dx_insert_sign_data(char* dataFilename_ptr)
{
  /* file pointer */
  FILE*     file;
  
  /* public key struct */
  dx_pk_st  rsaPKData;
  
  /* the size of the data line */
  int       dataLineSize;   
  
  /* pointer to data line */
  char*     buffer_ptr;
  
  char*     dataLine_ptr;
  
  /* number of read bytes */ 
  int       numBytesRead;
  
  /* size caller id string */
  int       callerIdSize;
  
  /* number of DDL keys */
  int       numDDLKeys;

  /* file descriptor for new elf sign file */
  int       fd;
  
  /* length of the signed section */
  int       signSctLen;
    
  /* return value */
  int       retVal;
  
  /* counter */
  int       i;
  
  /* error */
  int       error = 0;
  
  /*----------------------
    CODE
  ------------------------*/
  
  signSctLen = 0;
  
  /* open the newly created sign file */
  fd = open("dx_sign_elf_file" , O_RDWR);
  if(fd < 0)
  {
    fprintf(stderr , "Failed to open dx_sign_elf_file\n");
    error = -1;
    goto end_function;
  }
  
  /* sign section input file */
  file = fopen(dataFilename_ptr , "r");
  if(file == NULL)
  {
    fprintf(stderr , "Failed to find DX sign section in the ELF file\n");
    error = -1;
    goto end_function;
  }
  
  dataLineSize = DX_MAX_PK_MODULUS_SIZE_IN_BYTES;
  
  /* allocate buffer for reading lines */
  buffer_ptr = malloc(dataLineSize);
  if(buffer_ptr == NULL)
  {
    fprintf(stderr , "Malloc failed\n");
    error = -1;
    goto end_function;
  }
  
  dataLine_ptr = buffer_ptr;
  
  /* go to the end of the file - start of the sign section in the elf file */
  lseek(fd , 0 , SEEK_END);
  
  /* format of the input file should be as following 
  <RSA private exponent size>
  <RSA private exponent>
  <RSA modulus size>
  <RSA modulus>
  <RSA public exponent size>
  <RSA public exponent>
  if this is an application signing , then
  <CallerId string>
  <Num of posiible RSA keys for DLL>
  < Fist posible key data>
        ...
        ...
        ...
  < Last possible key data>
  */
  retVal = dx_read_and_store_rsa_sign_key(file,
                                          fd,
                                          &signSctLen);
  if(retVal < 0)
  {
    error = -1;
    goto end_function;
  }

  /*read the caller id size in bytes */
  if( fscanf(file, "%d" , &callerIdSize) == EOF )
  { 
    /* this means that thus is input file for DLL */
    goto end_function_insert_sign;
  }
  
  /* store the caller id size into the file */
  write(fd , &callerIdSize , sizeof(int));
  
  signSctLen += sizeof(int);
  
  dx_read_empty_lines_title(file);

  /* read caller id string */
  numBytesRead = getline(&dataLine_ptr , &dataLineSize , file);
  
  /* if this is APP input data - check the size of the caller id string */
  if(numBytesRead < 0 || numBytesRead > DX_DM_CALLER_ID_STRING_LEN_IN_BYTES)
  {
    fprintf(stderr , "getline failed\n");
    error = -1;
    goto end_function_free;
  }
  
  /* store the caller id in elf file */
  write(fd , dataLine_ptr , DX_DM_CALLER_ID_STRING_LEN_IN_BYTES);
  
  signSctLen += DX_DM_CALLER_ID_STRING_LEN_IN_BYTES;
  
  dx_read_empty_lines_title(file);
  
  /* read the number of possible DLL keys */
  if(fscanf(file, "%d" , &numDDLKeys) == EOF)
  {
    fprintf(stderr , "Incorrect input data format - number of DLL keys missing\n");
    error = -1;
    goto end_function_free;
  }
  
  /* store the number of possible DDL keys in the file */
  write(fd , &numDDLKeys , sizeof(int));
  
  signSctLen += sizeof(int);
  
  /* read the posiible key and store them in the sign section */
  for(i = 0; i < numDDLKeys; i++)
  {
    retVal = dx_read_and_store_rsa_key(file,
                                       fd,
                                       &rsaPKData,
                                       &signSctLen );
    if(retVal < 0)
    {
      error = -1;
      goto end_function;
    }
  }
 
end_function_insert_sign:

  write(fd , sign_init , DX_DM_SIGN_LEN_IN_BYTES);
  
  /* close the sign file */
  close(fd);
  
  /* close input data */
  fclose(file);
  
  signSctLen += DX_DM_SIGN_LEN_IN_BYTES;
  
  dx_update_section_table(signSctLen);
  
  goto end_function;

end_function_free:

  free(dataLine_ptr);
  
end_function:

  return error;
  
}

/*
  updates the section table entry of the sign section with the length
*/
static int dx_update_section_table(int len)
{
  /* file descriptor */
  int             fd;
  
  /* elf header */
  elf_hdr_st*     elfHdr_ptr;
  
  /* pointer to section table */
  elf32_shdr_st*  elfSctTbl_ptr;
  
  /* data on the file */
  struct stat     statData;
  
  /* mapped file */
  char*           elfFile;
  
  /*--------------------------------------
      CODE
  ------------------------------------------*/
  
  /* reopen new elf in order to update the section table */
  fd = open("dx_sign_elf_file" , O_RDWR);
  if(fd < 0)
  {
    fprintf(stderr , "Failed to open dx_sign_elf_file\n");
    return -1;
  }
  
  if(fstat(fd , &statData) < 0)
  {
    fprintf(stderr , "fstat for dx_sign_elf_file failed\n");
    return -1;
  }
  
  elfFile = mmap(NULL , statData.st_size , PROT_READ | PROT_WRITE , MAP_FILE | MAP_SHARED , fd , 0);
  
  /* get the elf header */
  elfHdr_ptr = (elf_hdr_st*)elfFile;
  
  /* get elf sections table */
  elfSctTbl_ptr =  (elf32_shdr_st*)(elfFile + elfHdr_ptr->e_shoff);
  
  elfSctTbl_ptr[elfHdr_ptr->e_shnum - 1].sh_size = len;
  
  /* unmap and close the file */
  munmap(elfFile , len);
  
  close(fd);
  
  return 0;
}

/* check if the first range is fully before second range, fully after second range , or contains second range
   the options of second range containing first, or first containing second only partually are not checked, since they are not posiible
   Return: -1 if fully before
           0 if contains 
           1 if fully after
*/
static int dx_check_range_and_update(unsigned long firstRange,
                                     unsigned long firstRangeSize,
                                     unsigned long secondRange,
                                     unsigned long secondRangeSize)
{
  if( (firstRange + firstRangeSize) < secondRange)
  {
    return -1;
  }
  
  if( (secondRange + secondRangeSize) < firstRange )
  {
    return 1;
  }
  
  return 0;
  
}


/*
  this function reads the RSA public key - exponent, exponent size in bits, modulus and modulus size in bits, and then stores it into the elf file
*/
static int dx_read_and_store_rsa_key(FILE*      inputFile,
                                     int        fd,
                                     dx_pk_st*  rsaPKData_ptr,
                                     int*       totalStoredSize_ptr)
{
  /* temp num */
  unsigned long   tempNum = 0;
  
  /* index */
  int             index = 0;
  
  /* separator */
  int             separator = ',';
  
  /* num of bytes read */
  int             numWriteBytes;
  
  /* key size */
  unsigned long   keySize;
  
  /* temporary buffer */
  char            tempBuff[100];


  /*--------------------------
    CODE
  -----------------------------*/
  
  /* skip comments or empty lines */
  if(dx_read_empty_lines_title(inputFile) < 0)
  {
    fprintf(stderr , "Incorrect input data format - empty lines\n");
    return -1;
  }
  
  
  /* read key size in bits */
  if( fscanf(inputFile, "%d" , &keySize) == EOF )
  { 
    fprintf(stderr , "Incorrect input data format - size of key is missing\n");
    /* size in bits */
    return -1;
  }
  
  rsaPKData_ptr->modulusSize = keySize / 8;
  
  /* skip comments or empty lines */
  if(dx_read_empty_lines_title(inputFile) < 0)
  {
    fprintf(stderr , "Incorrect input data format - empty lines\n");
    return -1;
  }
  
  /* read public exponent E */
  index = 0;
  while( separator == ',' )
  {	
    if ( fscanf(inputFile, "%x", &tempNum) == EOF )
    {
      fprintf(stderr , "Incorrect input data format\n");
      return -1;
    }
          
    rsaPKData_ptr->exponent[index] = (unsigned char)tempNum;
    index++;
    separator = fgetc(inputFile);	    					
    if ( separator == EOF ) 
    {
      fprintf(stderr , "Incorrect input data format - incomplete E\n");
      return -1;   
    }
  }
  
  rsaPKData_ptr->exponentSize = index;
  
  /* skip comments or empty lines */
  if(dx_read_empty_lines_title(inputFile) < 0)
  {
    fprintf(stderr , "Incorrect input data format - empty lines\n");
    return -1;
  }
  
  /* read modulus N */
  for(index = 0 ; index < rsaPKData_ptr->modulusSize ; index++ )
  {
    if ( fscanf(inputFile, "%x", &tempNum) == EOF )
    {
      fprintf(stderr , "Incorrect input data format\n");
      return -1;
    }
            
    rsaPKData_ptr->modulus[index] = (unsigned char)tempNum;
    
    separator = fgetc(inputFile);	    					
    if ( separator == EOF ) 
    {
      fprintf(stderr , "Incorrect input data format - incomplete N\n");
      return -1;
    }
  }
  
  /* check if we read the correct number of bytes for modulus */
  if( rsaPKData_ptr->modulusSize > index)
  {
    fprintf(stderr , "Incorrect input data format - incomplete size of modulus\n");
    return -1;
  }
  
  /* skip comments or empty lines */
  if(dx_read_empty_lines_title(inputFile) < 0)
  {
    fprintf(stderr , "Incorrect input data format - empty lines\n");
    return -1;
  }

  /* store the modulus size */
  numWriteBytes = write(fd , &rsaPKData_ptr->modulusSize , sizeof(int));
  if(numWriteBytes != sizeof(int))
  {
    fprintf(stderr , "Write failed\n");
    return -1;
  }
  
  /* store the exponent size in elf file */
  numWriteBytes = write(fd , &rsaPKData_ptr->exponentSize , sizeof(int));
  if(numWriteBytes != sizeof(int))
  {
    fprintf(stderr , "Write failed\n");
    return -1;
  }
  
  /* store the modulus  in elf file(maximum size) */
  numWriteBytes = write(fd , rsaPKData_ptr->modulus , DX_MAX_PK_MODULUS_SIZE_IN_BYTES);
  if(numWriteBytes != DX_MAX_PK_MODULUS_SIZE_IN_BYTES)
  {
    fprintf(stderr , "Write failed\n");
    return -1;
  }
  
  /* store the exponent */
  numWriteBytes = write(fd , rsaPKData_ptr->exponent , DX_MAX_PK_EXPONENT_SIZE_IN_BYTES);
  if(numWriteBytes != DX_MAX_PK_EXPONENT_SIZE_IN_BYTES)
  {
    fprintf(stderr , "Write failed\n");
    return -1;
  }
  
  *totalStoredSize_ptr += (sizeof(int) * 2) + DX_MAX_PK_MODULUS_SIZE_IN_BYTES + DX_MAX_PK_EXPONENT_SIZE_IN_BYTES;

  return 0;

}

/*
  this function reads the RSA private key key - private exponent, private exponent size in bytes, modulus and modulus size in bits, public exponent, public exponent size in bytes, and then stores 
  the public part (public exponent, size, modulus, size) into the elf file
*/
static int dx_read_and_store_rsa_sign_key(FILE*           inputFile,
                                          int             fd,
                                          int*            totalStoredSize_ptr)
{
  /* key size */
  unsigned long keySize;
  
  /* rsa public key struct */
  dx_pk_st      rsaKey;
  
  /* temporary buffer */
  char          tempBuff[100];
  
  /* temp num */
  unsigned long tempNum = 0;
  
  /* index */
  int           index = 0;
  
  /* separator */
  int           separator = ',';
  
  
  /*---------------------------------
      CODE
  --------------------------------------*/
  
  /* read the public key */
  if(dx_read_and_store_rsa_key(inputFile , fd , &rsaKey , totalStoredSize_ptr) < 0)
  {
    return -1;
  }
  
  /* store the public key in global variables */
  memcpy(g_PubExponent , rsaKey.exponent , rsaKey.exponentSize);
  
  memcpy(g_Modulus , rsaKey.modulus , rsaKey.modulusSize);
  
  g_ModulusSize = rsaKey.modulusSize;
  
  g_ExponentSize = rsaKey.exponentSize;
  
  /* read the private exponent */
  for(index = 0 ; index < rsaKey.modulusSize ; index++ )
  {
    if ( fscanf(inputFile, "%x", &tempNum) == EOF )
    {
      return -1;
    }
            
    g_PrivExponent[index] = (unsigned char)tempNum;
    
    separator = fgetc(inputFile);	    					
    if ( separator == EOF ) 
    {
      fprintf(stderr , "Incorrect input data format - incomplete D\n");
      return -1;
    }
  }
  
  /* check if we read the correct number of bytes for modulus */
  if( rsaKey.modulusSize > index)
  {
    fprintf(stderr , "Incorrect input data format - D size incomplete\n");
    return -1;
  }

  /* skip comments or empty lines */
  if(dx_read_empty_lines_title(inputFile) < 0)
  {
    fprintf(stderr , "Incorrect input data format - empty lines\n");
    return -1;
  }
  
  return 0;
}





/*
  this function sign the new elf file, using thhe the SHA1 hash function and PSS
*/
static int dx_sign_data()
{
  /* file descriptor */
  int                   fd;
  
  /* data on the file */
  struct stat           statData;
  
  /* mapped file */
  char*                 elfFile;
  
  /* pointer into the mapped elf file where signature shoudl ber inserted */
  char*                 sign_ptr;
  
  /* signature */
  unsigned char         signature[DX_MAX_PK_MODULUS_SIZE_IN_BYTES];
  
  /* elf header */
  elf_hdr_st*           elfHdr_ptr;
  
  /* signature size */
  unsigned short        signSize;
  
  /* private key for signing */
  CE2_RSAUserPrivKey_t  privKey;
  
  /* error */
  CE2Error_t            error;
  
  
  /*-------------------
      CODE
  --------------------*/
  
  /* open elf file */
  fd = open ("dx_sign_elf_file", O_RDWR);

  if(fd < 0)
  {
    fprintf(stderr , "Failed to open dx_sign_elf_file for signing\n");
    return -1;
  }
  
  if(fstat(fd , &statData) < 0)
  {
    fprintf(stderr , "fstat for dx_sign_elf_file failed\n");
    return -1;
  }
  
  /* map the file */
  elfFile = mmap (NULL , statData.st_size , PROT_READ|PROT_WRITE , MAP_FILE | MAP_SHARED , fd , 0);
  if(elfFile == (void*)-1)
  {
    fprintf(stderr , "mmap on opened dx_sign_elf_file failed\n");
    return -1;
  }
  
  /* build private key */
  error = CE2_RSA_Build_PrivKey(&privKey , 
                                g_PrivExponent, 
                                g_ModulusSize,
                                g_PubExponent,
                                g_ExponentSize,
                                g_Modulus,
                                g_ModulusSize );
  if(error != CE2_OK)
  {
    fprintf(stderr , "CE2_RSA_Build_PrivKey failed\n");
    return -1;
  }
  
  /* sign the file */
  error = CE2_RSA_PSS_Sign(&privKey , 
                           CE2_RSA_HASH_SHA1_mode , 
                           CE2_PKCS1_MGF1 , 
                           20 , 
                           elfFile , 
                           statData.st_size - DX_DM_SIGN_LEN_IN_BYTES,
                           signature,
                           &signSize);
  if(error != CE2_OK)
  {
    fprintf(stderr , "CE2_RSA_PSS_Sign failed\n");
    return -1;
  }
  
  /* signature is the last data of the file */
  sign_ptr = elfFile + (statData.st_size - DX_DM_SIGN_LEN_IN_BYTES );
  
  memcpy(sign_ptr , signature , signSize);
  
  munmap(elfFile , statData.st_size);
  
  close(fd);
  
  return 0;
}

/*
  
*/
static int dx_read_empty_lines_title(FILE* file)
{
  /* buffer */
  char* buff_ptr;
  
  /* check char */
  char  checkChar;

  int   size;
  
  /* error */
  int   error = 0;
  
  /*----------------------
      CODE
  -------------------------*/
  
  buff_ptr = NULL;
  while(1)
  {
    checkChar = fgetc(file);
    if(!isspace(checkChar) && checkChar != '/')
    {
      /* part of the input */
      ungetc(checkChar , file);
      break;
    }
    if(getline(&buff_ptr, &size , file) < 0)
    {
      error = -1;
      goto end_function;
    }
    
    free(buff_ptr);
    buff_ptr = NULL;
  }
  
end_function:

  free(buff_ptr);
  
  return error;
}

