Beispiel #1
0
int
tls_connection_load_cipher(struct SSLConnection *conn)
{
    if (conn->cipher_suite.cs1 != 0x00)
        return 1;

    if (conn->cipher_suite.cs2 == TLS_RSA_WITH_AES_256_CBC_SHA.cs2) {
        conn->ciph = gcry_cipher_map_name("AES256");
    } else if (conn->cipher_suite.cs2 == TLS_RSA_WITH_AES_128_CBC_SHA.cs2) {
        conn->ciph = gcry_cipher_map_name("AES");
    } else {
        return 1;
    }
    return 0;
}
Beispiel #2
0
int init_My_crypto(My_crypto* obj, const char alg[], int mode) {
	obj->_cipher = gcry_cipher_map_name(alg);
	//ret->_md = gcry_md_map_name("MD5");
	if (gcry_cipher_open(&(obj->_cipherhd), obj->_cipher, mode, 0) != GPG_ERR_NO_ERROR)
		return -1;
	return 0;
}
Beispiel #3
0
static crypto_t _cipher_new(crypto_t c, gchar *key,
                            const gchar *algoname,
                            const gint cipher_mode,
                            const guint cipher_flags)
{
  gcry_error_t e;

  c->algo = gcry_cipher_map_name(algoname);
  if (c->algo ==0)
    {
      return (_fail(c, g_strdup_printf("algorithm `%s' was not available",
                                       algoname)));
    }

  c->cipher.flags = cipher_flags;
  c->cipher.mode = cipher_mode;

  c->cipher.should_pad = (cipher_mode != GCRY_CIPHER_MODE_STREAM
                          && cipher_mode != GCRY_CIPHER_MODE_CFB
                          && cipher_mode != GCRY_CIPHER_MODE_OFB)
                         ? TRUE
                         : FALSE;

  c->cipher.blklen = gcry_cipher_get_algo_blklen(c->algo);
  if (c->cipher.blklen ==0)
    return (_fail(c, g_strdup("gcry_cipher_get_algo_blklen failed")));

  e = gcry_cipher_open(&c->cipher.h, c->algo, cipher_mode, cipher_flags);
  if (e != 0)
    {
      return (_fail(c, g_strdup_printf("gcry_cipher_open failed: %s",
                                       gpg_strerror(e))));
    }
  return (_setkey(c, key));
}
Beispiel #4
0
static void
check_ciphers (void)
{
  static int algos[] = {
    GCRY_CIPHER_3DES,
    GCRY_CIPHER_CAST5,
    GCRY_CIPHER_BLOWFISH,
    GCRY_CIPHER_AES,
    GCRY_CIPHER_AES192,
    GCRY_CIPHER_AES256,
    GCRY_CIPHER_TWOFISH,
    GCRY_CIPHER_TWOFISH128,
    GCRY_CIPHER_DES,
    GCRY_CIPHER_SERPENT128,
    GCRY_CIPHER_SERPENT192,
    GCRY_CIPHER_SERPENT256,
    0
  };
  static int algos2[] = {
    GCRY_CIPHER_ARCFOUR,
    0
  };
  int i;

  for (i = 0; algos[i]; i++)
    {
      if (verbose)
	fprintf (stderr, "checking `%s' [%i]\n",
		 gcry_cipher_algo_name (algos[i]),
		 gcry_cipher_map_name (gcry_cipher_algo_name (algos[i])));

      check_one_cipher (algos[i], GCRY_CIPHER_MODE_ECB, 0);
      check_one_cipher (algos[i], GCRY_CIPHER_MODE_CFB, 0);
      check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC, 0);
      check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_CTS);
      check_one_cipher (algos[i], GCRY_CIPHER_MODE_CTR, 0);
    }

  for (i = 0; algos2[i]; i++)
    {
      if (verbose)
	fprintf (stderr, "checking `%s'\n",
		 gcry_cipher_algo_name (algos2[i]));

      check_one_cipher (algos2[i], GCRY_CIPHER_MODE_STREAM, 0);
    }
  /* we have now run all cipher's selftests */

  /* TODO: add some extra encryption to test the higher level functions */
}
/** \brief init the gcry_md_hd
 * 
 * - this init is assumed to be done everytime it is done for ciph_type
 */
