/*
  gen-keys: This program should be run on the DSS once for every course to create the DSS private and public keys.
  source: http://www.ter.se/dss
*/

#include <stdio.h>
#include <gnunet/platform.h>
#include <gnunet/gnunet_util_lib.h>
#include "common.c"

/**
 * Declaration of functions
 */
int  checkParams (int nrParams, char* params[], unsigned int* sizeKey);
void showHelp ();

/**
 * Main
 */
int main (int nrParams, char* params[])
{
  // Check parameters to the program.
  unsigned int sizeKey = DEFAULT_KEY_SIZE;
  if (checkParams (nrParams, params, &sizeKey))
  {
    return (1);
  }

  /**
   * Pass
   */

  // Read the DSS RSA private pass key from file.
  struct GNUNET_CRYPTO_rsa_PrivateKey *privatePassKeyDSS;
  if (readPrivateKeyFromFile (DSS_PRIVATE_PASS_KEY, &privatePassKeyDSS))
  {
    // Unable to open the DSS RSA private pass key file so we generate it instead.
    printf ("Generate the DSS RSA private pass key using a key size of %u bits.\n", sizeKey);
    privatePassKeyDSS = GNUNET_CRYPTO_rsa_private_key_create (sizeKey);
  }

  // Extract the DSS RSA public pass key out of the DSS RSA private pass key.
  struct GNUNET_CRYPTO_rsa_PublicKey *publicPassKeyDSS;
  printf ("Extract the DSS RSA public pass key out of the DSS RSA private pass key.\n");
  publicPassKeyDSS = GNUNET_CRYPTO_rsa_private_key_get_public (privatePassKeyDSS);

  // Write the DSS RSA private pass key to file.
  if (writePrivateKeyToFile (DSS_PRIVATE_PASS_KEY, &privatePassKeyDSS))
  {
    return (1);
  } 
  GNUNET_CRYPTO_rsa_private_key_free (privatePassKeyDSS); // Free the DSS RSA private pass key

  // Write the DSS RSA public pass key to file.
  if (writePublicKeyToFile (DSS_PUBLIC_PASS_KEY, &publicPassKeyDSS))
  {
    return (1);
  } 
  GNUNET_CRYPTO_rsa_public_key_free (publicPassKeyDSS); // Free the DSS RSA public pass key

  /**
   * Fail
   */

  // Read the DSS RSA private fail key from file.
  struct GNUNET_CRYPTO_rsa_PrivateKey *privateFailKeyDSS;
  if (readPrivateKeyFromFile (DSS_PRIVATE_FAIL_KEY, &privateFailKeyDSS))
  {
    // Unable to open the DSS RSA private fail key file so we generate it instead.
    printf ("Generate the DSS RSA private fail key using a key size of %u bits.\n", sizeKey);
    privateFailKeyDSS = GNUNET_CRYPTO_rsa_private_key_create (sizeKey);
  }

  // Extract the DSS RSA public fail key out of the DSS RSA private fail key.
  struct GNUNET_CRYPTO_rsa_PublicKey *publicFailKeyDSS;
  printf ("Extract the DSS RSA public fail key out of the DSS RSA private fail key.\n");
  publicFailKeyDSS = GNUNET_CRYPTO_rsa_private_key_get_public (privateFailKeyDSS);

  // Write the DSS RSA private fail key to file.
  if (writePrivateKeyToFile (DSS_PRIVATE_FAIL_KEY, &privateFailKeyDSS))
  {
    return (1);
  } 
  GNUNET_CRYPTO_rsa_private_key_free (privateFailKeyDSS); // Free the DSS RSA private fail key

  // Write the DSS RSA public fail key to file.
  if (writePublicKeyToFile (DSS_PUBLIC_FAIL_KEY, &publicFailKeyDSS))
  {
    return (1);
  } 
  GNUNET_CRYPTO_rsa_public_key_free (publicFailKeyDSS); // Free the DSS RSA public fail key

  return (0);
}

/**
 * Check parameters to the program.
 */
int checkParams (int nrParams, char* params[], unsigned int* sizeKey)
{
  int i;

  for (i = 1 ; i < nrParams; i++)
  {
    if (strcmp (params[i], "-h") == 0 || strcmp (params[i], "--help") == 0)
    {
      showHelp ();
      return (1);
    }

    if (strcmp (params[i], "-v") == 0 || strcmp (params[i], "--version") == 0)
    {
      printf (VERSION"\n");
      return (1);
    }

    if (strcmp (params[i], "-k") == 0)
    {
      i = i + 1;
      if (i == nrParams)
      {
        printf ("Option -k needs a parameter specifying key size in bits: 1024, 2048 or 4096.\n");
        return (1);
      }
      else
      if (strcmp (params[i], "1024") == 0)
      {
        *sizeKey = 1024;
      }
      else
      if (strcmp (params[i], "2048") == 0)
      {
        *sizeKey = 2048;
      }
      else
      if (strcmp (params[i], "4096") == 0)
      {
        *sizeKey = 4096;
      }
      else
      {
        printf ("Invalid parameter to option -k: %s\n", params[i]);
        printf ("Key size can only be 1024, 2048 or 4096 bits.\n");
        return (1);
      }
    }
    else
    if (i < (nrParams - 1))
    {
      printf ("Invalid option: %s\n", params[i]);
      printf ("Use \"-h\" for help.\n");
      return (1);
    }
  }

  return (0);
}

/**
 * Show help
 */
void showHelp ()
{
  printf ("Description:\n");
  printf ("  gen-keys: This program should be run on the DSS once for every course to create the DSS private and public keys.\n");
  printf ("Usage:\n");
  printf ("  gen-keys [-k key_size]\n");
  printf ("Options:\n");
  printf ("  -k = Key size used if new keys are created: 1024, 2048 or 4096\n");
  printf ("Output:\n");
  printf ("  The DSS two key pairs for the grades pass and fail.\n");
  printf ("Dependencies:\n");
  printf ("  This program relies on GNUnet and Libgcrypt.\n");
  printf ("License:\n");
  printf ("  GNU General Public License, version 3+.\n");
}

