Пример #1
0
/****************
 * This filter is used to en/de-cipher data with a conventional algorithm
 */
int
cipher_filter( void *opaque, int control,
	       IOBUF a, byte *buf, size_t *ret_len)
{
    size_t size = *ret_len;
    cipher_filter_context_t *cfx = opaque;
    int rc=0;

    if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */
	rc = -1; /* not yet used */
    }
    else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
	assert(a);
	if( !cfx->header ) {
	    write_header( cfx, a );
	}
	if (cfx->mdc_hash)
	    gcry_md_write (cfx->mdc_hash, buf, size);
	gcry_cipher_encrypt (cfx->cipher_hd, buf, size, NULL, 0);
	rc = iobuf_write( a, buf, size );
    }
    else if( control == IOBUFCTRL_FREE ) {
	if( cfx->mdc_hash ) {
	    byte *hash;
	    int hashlen = gcry_md_get_algo_dlen (gcry_md_get_algo
                                                 (cfx->mdc_hash));
	    byte temp[22];

	    assert( hashlen == 20 );
	    /* We must hash the prefix of the MDC packet here. */
	    temp[0] = 0xd3;
	    temp[1] = 0x14;
	    gcry_md_putc (cfx->mdc_hash, temp[0]);
	    gcry_md_putc (cfx->mdc_hash, temp[1]);

	    gcry_md_final (cfx->mdc_hash);
	    hash = gcry_md_read (cfx->mdc_hash, 0);
	    memcpy(temp+2, hash, 20);
	    gcry_cipher_encrypt (cfx->cipher_hd, temp, 22, NULL, 0);
	    gcry_md_close (cfx->mdc_hash); cfx->mdc_hash = NULL;
	    if( iobuf_write( a, temp, 22 ) )
		log_error("writing MDC packet failed\n" );
	}
	gcry_cipher_close (cfx->cipher_hd);
    }
    else if( control == IOBUFCTRL_DESC ) {
	*(char**)buf = "cipher_filter";
    }
    return rc;
}
Пример #2
0
/* final part of the hash */
static uint8_t *hash_finish( gcry_md_hd_t hd, signature_packet_t *p_sig )
{
    if( p_sig->version == 3 )
    {
        gcry_md_putc( hd, p_sig->type );
        gcry_md_write( hd, &p_sig->specific.v3.timestamp, 4 );
    }
    else if( p_sig->version == 4 )
    {
        gcry_md_putc( hd, p_sig->version );
        gcry_md_putc( hd, p_sig->type );
        gcry_md_putc( hd, p_sig->public_key_algo );
        gcry_md_putc( hd, p_sig->digest_algo );
        gcry_md_write( hd, p_sig->specific.v4.hashed_data_len, 2 );
        size_t i_len = scalar_number( p_sig->specific.v4.hashed_data_len, 2 );
        gcry_md_write( hd, p_sig->specific.v4.hashed_data, i_len );

        gcry_md_putc( hd, 0x04 );
        gcry_md_putc( hd, 0xFF );

        i_len += 6; /* hashed data + 6 bytes header */

        gcry_md_putc( hd, (i_len >> 24) & 0xff );
        gcry_md_putc( hd, (i_len >> 16) & 0xff );
        gcry_md_putc( hd, (i_len >> 8) & 0xff );
        gcry_md_putc( hd, (i_len) & 0xff );
    }
Пример #3
0
int _hash_my_key(QSP_ARG_DECL  void **vpp,const char *key,int key_len)
{
	unsigned char *digest;
	unsigned char *storage;
	int i;
	int need_size;

	// get required digest size
	need_size = gcry_md_get_algo_dlen(the_hash_algo);
	storage = getbuf(need_size);

	for(i=0;i<key_len;i++){
		gcry_md_putc(my_hash_hdl,key[i]);
	}
	gcry_md_final(my_hash_hdl);
	digest = gcry_md_read(my_hash_hdl,0);
	memcpy(storage,digest,need_size);
	*vpp = storage;

	gcry_md_reset(my_hash_hdl);	// to compute a second hash
					// or we could close?

	// return the length of the hash
	// For SHA256, this is 32
	return the_hash_len;
}
Пример #4
0
/*
 * This filter is used to en/de-cipher data with a symmetric algorithm
 */
int
cipher_filter_cfb (void *opaque, int control,
                   iobuf_t a, byte *buf, size_t *ret_len)
{
  cipher_filter_context_t *cfx = opaque;
  size_t size = *ret_len;
  int rc = 0;

  if (control == IOBUFCTRL_UNDERFLOW) /* decrypt */
    {
      rc = -1; /* not yet used */
    }
  else if (control == IOBUFCTRL_FLUSH) /* encrypt */
    {
      log_assert (a);
      if (!cfx->wrote_header)
        write_header (cfx, a);
      if (cfx->mdc_hash)
        gcry_md_write (cfx->mdc_hash, buf, size);
      gcry_cipher_encrypt (cfx->cipher_hd, buf, size, NULL, 0);
      if (cfx->short_blklen_warn)
        {
          cfx->short_blklen_count += size;
          if (cfx->short_blklen_count > (150 * 1024 * 1024))
            {
              log_info ("WARNING: encrypting more than %d MiB with algorithm "
                        "%s should be avoided\n", 150,
                        openpgp_cipher_algo_name (cfx->dek->algo));
              cfx->short_blklen_warn = 0; /* Don't show again.  */
            }
        }

      rc = iobuf_write (a, buf, size);
    }
  else if (control == IOBUFCTRL_FREE)
    {
      if (cfx->mdc_hash)
        {
          byte *hash;
          int hashlen = gcry_md_get_algo_dlen (gcry_md_get_algo(cfx->mdc_hash));
          byte temp[22];

          log_assert (hashlen == 20);
          /* We must hash the prefix of the MDC packet here. */
          temp[0] = 0xd3;
          temp[1] = 0x14;
          gcry_md_putc (cfx->mdc_hash, temp[0]);
          gcry_md_putc (cfx->mdc_hash, temp[1]);

          gcry_md_final (cfx->mdc_hash);
          hash = gcry_md_read (cfx->mdc_hash, 0);
          memcpy(temp+2, hash, 20);
          gcry_cipher_encrypt (cfx->cipher_hd, temp, 22, NULL, 0);
          gcry_md_close (cfx->mdc_hash); cfx->mdc_hash = NULL;
          if (iobuf_write( a, temp, 22))
            log_error ("writing MDC packet failed\n");
	}

      gcry_cipher_close (cfx->cipher_hd);
    }
  else if (control == IOBUFCTRL_DESC)
    {
      mem2str (buf, "cipher_filter_cfb", *ret_len);
    }

  return rc;
}
Пример #5
0
static int
iscsi_login_add_chap_response(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
{
	char str[MAX_STRING_SIZE+1];
	char * strp;
	unsigned char c, cc[2];
	unsigned char digest[16];
	gcry_md_hd_t ctx;
	int i;

	if (iscsi->current_phase != ISCSI_PDU_LOGIN_CSG_SECNEG
	|| iscsi->secneg_phase != ISCSI_LOGIN_SECNEG_PHASE_SEND_RESPONSE) {
		return 0;
	}

	gcry_md_open(&ctx, GCRY_MD_MD5, 0);
	if (!ctx) {
		iscsi_set_error(iscsi, "Cannot create MD5 algorithm");
		return -1;
	}

	if (!iscsi->chap_c[0]) {
		iscsi_set_error(iscsi, "No CHAP challenge found");
		return -1;
	}
	gcry_md_putc(ctx, iscsi->chap_i);
	gcry_md_write(ctx, (unsigned char *)iscsi->passwd, strlen(iscsi->passwd));

	strp = iscsi->chap_c;
	while (*strp != 0) {
		c = (h2i(strp[0]) << 4) | h2i(strp[1]);
		strp += 2;
		gcry_md_putc(ctx, c);
	}
	memcpy(digest, gcry_md_read(ctx, 0), sizeof(digest));
	gcry_md_close(ctx);

	strncpy(str,"CHAP_R=0x",MAX_STRING_SIZE);
	if (iscsi_pdu_add_data(iscsi, pdu, (unsigned char *)str, strlen(str))
	    != 0) {
		iscsi_set_error(iscsi, "Out-of-memory: pdu add data failed.");
		return -1;
	}

	for (i=0; i<16; i++) {
		c = digest[i];
		cc[0] = i2h((c >> 4)&0x0f);
		cc[1] = i2h((c     )&0x0f);
		if (iscsi_pdu_add_data(iscsi, pdu, &cc[0], 2) != 0) {
			iscsi_set_error(iscsi, "Out-of-memory: pdu add data "
				"failed.");
			return -1;
		}
	}
	c = 0;
	if (iscsi_pdu_add_data(iscsi, pdu, &c, 1) != 0) {
		iscsi_set_error(iscsi, "Out-of-memory: pdu add data "
			"failed.");
		return -1;
	}

	return 0;
}
Пример #6
0
/* Hash a passphrase using the supplied s2k.
   Always needs: dek->algo, s2k->mode, s2k->hash_algo.  */
static void
hash_passphrase ( DEK *dek, char *pw, STRING2KEY *s2k)
{
  gcry_md_hd_t md;
  int pass, i;
  int used = 0;
  int pwlen = strlen(pw);

  assert ( s2k->hash_algo );
  dek->keylen = openpgp_cipher_get_algo_keylen (dek->algo);
  if ( !(dek->keylen > 0 && dek->keylen <= DIM(dek->key)) )
    BUG();

  if (gcry_md_open (&md, s2k->hash_algo, 1))
    BUG ();
  for (pass=0; used < dek->keylen ; pass++ )
    {
      if ( pass )
        {
          gcry_md_reset (md);
          for (i=0; i < pass; i++ ) /* Preset the hash context.  */
            gcry_md_putc (md, 0 );
	}

      if ( s2k->mode == 1 || s2k->mode == 3 )
        {
          int len2 = pwlen + 8;
          ulong count = len2;

          if ( s2k->mode == 3 )
            {
              count = S2K_DECODE_COUNT(s2k->count);
              if ( count < len2 )
                count = len2;
	    }

          /* Fixme: To avoid DoS attacks by sending an sym-encrypted
             packet with a very high S2K count, we should either cap
             the iteration count or CPU seconds based timeout.  */

          /* A little bit complicated because we need a ulong for count. */
          while ( count > len2 )  /* maybe iterated+salted */
            {
              gcry_md_write ( md, s2k->salt, 8 );
              gcry_md_write ( md, pw, pwlen );
              count -= len2;
	    }
          if ( count < 8 )
            gcry_md_write ( md, s2k->salt, count );
          else
            {
              gcry_md_write ( md, s2k->salt, 8 );
              count -= 8;
              gcry_md_write ( md, pw, count );
	    }
	}
      else
        gcry_md_write ( md, pw, pwlen );
      gcry_md_final( md );

      i = gcry_md_get_algo_dlen ( s2k->hash_algo );
      if ( i > dek->keylen - used )
        i = dek->keylen - used;

      memcpy (dek->key+used, gcry_md_read (md, s2k->hash_algo), i);
      used += i;
    }
  gcry_md_close(md);
}
Пример #7
0
static void
md_bench ( const char *algoname )
{
  int algo;
  gcry_md_hd_t hd;
  int i, j, repcount;
  char buf_base[1000+15];
  size_t bufsize = 1000;
  char *buf;
  char *largebuf_base;
  char *largebuf;
  char digest[512/8];
  gcry_error_t err = GPG_ERR_NO_ERROR;

  if (!algoname)
    {
      for (i=1; i < 400; i++)
        if (in_fips_mode && i == GCRY_MD_MD5)
          ; /* Don't use MD5 in fips mode.  */
        else if ( !gcry_md_test_algo (i) )
          md_bench (gcry_md_algo_name (i));
      return;
    }

  buf = buf_base + ((16 - ((size_t)buf_base & 0x0f)) % buffer_alignment);

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

  err = gcry_md_open (&hd, algo, 0);
  if (err)
    {
      fprintf (stderr, PGM ": error opening hash algorithm `%s'\n", algoname);
      exit (1);
    }

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

  printf ("%-12s", gcry_md_algo_name (algo));

  start_timer ();
  for (repcount=0; repcount < hash_repetitions; repcount++)
    for (i=0; i < 1000; i++)
      gcry_md_write (hd, buf, bufsize);
  gcry_md_final (hd);
  stop_timer ();
  printf (" %s", elapsed_time ());
  fflush (stdout);

  gcry_md_reset (hd);
  start_timer ();
  for (repcount=0; repcount < hash_repetitions; repcount++)
    for (i=0; i < 10000; i++)
      gcry_md_write (hd, buf, bufsize/10);
  gcry_md_final (hd);
  stop_timer ();
  printf (" %s", elapsed_time ());
  fflush (stdout);

  gcry_md_reset (hd);
  start_timer ();
  for (repcount=0; repcount < hash_repetitions; repcount++)
    for (i=0; i < 1000000; i++)
      gcry_md_write (hd, buf, 1);
  gcry_md_final (hd);
  stop_timer ();
  printf (" %s", elapsed_time ());
  fflush (stdout);

  start_timer ();
  for (repcount=0; repcount < hash_repetitions; repcount++)
    for (i=0; i < 1000; i++)
      for (j=0; j < bufsize; j++)
        gcry_md_putc (hd, buf[j]);
  gcry_md_final (hd);
  stop_timer ();
  printf (" %s", elapsed_time ());
  fflush (stdout);

  gcry_md_close (hd);

  /* Now 100 hash operations on 10000 bytes using the fast function.
     We initialize the buffer so that all memory pages are committed
     and we have repeatable values.  */
  if (gcry_md_get_algo_dlen (algo) > sizeof digest)
    die ("digest buffer too short\n");

  largebuf_base = malloc (10000+15);
  if (!largebuf_base)
    die ("out of core\n");
  largebuf = (largebuf_base
              + ((16 - ((size_t)largebuf_base & 0x0f)) % buffer_alignment));

  for (i=0; i < 10000; i++)
    largebuf[i] = i;
  start_timer ();
  for (repcount=0; repcount < hash_repetitions; repcount++)
    for (i=0; i < 100; i++)
      gcry_md_hash_buffer (algo, digest, largebuf, 10000);
  stop_timer ();
  printf (" %s", elapsed_time ());
  free (largebuf_base);

  putchar ('\n');
  fflush (stdout);
}
Пример #8
0
gboolean
egg_hkdf_perform (const gchar *hash_algo, gconstpointer input, gsize n_input,
                  gconstpointer salt, gsize n_salt, gconstpointer info,
                  gsize n_info, gpointer output, gsize n_output)
{
	gpointer alloc = NULL;
	gpointer buffer = NULL;
	gcry_md_hd_t md1, md2;
	guint hash_len;
	gint i;
	gint flags, algo;
	gsize step, n_buffer;
	guchar *at;
	gcry_error_t gcry;

	algo = gcry_md_map_name (hash_algo);
	g_return_val_if_fail (algo != 0, FALSE);

	hash_len = gcry_md_get_algo_dlen (algo);
	g_return_val_if_fail (hash_len != 0, FALSE);
	g_return_val_if_fail (n_output <= 255 * hash_len, FALSE);

	/* Buffer we need to for intermediate stuff */
	if (gcry_is_secure (input)) {
		flags = GCRY_MD_FLAG_SECURE;
		buffer = gcry_malloc_secure (hash_len);
	} else {
		flags = 0;
		buffer = gcry_malloc (hash_len);
	}

	g_return_val_if_fail (buffer, FALSE);
	n_buffer = 0;

	/* Salt defaults to hash_len zeros */
	if (!salt) {
		salt = alloc = g_malloc0 (hash_len);
		n_salt = hash_len;
	}

	/* Step 1: Extract */
	gcry = gcry_md_open (&md1, algo, GCRY_MD_FLAG_HMAC | flags);
	g_return_val_if_fail (gcry == 0, FALSE);
	gcry = gcry_md_setkey (md1, salt, n_salt);
	g_return_val_if_fail (gcry == 0, FALSE);
	gcry_md_write (md1, input, n_input);

	/* Step 2: Expand */
	gcry = gcry_md_open (&md2, algo, GCRY_MD_FLAG_HMAC | flags);
	g_return_val_if_fail (gcry == 0, FALSE);
	gcry = gcry_md_setkey (md2, gcry_md_read (md1, algo), hash_len);
	g_return_val_if_fail (gcry == 0, FALSE);
	gcry_md_close (md1);

	at = output;
	for (i = 1; i < 256; ++i) {
		gcry_md_reset (md2);
		gcry_md_write (md2, buffer, n_buffer);
		gcry_md_write (md2, info, n_info);
		gcry_md_putc (md2, i);

		n_buffer = hash_len;
		memcpy (buffer, gcry_md_read (md2, algo), n_buffer);

		step = MIN (n_buffer, n_output);
		memcpy (at, buffer, step);
		n_output -= step;
		at += step;

		if (!n_output)
			break;
	}

	g_free (alloc);
	gcry_free (buffer);
	return TRUE;
}
Пример #9
0
/****************
 * Copy data from INP to OUT and do some escaping if requested.
 * md is updated as required by rfc2440
 */
int
copy_clearsig_text( IOBUF out, IOBUF inp, gcry_md_hd_t md,
		    int escape_dash, int escape_from)
{
    unsigned int maxlen;
    byte *buffer = NULL;    /* malloced buffer */
    unsigned int bufsize;   /* and size of this buffer */
    unsigned int n;
    int truncated = 0;
    int pending_lf = 0;

   if( !escape_dash )
	escape_from = 0;

    write_status_begin_signing (md);

    for(;;) {
	maxlen = MAX_LINELEN;
	n = iobuf_read_line( inp, &buffer, &bufsize, &maxlen );
	if( !maxlen )
	    truncated++;

	if( !n )
	    break; /* read_line has returned eof */

	/* update the message digest */
	if( escape_dash ) {
	    if( pending_lf ) {
		gcry_md_putc ( md, '\r' );
		gcry_md_putc ( md, '\n' );
	    }
	    gcry_md_write ( md, buffer,
                            len_without_trailing_chars (buffer, n, " \t\r\n"));
	}
	else
            gcry_md_write ( md, buffer, n );
	pending_lf = buffer[n-1] == '\n';

	/* write the output */
	if(    ( escape_dash && *buffer == '-')
	    || ( escape_from && n > 4 && !memcmp(buffer, "From ", 5 ) ) ) {
	    iobuf_put( out, '-' );
	    iobuf_put( out, ' ' );
	}

#if  0 /*defined(HAVE_DOSISH_SYSTEM)*/
	/* We don't use this anymore because my interpretation of rfc2440 7.1
	 * is that there is no conversion needed.  If one decides to
	 * clearsign a unix file on a DOS box he will get a mixed line endings.
	 * If at some point it turns out, that a conversion is a nice feature
	 * we can make an option out of it.
	 */
	/* make sure the lines do end in CR,LF */
	if( n > 1 && ( (buffer[n-2] == '\r' && buffer[n-1] == '\n' )
			    || (buffer[n-2] == '\n' && buffer[n-1] == '\r'))) {
	    iobuf_write( out, buffer, n-2 );
	    iobuf_put( out, '\r');
	    iobuf_put( out, '\n');
	}
	else if( n && buffer[n-1] == '\n' ) {
	    iobuf_write( out, buffer, n-1 );
	    iobuf_put( out, '\r');
	    iobuf_put( out, '\n');
	}
	else
	    iobuf_write( out, buffer, n );

#else
	iobuf_write( out, buffer, n );
#endif
    }

    /* at eof */
    if( !pending_lf ) { /* make sure that the file ends with a LF */
	iobuf_writestr( out, LF );
	if( !escape_dash )
	    gcry_md_putc( md, '\n' );
    }

    if( truncated )
	log_info(_("input line longer than %d characters\n"), MAX_LINELEN );

    return 0; /* okay */
}