bool skey_ciph_t::init_gcry_hd()				throw()
{
	const skey_ciph_algo_t &algo	= ciph_type.get_algo();
	// get the algo from the algo_str
	int gcry_cipher_algo = gcry_cipher_map_name( algo.to_string().c_str() );
	// if the algo_str isnt supported, throw an exception
	if( !gcry_cipher_algo ){
		KLOG_ERR("Can't map " << algo.to_string() << " in gcrypt cipher_map_name");
		return true;
	}
	// open the gcrypt cipher
	if( gcry_cipher_open(&gcry_cipher_hd, gcry_cipher_algo, get_gcry_cipher_mode(), GCRY_CIPHER_SECURE) ){
		KLOG_ERR("Can't open " << ciph_type << " in gcrypt cipher_open");
		return true;
	}
	// return false if no error occured
	return false;
}
Beispiel #6
0
void
cipher_bench (char **argv, int argc)
{
  int i, algo;

  bench_print_section ("cipher", "Cipher");

  if (argv && argc)
    {
      for (i = 0; i < argc; i++)
        {
          algo = gcry_cipher_map_name (argv[i]);
          if (algo)
            _cipher_bench (algo);
        }
    }
  else
    {
      for (i = 1; i < 400; i++)
        if (!gcry_cipher_test_algo (i))
          _cipher_bench (i);
    }
}
Beispiel #7
0
/* Initialize the data encryption key (session key). */
static int
init_dek (DEK dek)
{
  int rc=0, mode, i;

  dek->algo = gcry_cipher_map_name (dek->algoid);
  mode = gcry_cipher_mode_from_oid (dek->algoid);
  if (!dek->algo || !mode)
    {
      log_error ("unsupported algorithm `%s'\n", dek->algoid);
      return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
    }
  
  /* Extra check for algorithms we consider to be too weak for
     encryption, although we support them for decryption.  Note that
     there is another check below discriminating on the key length. */
  switch (dek->algo)
    {
    case GCRY_CIPHER_DES:
    case GCRY_CIPHER_RFC2268_40:
      log_error ("cipher algorithm `%s' not allowed: too weak\n",
                 gcry_cipher_algo_name (dek->algo));
      return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
    default:
      break;
    }

  dek->keylen = gcry_cipher_get_algo_keylen (dek->algo);
  if (!dek->keylen || dek->keylen > sizeof (dek->key))
    return gpg_error (GPG_ERR_BUG);

  dek->ivlen = gcry_cipher_get_algo_blklen (dek->algo);
  if (!dek->ivlen || dek->ivlen > sizeof (dek->iv))
    return gpg_error (GPG_ERR_BUG);

  /* Make sure we don't use weak keys. */
  if (dek->keylen < 100/8)
    { 
      log_error ("key length of `%s' too small\n", dek->algoid);
      return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
    }
  
  rc = gcry_cipher_open (&dek->chd, dek->algo, mode, GCRY_CIPHER_SECURE);
  if (rc)
    {
      log_error ("failed to create cipher context: %s\n", gpg_strerror (rc));
      return rc;
    }
  
  for (i=0; i < 8; i++)
    {
      gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM );
      rc = gcry_cipher_setkey (dek->chd, dek->key, dek->keylen);
      if (gpg_err_code (rc) != GPG_ERR_WEAK_KEY)
        break;
      log_info(_("weak key created - retrying\n") );
    }
  if (rc)
    {
      log_error ("failed to set the key: %s\n", gpg_strerror (rc));
      gcry_cipher_close (dek->chd);
      dek->chd = NULL;
      return rc;
    }

  gcry_create_nonce (dek->iv, dek->ivlen);
  rc = gcry_cipher_setiv (dek->chd, dek->iv, dek->ivlen);
  if (rc)
    {
      log_error ("failed to set the IV: %s\n", gpg_strerror (rc));
      gcry_cipher_close (dek->chd);
      dek->chd = NULL;
      return rc;
    }
  
  return 0;
}
/** \brief return the gcrypt algo id
 */
int	skey_ciph_t::get_gcry_cipher_algo()			const throw()
{
	const skey_ciph_algo_t &algo		= ciph_type.get_algo();
	int 			gcry_cipher_algo= gcry_cipher_map_name( algo.to_string().c_str() );	
	return gcry_cipher_algo;
}
Beispiel #9
0
static void
cipher_bench ( const char *algoname )
{
  static int header_printed;
  int algo;
  gcry_cipher_hd_t hd;
  int i;
  int keylen, blklen;
  char key[128];
  char *outbuf, *buf;
  char *raw_outbuf, *raw_buf;
  size_t allocated_buflen, buflen;
  int repetitions;
  static struct { int mode; const char *name; int blocked; } modes[] = {
    { GCRY_CIPHER_MODE_ECB, "   ECB/Stream", 1 },
    { GCRY_CIPHER_MODE_CBC, "      CBC", 1 },
    { GCRY_CIPHER_MODE_CFB, "      CFB", 0 },
    { GCRY_CIPHER_MODE_OFB, "      OFB", 0 },
    { GCRY_CIPHER_MODE_CTR, "      CTR", 0 },
    { GCRY_CIPHER_MODE_STREAM, "", 0 },
    {0}
  };
  int modeidx;
  gcry_error_t err = GPG_ERR_NO_ERROR;


  if (!algoname)
    {
      for (i=1; i < 400; i++)
        if ( !gcry_cipher_test_algo (i) )
          cipher_bench (gcry_cipher_algo_name (i));
      return;
    }

  if (large_buffers)
    {
      allocated_buflen = 1024 * 100;
      repetitions = 10;
    }
  else
    {
      allocated_buflen = 1024;
      repetitions = 1000;
    }
  repetitions *= cipher_repetitions;

  raw_buf = gcry_xmalloc (allocated_buflen+15);
  buf = (raw_buf
         + ((16 - ((size_t)raw_buf & 0x0f)) % buffer_alignment));
  outbuf = raw_outbuf = gcry_xmalloc (allocated_buflen+15);
  outbuf = (raw_outbuf
            + ((16 - ((size_t)raw_outbuf & 0x0f)) % buffer_alignment));

  if (!header_printed)
    {
      if (cipher_repetitions != 1)
        printf ("Running each test %d times.\n", cipher_repetitions);
      printf ("%-12s", "");
      for (modeidx=0; modes[modeidx].mode; modeidx++)
        if (*modes[modeidx].name)
          printf (" %-15s", modes[modeidx].name );
      putchar ('\n');
      printf ("%-12s", "");
      for (modeidx=0; modes[modeidx].mode; modeidx++)
        if (*modes[modeidx].name)
          printf (" ---------------" );
      putchar ('\n');
      header_printed = 1;
    }

  algo = gcry_cipher_map_name (algoname);
  if (!algo)
    {
      fprintf (stderr, PGM ": invalid cipher algorithm `%s'\n", algoname);
      exit (1);
    }

  keylen = gcry_cipher_get_algo_keylen (algo);
  if (!keylen)
    {
      fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n",
	       algoname);
      exit (1);
    }
  if ( keylen > sizeof key )
    {
        fprintf (stderr, PGM ": algo %d, keylength problem (%d)\n",
                 algo, keylen );
        exit (1);
    }
  for (i=0; i < keylen; i++)
    key[i] = i + (clock () & 0xff);

  blklen = gcry_cipher_get_algo_blklen (algo);
  if (!blklen)
    {
      fprintf (stderr, PGM ": failed to get block length for algorithm `%s'\n",
	       algoname);
      exit (1);
    }

  printf ("%-12s", gcry_cipher_algo_name (algo));
  fflush (stdout);

  for (modeidx=0; modes[modeidx].mode; modeidx++)
    {
      if ((blklen > 1 && modes[modeidx].mode == GCRY_CIPHER_MODE_STREAM)
          | (blklen == 1 && modes[modeidx].mode != GCRY_CIPHER_MODE_STREAM))
        continue;

      for (i=0; i < sizeof buf; i++)
        buf[i] = i;

      err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0);
      if (err)
        {
          fprintf (stderr, PGM ": error opening cipher `%s'\n", algoname);
          exit (1);
        }

      if (!cipher_with_keysetup)
        {
          err = gcry_cipher_setkey (hd, key, keylen);
          if (err)
            {
              fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
                       gpg_strerror (err));
              gcry_cipher_close (hd);
              exit (1);
            }
        }

      buflen = allocated_buflen;
      if (modes[modeidx].blocked)
        buflen = (buflen / blklen) * blklen;

      start_timer ();
      for (i=err=0; !err && i < repetitions; i++)
        {
          if (cipher_with_keysetup)
            {
              err = gcry_cipher_setkey (hd, key, keylen);
              if (err)
                {
                  fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
                           gpg_strerror (err));
                  gcry_cipher_close (hd);
                  exit (1);
                }
            }
          err = gcry_cipher_encrypt ( hd, outbuf, buflen, buf, buflen);
        }
      stop_timer ();

      printf (" %s", elapsed_time ());
      fflush (stdout);
      gcry_cipher_close (hd);
      if (err)
        {
          fprintf (stderr, "gcry_cipher_encrypt failed: %s\n",
                   gpg_strerror (err) );
          exit (1);
        }

      err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0);
      if (err)
        {
          fprintf (stderr, PGM ": error opening cipher `%s'/n", algoname);
          exit (1);
        }

      if (!cipher_with_keysetup)
        {
          err = gcry_cipher_setkey (hd, key, keylen);
          if (err)
            {
              fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
                       gpg_strerror (err));
              gcry_cipher_close (hd);
              exit (1);
            }
        }

      start_timer ();
      for (i=err=0; !err && i < repetitions; i++)
        {
          if (cipher_with_keysetup)
            {
              err = gcry_cipher_setkey (hd, key, keylen);
              if (err)
                {
                  fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
                           gpg_strerror (err));
                  gcry_cipher_close (hd);
                  exit (1);
                }
            }
          err = gcry_cipher_decrypt ( hd, outbuf, buflen,  buf, buflen);
        }
      stop_timer ();
      printf (" %s", elapsed_time ());
      fflush (stdout);
      gcry_cipher_close (hd);
      if (err)
        {
          fprintf (stderr, "gcry_cipher_decrypt failed: %s\n",
                   gpg_strerror (err) );
          exit (1);
        }
    }

  putchar ('\n');
  gcry_free (raw_buf);
  gcry_free (raw_outbuf);
}
static void
cipher_bench ( const char *algoname )
{
  static int header_printed;
  int algo;
  gcry_cipher_hd_t hd;
  int i;
  int keylen, blklen;
  char key[128];
  char outbuf[1000], buf[1000];
  size_t buflen;
  static struct { int mode; const char *name; int blocked; } modes[] = {
    { GCRY_CIPHER_MODE_ECB, "ECB", 1 },
    { GCRY_CIPHER_MODE_CBC, "CBC", 1 },
    { GCRY_CIPHER_MODE_CFB, "CFB", 0 },
    { GCRY_CIPHER_MODE_CTR, "CTR", 0 },
    { GCRY_CIPHER_MODE_STREAM, "STREAM", 0 },
    {0}
  };
  int modeidx;
  gcry_error_t err = GPG_ERR_NO_ERROR;


  if (!algoname)
    {
      for (i=1; i < 400; i++)
        if ( !gcry_cipher_test_algo (i) )
          cipher_bench (gcry_cipher_algo_name (i));
      return;
    }


  if (!header_printed)
    {
      printf ("%-10s", "");
      for (modeidx=0; modes[modeidx].mode; modeidx++)
        printf (" %-15s", modes[modeidx].name );
      putchar ('\n');
      printf ("%-10s", "");
      for (modeidx=0; modes[modeidx].mode; modeidx++)
        printf (" ---------------" );
      putchar ('\n');
      header_printed = 1;
    }

  algo = gcry_cipher_map_name (algoname);
  if (!algo)
    {
      fprintf (stderr, PGM ": invalid cipher algorithm `%s'\n", algoname);
      exit (1);
    }

  keylen = gcry_cipher_get_algo_keylen (algo);
  if (!keylen)
    {
      fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n",
	       algoname);
      exit (1);
    }
  if ( keylen > sizeof key )
    {
        fprintf (stderr, PGM ": algo %d, keylength problem (%d)\n",
                 algo, keylen );
        exit (1);
    }
  for (i=0; i < keylen; i++)
    key[i] = i + (clock () & 0xff);

  blklen = gcry_cipher_get_algo_blklen (algo);
  if (!blklen)
    {
      fprintf (stderr, PGM ": failed to get block length for algorithm `%s'\n",
	       algoname);
      exit (1);
    }

  printf ("%-10s", gcry_cipher_algo_name (algo));
  fflush (stdout);

  for (modeidx=0; modes[modeidx].mode; modeidx++)
    {
      if ((blklen > 1 && modes[modeidx].mode == GCRY_CIPHER_MODE_STREAM)
          | (blklen == 1 && modes[modeidx].mode != GCRY_CIPHER_MODE_STREAM))
        {
          printf ("                " );
          continue;
        }

      for (i=0; i < sizeof buf; i++)
        buf[i] = i;

      err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0);
      if (err)
        {
          fprintf (stderr, PGM ": error opening cipher `%s'\n", algoname);
          exit (1);
        }
      
      err = gcry_cipher_setkey (hd, key, keylen);
      if (err)
      { 
          fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
		   gpg_strerror (err));
          gcry_cipher_close (hd);
          exit (1);
        }

      buflen = sizeof buf;
      if (modes[modeidx].blocked)
        buflen = (buflen / blklen) * blklen;

      start_timer ();
      for (i=err=0; !err && i < 1000; i++)
        err = gcry_cipher_encrypt ( hd, outbuf, buflen, buf, buflen);
      stop_timer ();
      printf (" %s", elapsed_time ());
      fflush (stdout);
      gcry_cipher_close (hd);
      if (err)
        { 
          fprintf (stderr, "gcry_cipher_encrypt failed: %s\n",
                   gpg_strerror (err) );
          exit (1);
        }

      err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0);
      if (err)
        {
          fprintf (stderr, PGM ": error opening cipher `%s'/n", algoname);
          exit (1);
        }
      
      err = gcry_cipher_setkey (hd, key, keylen);
      if (err)
        { 
          fprintf (stderr, "gcry_cipher_setkey failed: %s\n",
                   gpg_strerror (err));
          gcry_cipher_close (hd);
          exit (1);
        }

      start_timer ();
      for (i=err=0; !err && i < 1000; i++)
        err = gcry_cipher_decrypt ( hd, outbuf, buflen,  buf, buflen);
      stop_timer ();
      printf (" %s", elapsed_time ());
      fflush (stdout);
      gcry_cipher_close (hd);
      if (err)
        { 
          fprintf (stderr, "gcry_cipher_decrypt failed: %s\n",
                   gpg_strerror (err) );
          exit (1);
        }
    }

  putchar ('\n');
}
Beispiel #11
0
static gcry_cipher_hd_t
prepare_and_encode_pkcs8_cipher (GNode *asn, const gchar *password,
                                 gsize n_password, gsize *n_block)
{
	GNode *asn1_params = NULL;
	gcry_cipher_hd_t cih;
	guchar *salt;
	gsize n_salt;
	gcry_error_t gcry;
	guchar *key, *iv;
	gsize n_key;
	int iterations;

	init_quarks ();

	/* Make sure the encryption algorithm works */
	g_return_val_if_fail (gcry_cipher_algo_info (gcry_cipher_map_name (g_quark_to_string (OID_PKCS12_PBE_3DES_SHA1)),
	                                             GCRYCTL_TEST_ALGO, NULL, 0) == 0, NULL);

	/* The encryption algorithm */
	if(!egg_asn1x_set_oid_as_quark (egg_asn1x_node (asn, "encryptionAlgorithm", "algorithm", NULL),
	                                OID_PKCS12_PBE_3DES_SHA1))
		g_return_val_if_reached (NULL);

	/* Randomize some input for the password based secret */
	iterations = g_random_int_range (1000, 4096);
	n_salt = 8;
	salt = g_malloc (n_salt);
	gcry_create_nonce (salt, n_salt);

	/* Allocate space for the key and iv */
	n_key = gcry_cipher_get_algo_keylen (GCRY_CIPHER_3DES);
	*n_block = gcry_cipher_get_algo_blklen (GCRY_MD_SHA1);
	g_return_val_if_fail (n_key && *n_block, NULL);

	if (!egg_symkey_generate_pkcs12 (GCRY_CIPHER_3DES, GCRY_MD_SHA1,
	                                        password, n_password, salt,
	                                        sizeof (salt), iterations, &key, &iv))
		g_return_val_if_reached (NULL);

	/* Now write out the parameters */
	asn1_params = egg_asn1x_create (pkix_asn1_tab, "pkcs-12-PbeParams");
	g_return_val_if_fail (asn1_params, NULL);
	egg_asn1x_set_string_as_raw (egg_asn1x_node (asn1_params, "salt", NULL), salt, n_salt, g_free);
	egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn1_params, "iterations", NULL), iterations);
	egg_asn1x_set_any_from (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL), asn1_params);

	/* Now make a cipher that matches what we wrote out */
	gcry = gcry_cipher_open (&cih, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0);
	g_return_val_if_fail (gcry == 0, NULL);
	g_return_val_if_fail (cih, NULL);

	gcry_cipher_setiv (cih, iv, *n_block);
	gcry_cipher_setkey (cih, key, n_key);

	g_free (iv);
	egg_secure_free (key);
	egg_asn1x_destroy (asn1_params);

	return cih;
}
Beispiel #12
0
int main (int argc, char **argv) {
	/*
		Parse arguments
	*/
	if(opt_parse("usage: %s < filename > [options]", options, argv) == 0) {
		opt_help(0, NULL);
	}
		
	/*
		Read in password
	*/
	char *pass = NULL;
	size_t passLen = 0;
	ssize_t passRead;
	
	char *fileName;
		
	printf("Password: "******"libgcrypt version mismatch\n", stderr);
		exit (2);
	}

	gcry_control(GCRYCTL_SUSPEND_SECMEM_WARN);
	gcry_control(GCRYCTL_INIT_SECMEM, 131072, 0);
	gcry_control(GCRYCTL_RESUME_SECMEM_WARN);
	gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);

	/*
		Key Generation
	*/
	char key[16] = "";
	size_t keyLength = gcry_cipher_get_algo_keylen(GCRY_CIPHER);

	const char *salt = "NaCl";
	size_t saltLen = sizeof(salt);
	unsigned long iterations = 4096;
	gpg_error_t errStatus;
		
	errStatus = gcry_kdf_derive(pass, passLen, GCRY_KDF_PBKDF2, GCRY_MD_SHA512, salt, saltLen, iterations, keyLength, key);
			
	/*
		Cipher Setup
	*/
//	printf("Key: %X\n", key);
	puts(key);
	
	const char* IV = "5844"; // const int IV = 5844;
	const char *name = "aes128";
	int algorithm = gcry_cipher_map_name(name);
	size_t blockLength = gcry_cipher_get_algo_blklen(GCRY_CIPHER);
	gcry_cipher_hd_t hand;

	gcry_cipher_open(&hand, algorithm, GCRY_CIPHER_MODE_CBC, 0);
	gcry_cipher_setkey(hand, key, keyLength);
	gcry_cipher_setiv(hand, IV, blockLength);
	
	char *buffer;
	long len;
	size_t macLen = 0;
	
	/*
		If the local flag is set then we encrypt the file locally
		instead of sending it over the network
		Otherwise we send the file over the network
	*/
	if (local == 1) {
	
		/* 
			Open the file for reading and then copy to a buffer
		*/	
		FILE *ifp = fopen(argv[1], "rb");
		if(ifp == 0) {
			printf("%s", "Could not open file");
			return 1;
		}
		
		// Lets figure out how big the file is
		fseek(ifp, 0L, SEEK_END);
		len = ftell(ifp);
		rewind(ifp);
		
		// Allocate secure RAM for the buffer
		buffer = gcry_calloc_secure(len, sizeof(char));

		// Copy the input file to the buffer
		fread(buffer, 1, len, ifp);
		
		// Since we're running locally, the name of the output file is the same as the argument
		// without the .gt
		fileName = argv[1];
		size_t inLen = strlen(fileName);

		// End the filename by replacing the "." with a NULL char
		fileName[inLen-3] = '\0';
	
		fclose(ifp);
		
	} else {
		/*
			Retrieve file from remote computer
			Open a socket and listen for communication
		*/
		int sock;
		int localSock;
		struct sockaddr_in inPort;
		
		inPort.sin_family = AF_INET;
		inPort.sin_addr.s_addr = INADDR_ANY;
		inPort.sin_port = htons(port);
	
		sock = socket(AF_INET, SOCK_STREAM, 0);

		if (sock == -1) {
			printf("%s", "Could not open socket");
			exit(1);
		}
		
		bind(sock, (struct sockaddr *) &inPort, sizeof(inPort));
		listen(sock, 0);
		
		printf("%s", "Waiting for connection...\n");
		
		// Accepting the connection
		localSock = accept(sock, NULL, NULL);
		printf("%s", "Inbound file...\n");
		
		// Allocate some memory for the buffer
		// len+(160(len%16)) is so that the memory we allocate is divisible 
		// by the blocklength, which is 16
        len = 4096L;
		buffer = gcry_calloc_secure(len+(16-(len%16)), sizeof(char));
        long dataRead = 0L;
        int keepReading = 1;
		
		// Let's figure out how much data we're getting
		// If I were to do this part over, I would instead open two connections
		// from techrypt- where the first connection sends the 
		// amount of data to be transmitted in the second connection
        while (keepReading) {
            dataRead = recv(localSock, buffer, len, MSG_PEEK);
            if (dataRead == len) {
                len = len * 2;
				sleep(.5);
                buffer = gcry_realloc(buffer, len);
                keepReading = 1;
            } else {
                keepReading = 0;
            }
        }
		// How much data did we read?
        len = dataRead;
		
		// Now lets actually store it in the buffer
        dataRead = recv(localSock, buffer, len, 0);
		
		// Output file name is the command line argument
		fileName = argv[1];
			
		close(sock);
		
		/*
			Setup the HMAC
		*/
		gcry_md_hd_t macHand;
	
		macLen = gcry_md_get_algo_dlen(GCRY_MD_SHA512);
		char *mac = gcry_calloc_secure(macLen, sizeof(char));
		
		gcry_md_open(&macHand, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC);
		gcry_md_setkey(macHand, key, keyLength);
		
		// Generate the HMAC for the message we received
		// Since we know there's a MAC of size macLen at the end
		// we will only generate the hash based on the first
		// len-macLen bytes
		gcry_md_write(macHand, buffer, len-macLen);
		mac = gcry_md_read(macHand, 0);
		
		/*
			Strip HMAC from buffer
		*/
		char *exMac = buffer+(len-macLen);
		
		/*
			Check HMAC against our HMAC
		*/
		// I think this may be exploitable with a strategically placed NULL
		// The use of memcmp could fix this...if I have time I will replace and check
		if(strncmp(mac, exMac, macLen) != 0) {
			exit(62);
		}
								
	}	
	

	/*
		Decrypt the buffer
	*/
	gcry_cipher_decrypt(hand, buffer, len, NULL, 0);
	
	
	/*
		Reverse padding algorithm
		Strip the amount of bytes from the end of the file
		determined by the contents of the last byte
		This is why using PKCS7 was so useful
	*/
	char *padPtr = buffer+len-macLen-1;
	int writeLen = len-macLen-(*padPtr);
	
	/*
		Write the buffer to a file
	*/
	FILE *ofp = fopen(fileName, "wb");
	fwrite(buffer, 1, writeLen, ofp);
	
	fclose(ofp);
		
	return 0;
}