예제 #1
0
파일: srp.c 프로젝트: attilamolnar/gnutls
/* generate x = SHA(s | SHA(U | ":" | p))
 * The output is exactly 20 bytes
 */
static int
_gnutls_calc_srp_sha(const char *username, const char *password,
		     uint8_t * salt, int salt_size, size_t * size,
		     void *digest)
{
	digest_hd_st td;
	uint8_t res[MAX_HASH_SIZE];
	int ret;
	const mac_entry_st *me = mac_to_entry(GNUTLS_MAC_SHA1);

	*size = 20;

	ret = _gnutls_hash_init(&td, me);
	if (ret < 0) {
		return GNUTLS_E_MEMORY_ERROR;
	}
	_gnutls_hash(&td, username, strlen(username));
	_gnutls_hash(&td, ":", 1);
	_gnutls_hash(&td, password, strlen(password));

	_gnutls_hash_deinit(&td, res);

	ret = _gnutls_hash_init(&td, me);
	if (ret < 0) {
		return GNUTLS_E_MEMORY_ERROR;
	}

	_gnutls_hash(&td, salt, salt_size);
	_gnutls_hash(&td, res, 20);	/* 20 bytes is the output of sha1 */

	_gnutls_hash_deinit(&td, digest);

	return 0;
}
예제 #2
0
static int
ssl3_sha(int i, uint8_t * secret, int secret_len,
	 uint8_t * rnd, int rnd_len, void *digest)
{
	int j, ret;
	uint8_t text1[26];

	digest_hd_st td;

	for (j = 0; j < i + 1; j++) {
		text1[j] = 65 + i;	/* A==65 */
	}

	ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_SHA1));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_hash(&td, text1, i + 1);
	_gnutls_hash(&td, secret, secret_len);
	_gnutls_hash(&td, rnd, rnd_len);

	_gnutls_hash_deinit(&td, digest);
	return 0;
}
예제 #3
0
static int
ssl3_md5(int i, uint8_t * secret, int secret_len,
	 uint8_t * rnd, int rnd_len, void *digest)
{
	uint8_t tmp[MAX_HASH_SIZE];
	digest_hd_st td;
	int ret;

	ret = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_MD5));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_hash(&td, secret, secret_len);

	ret = ssl3_sha(i, secret, secret_len, rnd, rnd_len, tmp);
	if (ret < 0) {
		gnutls_assert();
		_gnutls_hash_deinit(&td, digest);
		return ret;
	}

	_gnutls_hash(&td, tmp, SHA1_DIGEST_OUTPUT);

	_gnutls_hash_deinit(&td, digest);
	return 0;
}
예제 #4
0
int
_gnutls_ssl3_hash_md5(const void *first, int first_len,
		      const void *second, int second_len,
		      int ret_len, uint8_t * ret)
{
	uint8_t digest[MAX_HASH_SIZE];
	digest_hd_st td;
	int block = MD5_DIGEST_OUTPUT;
	int rc;

	rc = _gnutls_hash_init(&td, mac_to_entry(GNUTLS_MAC_MD5));
	if (rc < 0) {
		gnutls_assert();
		return rc;
	}

	_gnutls_hash(&td, first, first_len);
	_gnutls_hash(&td, second, second_len);

	_gnutls_hash_deinit(&td, digest);

	if (ret_len > block) {
		gnutls_assert();
		return GNUTLS_E_INTERNAL_ERROR;
	}

	memcpy(ret, digest, ret_len);

	return 0;

}
예제 #5
0
/* generate x = SHA(s | SHA(U | ":" | p))
 * The output is exactly 20 bytes
 */
int
_gnutls_calc_srp_sha (const char *username, const char *password,
		      opaque * salt, int salt_size, size_t * size,
		      void *digest)
{
  GNUTLS_HASH_HANDLE td;
  opaque res[MAX_HASH_SIZE];

  *size = 20;

  td = _gnutls_hash_init (GNUTLS_MAC_SHA1);
  if (td == NULL)
    {
      return GNUTLS_E_MEMORY_ERROR;
    }
  _gnutls_hash (td, username, strlen (username));
  _gnutls_hash (td, ":", 1);
  _gnutls_hash (td, password, strlen (password));

  _gnutls_hash_deinit (td, res);

  td = _gnutls_hash_init (GNUTLS_MAC_SHA1);
  if (td == NULL)
    {
      return GNUTLS_E_MEMORY_ERROR;
    }

  _gnutls_hash (td, salt, salt_size);
  _gnutls_hash (td, res, 20);	/* 20 bytes is the output of sha1 */

  _gnutls_hash_deinit (td, digest);

  return 0;
}
예제 #6
0
파일: sig-check.c 프로젝트: bf4/pidgin-mac
/* Hash all multi precision integers of the key PK with the given
   message digest context MD. */
static int
hash_mpibuf (cdk_pubkey_t pk, digest_hd_st * md, int usefpr)
{
  byte buf[MAX_MPI_BYTES];	/* FIXME: do not use hardcoded length. */
  size_t nbytes;
  size_t i, npkey;
  int err;

  /* We have to differ between two modes for v3 keys. To form the
     fingerprint, we hash the MPI values without the length prefix.
     But if we calculate the hash for verifying/signing we use all data. */
  npkey = cdk_pk_get_npkey (pk->pubkey_algo);
  for (i = 0; i < npkey; i++)
    {
      nbytes = MAX_MPI_BYTES;
      err = _gnutls_mpi_print_pgp (pk->mpi[i], buf, &nbytes);
      if (err < 0)
	return map_gnutls_error (err);
      if (!usefpr || pk->version == 4)
	_gnutls_hash (md, buf, nbytes);
      else			/* without the prefix. */
	_gnutls_hash (md, buf + 2, nbytes - 2);
    }
  return 0;
}
예제 #7
0
int
_gnutls_mac_init_ssl3(digest_hd_st * ret, const mac_entry_st * e,
		      void *key, int keylen)
{
	uint8_t ipad[48];
	int padsize, result;

	FAIL_IF_LIB_ERROR;

	padsize = get_padsize(e->id);
	if (padsize == 0) {
		gnutls_assert();
		return GNUTLS_E_HASH_FAILED;
	}

	memset(ipad, 0x36, padsize);

	result = _gnutls_hash_init(ret, e);
	if (result < 0) {
		gnutls_assert();
		return result;
	}

	ret->key = key;
	ret->keysize = keylen;

	if (keylen > 0)
		_gnutls_hash(ret, key, keylen);
	_gnutls_hash(ret, ipad, padsize);

	return 0;
}
예제 #8
0
static int
openssl_hash_password(const char *pass, gnutls_datum_t * key,
		      gnutls_datum_t * salt)
{
	unsigned char md5[16];
	digest_hd_st hd;
	unsigned int count = 0;
	int err;

	while (count < key->size) {
		err = _gnutls_hash_init(&hd, mac_to_entry(GNUTLS_MAC_MD5));
		if (err) {
			gnutls_assert();
			return err;
		}
		if (count) {
			err = _gnutls_hash(&hd, md5, sizeof(md5));
			if (err) {
			      hash_err:
				_gnutls_hash_deinit(&hd, NULL);
				gnutls_assert();
				return err;
			}
		}
		if (pass) {
			err = _gnutls_hash(&hd, pass, strlen(pass));
			if (err) {
				gnutls_assert();
				goto hash_err;
			}
		}
		err = _gnutls_hash(&hd, salt->data, 8);
		if (err) {
			gnutls_assert();
			goto hash_err;
		}

		_gnutls_hash_deinit(&hd, md5);

		if (key->size - count <= sizeof(md5)) {
			memcpy(&key->data[count], md5, key->size - count);
			break;
		}

		memcpy(&key->data[count], md5, sizeof(md5));
		count += sizeof(md5);
	}

	return 0;
}
예제 #9
0
int
_gnutls_mac_deinit_ssl3_handshake(digest_hd_st * handle,
				  void *digest, uint8_t * key,
				  uint32_t key_size)
{
	uint8_t ret[MAX_HASH_SIZE];
	digest_hd_st td;
	uint8_t opad[48];
	uint8_t ipad[48];
	int padsize;
	int block, rc;

	padsize = get_padsize(handle->e->id);
	if (padsize == 0) {
		gnutls_assert();
		rc = GNUTLS_E_INTERNAL_ERROR;
		goto cleanup;
	}

	memset(opad, 0x5C, padsize);
	memset(ipad, 0x36, padsize);

	rc = _gnutls_hash_init(&td, handle->e);
	if (rc < 0) {
		gnutls_assert();
		goto cleanup;
	}

	if (key_size > 0)
		_gnutls_hash(&td, key, key_size);

	_gnutls_hash(&td, opad, padsize);
	block = _gnutls_mac_get_algo_len(handle->e);

	if (key_size > 0)
		_gnutls_hash(handle, key, key_size);
	_gnutls_hash(handle, ipad, padsize);
	_gnutls_hash_deinit(handle, ret);	/* get the previous hash */

	_gnutls_hash(&td, ret, block);

	_gnutls_hash_deinit(&td, digest);

	return 0;

      cleanup:
	_gnutls_hash_deinit(handle, NULL);
	return rc;
}
예제 #10
0
파일: sign.c 프로젝트: Chronic-Dev/gnutls
static int
dsa_sign (const gnutls_datum_t * text,
	  bigint_t * params, int params_len, gnutls_datum_t * signature)
{
  int ret;
  opaque _digest[MAX_HASH_SIZE];
  digest_hd_st hd;
  gnutls_datum_t digest;
  gnutls_digest_algorithm_t hash = _gnutls_dsa_q_to_hash (params[1]);

  ret = _gnutls_hash_init (&hd, hash);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  _gnutls_hash (&hd, text->data, text->size);
  _gnutls_hash_deinit (&hd, _digest);

  digest.data = _digest;
  digest.size = _gnutls_hash_get_algo_len (hash);

  if ((ret =
       _gnutls_sign (GNUTLS_PK_DSA, params, params_len, &digest,
		     signature)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return 0;
}
예제 #11
0
파일: sign.c 프로젝트: uvbs/SupportCenter
static int
dsa_sign (const gnutls_datum_t * text,
	  mpi_t * params, int params_len, gnutls_datum_t * signature)
{
  int ret;
  opaque _digest[MAX_HASH_SIZE];
  GNUTLS_HASH_HANDLE hd;
  gnutls_datum_t digest;

  hd = _gnutls_hash_init (GNUTLS_MAC_SHA1);
  if (hd == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_HASH_FAILED;
    }

  _gnutls_hash (hd, text->data, text->size);
  _gnutls_hash_deinit (hd, _digest);

  digest.data = _digest;
  digest.size = 20;

  if ((ret =
       _gnutls_sign (GNUTLS_PK_DSA, params, params_len, &digest,
		     signature)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return 0;
}
예제 #12
0
파일: verify.c 프로젝트: Chronic-Dev/gnutls
/* Hashes input data and verifies a DSA signature.
 */
static int
dsa_verify_sig (const gnutls_datum_t * text,
		const gnutls_datum_t * hash,
		const gnutls_datum_t * signature, bigint_t * params,
		int params_len)
{
  int ret;
  opaque _digest[MAX_HASH_SIZE];
  gnutls_datum_t digest;
  digest_hd_st hd;

  if (hash && hash->data && hash->size == 20)
    {
      digest = *hash;
    }
  else
    {
      ret = _gnutls_hash_init (&hd, GNUTLS_MAC_SHA1);
      if (ret < 0)
	{
	  gnutls_assert ();
	  return ret;
	}

      _gnutls_hash (&hd, text->data, text->size);
      _gnutls_hash_deinit (&hd, _digest);

      digest.data = _digest;
      digest.size = 20;
    }

  ret = _gnutls_dsa_verify (&digest, signature, params, params_len);

  return ret;
}
예제 #13
0
/* This calculates the SHA1(A | B)
 * A and B will be left-padded with zeros to fill n_size.
 */
mpi_t
_gnutls_calc_srp_u (mpi_t A, mpi_t B, mpi_t n)
{
  size_t b_size, a_size;
  opaque *holder, hd[MAX_HASH_SIZE];
  size_t holder_size, hash_size, n_size;
  GNUTLS_HASH_HANDLE td;
  int ret;
  mpi_t res;

  /* get the size of n in bytes */
  _gnutls_mpi_print (NULL, &n_size, n);

  _gnutls_mpi_print (NULL, &a_size, A);
  _gnutls_mpi_print (NULL, &b_size, B);

  if (a_size > n_size || b_size > n_size)
    {
      gnutls_assert ();
      return NULL;		/* internal error */
    }

  holder_size = n_size + n_size;

  holder = gnutls_calloc (1, holder_size);
  if (holder == NULL)
    return NULL;

  _gnutls_mpi_print (&holder[n_size - a_size], &a_size, A);
  _gnutls_mpi_print (&holder[n_size + n_size - b_size], &b_size, B);

  td = _gnutls_hash_init (GNUTLS_MAC_SHA1);
  if (td == NULL)
    {
      gnutls_free (holder);
      gnutls_assert ();
      return NULL;
    }
  _gnutls_hash (td, holder, holder_size);
  _gnutls_hash_deinit (td, hd);

  /* convert the bytes of hd to integer
   */
  hash_size = 20;		/* SHA */
  ret = _gnutls_mpi_scan_nz (&res, hd, &hash_size);
  gnutls_free (holder);

  if (ret < 0)
    {
      gnutls_assert ();
      return NULL;
    }

  return res;
}
예제 #14
0
int _gnutls_mac_output_ssl3(digest_hd_st * handle, void *digest)
{
	uint8_t ret[MAX_HASH_SIZE];
	digest_hd_st td;
	uint8_t opad[48];
	int padsize;
	int block, rc;

	padsize = get_padsize(handle->e->id);
	if (padsize == 0) {
		gnutls_assert();
		return GNUTLS_E_INTERNAL_ERROR;
	}

	memset(opad, 0x5C, padsize);

	rc = _gnutls_hash_init(&td, handle->e);
	if (rc < 0) {
		gnutls_assert();
		return rc;
	}

	if (handle->keysize > 0)
		_gnutls_hash(&td, handle->key, handle->keysize);

	_gnutls_hash(&td, opad, padsize);
	block = _gnutls_mac_get_algo_len(handle->e);
	_gnutls_hash_output(handle, ret);	/* get the previous hash */
	_gnutls_hash(&td, ret, block);

	_gnutls_hash_deinit(&td, digest);

	/* reset handle */
	memset(opad, 0x36, padsize);

	if (handle->keysize > 0)
		_gnutls_hash(handle, handle->key, handle->keysize);
	_gnutls_hash(handle, opad, padsize);

	return 0;
}
예제 #15
0
static inline void
mac_hash (digest_hd_st * td, void *data, int data_size, int ver)
{
  if (ver == GNUTLS_SSL3)
    {                           /* SSL 3.0 */
      _gnutls_hash (td, data, data_size);
    }
  else
    {
      _gnutls_hmac (td, data, data_size);
    }
}
예제 #16
0
파일: verify.c 프로젝트: dezelin/maily
/* Hashes input data and verifies a DSA signature.
 */
static int
dsa_verify_sig (const gnutls_datum_t * text,
                const gnutls_datum_t * hash,
                const gnutls_datum_t * signature, bigint_t * params,
                int params_len)
{
  int ret;
  opaque _digest[MAX_HASH_SIZE];
  gnutls_datum_t digest;
  digest_hd_st hd;
  gnutls_digest_algorithm_t algo;
  unsigned int hash_len;

  algo = _gnutls_dsa_q_to_hash (params[1], &hash_len);
  if (hash)
    {
      /* SHA1 or better allowed */
      if (!hash->data || hash->size < hash_len)
        {
          gnutls_assert();
          _gnutls_debug_log("Hash size (%d) does not correspond to hash %s", (int)hash->size, gnutls_mac_get_name(algo));
          
          if (hash->size != 20)
            return GNUTLS_E_PK_SIG_VERIFY_FAILED;
        }
      digest = *hash;
    }
  else
    {

      ret = _gnutls_hash_init (&hd, algo);
      if (ret < 0)
        {
          gnutls_assert ();
          return ret;
        }

      _gnutls_hash (&hd, text->data, text->size);
      _gnutls_hash_deinit (&hd, _digest);

      digest.data = _digest;
      digest.size = _gnutls_hash_get_algo_len(algo);
    }

  ret = _gnutls_dsa_verify (&digest, signature, params, params_len);

  return ret;
}
예제 #17
0
파일: sign.c 프로젝트: Chronic-Dev/gnutls
/* if hash==MD5 then we do RSA-MD5
 * if hash==SHA then we do RSA-SHA
 * params[0] is modulus
 * params[1] is public key
 */
static int
pkcs1_rsa_sign (gnutls_digest_algorithm_t hash, const gnutls_datum_t * text,
		bigint_t * params, int params_len, gnutls_datum_t * signature)
{
  int ret;
  opaque _digest[MAX_HASH_SIZE];
  digest_hd_st hd;
  gnutls_datum_t digest, info;

  ret = _gnutls_hash_init (&hd, HASH2MAC (hash));
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  _gnutls_hash (&hd, text->data, text->size);
  _gnutls_hash_deinit (&hd, _digest);

  digest.data = _digest;
  digest.size = _gnutls_hash_get_algo_len (HASH2MAC (hash));

  /* Encode the digest as a DigestInfo
   */
  if ((ret = encode_ber_digest_info (hash, &digest, &info)) != 0)
    {
      gnutls_assert ();
      return ret;
    }

  if ((ret =
       _gnutls_sign (GNUTLS_PK_RSA, params, params_len, &info,
		     signature)) < 0)
    {
      gnutls_assert ();
      _gnutls_free_datum (&info);
      return ret;
    }

  _gnutls_free_datum (&info);

  return 0;
}
예제 #18
0
파일: hash.c 프로젝트: ares89/vlc
static cdk_error_t
hash_encode (void *data, FILE * in, FILE * out)
{
  md_filter_t *mfx = data;
  byte buf[BUFSIZE];
  int err;
  int nread;

  if (!mfx)
    {
      gnutls_assert ();
      return CDK_Inv_Value;
    }

  _cdk_log_debug ("hash filter: encode algo=%d\n", mfx->digest_algo);

  if (!mfx->md_initialized)
    {
      err = _gnutls_hash_init (&mfx->md, mfx->digest_algo);
      if (err < 0)
        {
          gnutls_assert ();
          return map_gnutls_error (err);
        }

      mfx->md_initialized = 1;
    }

  while (!feof (in))
    {
      nread = fread (buf, 1, BUFSIZE, in);
      if (!nread)
        break;
      _gnutls_hash (&mfx->md, buf, nread);
    }

  wipemem (buf, sizeof (buf));
  return 0;
}
예제 #19
0
파일: gnutls_sig.c 프로젝트: bf4/pidgin-mac
/* Generates a signature of all the random data and the parameters.
 * Used in DHE_* ciphersuites.
 */
int
_gnutls_tls_sign_params (gnutls_session_t session, gnutls_cert * cert,
			 gnutls_privkey * pkey, gnutls_datum_t * params,
			 gnutls_datum_t * signature)
{
  gnutls_datum_t dconcat;
  int ret;
  digest_hd_st td_sha;
  opaque concat[36];
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);

  ret = _gnutls_hash_init (&td_sha, GNUTLS_MAC_SHA1);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  _gnutls_hash (&td_sha, session->security_parameters.client_random,
		GNUTLS_RANDOM_SIZE);
  _gnutls_hash (&td_sha, session->security_parameters.server_random,
		GNUTLS_RANDOM_SIZE);
  _gnutls_hash (&td_sha, params->data, params->size);

  switch (cert->subject_pk_algorithm)
    {
    case GNUTLS_PK_RSA:
      if (ver < GNUTLS_TLS1_2)
	{
	  digest_hd_st td_md5;

	  ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5);
	  if (ret < 0)
	    {
	      gnutls_assert ();
	      return ret;
	    }

	  _gnutls_hash (&td_md5, session->security_parameters.client_random,
			GNUTLS_RANDOM_SIZE);
	  _gnutls_hash (&td_md5, session->security_parameters.server_random,
			GNUTLS_RANDOM_SIZE);
	  _gnutls_hash (&td_md5, params->data, params->size);

	  _gnutls_hash_deinit (&td_md5, concat);
	  _gnutls_hash_deinit (&td_sha, &concat[16]);

	  dconcat.size = 36;
	}
      else
	{
#if 1
	  /* Use NULL parameters. */
	  memcpy (concat,
		  "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14",
		  15);
	  _gnutls_hash_deinit (&td_sha, &concat[15]);
	  dconcat.size = 35;
#else
	  /* No parameters field. */
	  memcpy (concat,
		  "\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14", 13);
	  _gnutls_hash_deinit (&td_sha, &concat[13]);
	  dconcat.size = 33;
#endif
	}
      dconcat.data = concat;
      break;
    case GNUTLS_PK_DSA:
      _gnutls_hash_deinit (&td_sha, concat);
      dconcat.data = concat;
      dconcat.size = 20;
      break;

    default:
      gnutls_assert ();
      _gnutls_hash_deinit (&td_sha, NULL);
      return GNUTLS_E_INTERNAL_ERROR;
    }
  ret = _gnutls_tls_sign (session, cert, pkey, &dconcat, signature);
  if (ret < 0)
    {
      gnutls_assert ();
    }

  return ret;

}
예제 #20
0
void
RIPEMD160_Update (RIPEMD160_CTX * ctx, const void *buf, int len)
{
  _gnutls_hash (ctx->handle, buf, len);
}
예제 #21
0
void
MD5_Update (MD5_CTX * ctx, const void *buf, int len)
{
  _gnutls_hash (ctx->handle, buf, len);
}
예제 #22
0
/* ID should be:
 * 3 for MAC
 * 2 for IV
 * 1 for encryption key
 */
int
_gnutls_pkcs12_string_to_key (unsigned int id, const opaque * salt,
			      unsigned int salt_size, unsigned int iter,
			      const char *pw, unsigned int req_keylen,
			      opaque * keybuf)
{
  int rc;
  unsigned int i, j;
  digest_hd_st md;
  bigint_t num_b1 = NULL, num_ij = NULL;
  bigint_t mpi512 = NULL;
  unsigned int pwlen;
  opaque hash[20], buf_b[64], buf_i[128], *p;
  size_t cur_keylen;
  size_t n;
  const opaque buf_512[] =	/* 2^64 */
  { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  };

  cur_keylen = 0;

  if (pw == NULL)
    pwlen = 0;
  else
    pwlen = strlen (pw);

  if (pwlen > 63 / 2)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if ((rc = _pkcs12_check_pass (pw, pwlen)) < 0)
    {
      gnutls_assert ();
      return rc;
    }

  rc = _gnutls_mpi_scan (&mpi512, buf_512, sizeof (buf_512));
  if (rc < 0)
    {
      gnutls_assert ();
      return rc;
    }

  /* Store salt and password in BUF_I */
  p = buf_i;
  for (i = 0; i < 64; i++)
    *p++ = salt[i % salt_size];
  if (pw)
    {
      for (i = j = 0; i < 64; i += 2)
	{
	  *p++ = 0;
	  *p++ = pw[j];
	  if (++j > pwlen)	/* Note, that we include the trailing zero */
	    j = 0;
	}
    }
  else
    memset (p, 0, 64);

  for (;;)
    {
      rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1);
      if (rc < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}
      for (i = 0; i < 64; i++)
	{
	  unsigned char lid = id & 0xFF;
	  _gnutls_hash (&md, &lid, 1);
	}
      _gnutls_hash (&md, buf_i, pw ? 128 : 64);
      _gnutls_hash_deinit (&md, hash);
      for (i = 1; i < iter; i++)
	{
	  rc = _gnutls_hash_init (&md, GNUTLS_MAC_SHA1);
	  if (rc < 0)
	    {
	      gnutls_assert ();
	      goto cleanup;
	    }
	  _gnutls_hash (&md, hash, 20);
	  _gnutls_hash_deinit (&md, hash);
	}
      for (i = 0; i < 20 && cur_keylen < req_keylen; i++)
	keybuf[cur_keylen++] = hash[i];
      if (cur_keylen == req_keylen)
	{
	  rc = 0;		/* ready */
	  goto cleanup;
	}

      /* need more bytes. */
      for (i = 0; i < 64; i++)
	buf_b[i] = hash[i % 20];
      n = 64;
      rc = _gnutls_mpi_scan (&num_b1, buf_b, n);
      if (rc < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}
      _gnutls_mpi_add_ui (num_b1, num_b1, 1);
      for (i = 0; i < 128; i += 64)
	{
	  n = 64;
	  rc = _gnutls_mpi_scan (&num_ij, buf_i + i, n);
	  if (rc < 0)
	    {
	      gnutls_assert ();
	      goto cleanup;
	    }
	  _gnutls_mpi_addm (num_ij, num_ij, num_b1, mpi512);
	  n = 64;
	  rc = _gnutls_mpi_print (num_ij, buf_i + i, &n);
	  if (rc < 0)
	    {
	      gnutls_assert ();
	      goto cleanup;
	    }
	  _gnutls_mpi_release (&num_ij);
	}
    }
cleanup:
  _gnutls_mpi_release (&num_ij);
  _gnutls_mpi_release (&num_b1);
  _gnutls_mpi_release (&mpi512);

  return rc;
}
예제 #23
0
/**
  * gnutls_x509_privkey_get_key_id - Return unique ID of the key's parameters
  * @key: Holds the key
  * @flags: should be 0 for now
  * @output_data: will contain the key ID
  * @output_data_size: holds the size of output_data (and will be
  *   replaced by the actual size of parameters)
  *
  * This function will return a unique ID the depends on the public key
  * parameters. This ID can be used in checking whether a certificate
  * corresponds to the given key.
  *
  * If the buffer provided is not long enough to hold the output, then
  * *output_data_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will
  * be returned.  The output will normally be a SHA-1 hash output,
  * which is 20 bytes.
  *
  * Return value: In case of failure a negative value will be
  *   returned, and 0 on success.
  *
  **/
int
gnutls_x509_privkey_get_key_id (gnutls_x509_privkey_t key,
				unsigned int flags,
				unsigned char *output_data,
				size_t * output_data_size)
{
  int result;
  GNUTLS_HASH_HANDLE hd;
  gnutls_datum_t der = { NULL, 0 };

  if (key == NULL || key->crippled)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if (*output_data_size < 20)
    {
      gnutls_assert ();
      *output_data_size = 20;
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
    }

  if (key->pk_algorithm == GNUTLS_PK_RSA)
    {
      result =
	_gnutls_x509_write_rsa_params (key->params, key->params_size, &der);
      if (result < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}
    }
  else if (key->pk_algorithm == GNUTLS_PK_DSA)
    {
      result =
	_gnutls_x509_write_dsa_public_key (key->params,
					   key->params_size, &der);
      if (result < 0)
	{
	  gnutls_assert ();
	  goto cleanup;
	}
    }
  else
    return GNUTLS_E_INTERNAL_ERROR;

  hd = _gnutls_hash_init (GNUTLS_MAC_SHA1);
  if (hd == GNUTLS_HASH_FAILED)
    {
      gnutls_assert ();
      result = GNUTLS_E_INTERNAL_ERROR;
      goto cleanup;
    }

  _gnutls_hash (hd, der.data, der.size);

  _gnutls_hash_deinit (hd, output_data);
  *output_data_size = 20;

  result = 0;

cleanup:

  _gnutls_free_datum (&der);
  return result;
}
예제 #24
0
/* ID should be:
 * 3 for MAC
 * 2 for IV
 * 1 for encryption key
 *
 * Note that this function produces different key for the
 * NULL password, and for the password with zero length.
 */
int
_gnutls_pkcs12_string_to_key(const mac_entry_st * me,
			     unsigned int id, const uint8_t * salt,
			     unsigned int salt_size, unsigned int iter,
			     const char *pw, unsigned int req_keylen,
			     uint8_t * keybuf)
{
	int rc;
	unsigned int i, j;
	digest_hd_st md;
	bigint_t num_b1 = NULL, num_ij = NULL;
	bigint_t mpi512 = NULL;
	unsigned int pwlen;
	uint8_t hash[MAX_HASH_SIZE], buf_b[64], buf_i[MAX_PASS_LEN * 2 + 64], *p;
	uint8_t d[64];
	size_t cur_keylen;
	size_t n, m, p_size, i_size;
	unsigned mac_len;
	const uint8_t buf_512[] =	/* 2^64 */
	{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x00, 0x00
	};

	cur_keylen = 0;

	if (pw == NULL)
		pwlen = 0;
	else
		pwlen = strlen(pw);

	if (pwlen > MAX_PASS_LEN) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	if ((rc = _pkcs12_check_pass(pw, pwlen)) < 0) {
		gnutls_assert();
		return rc;
	}

	rc = _gnutls_mpi_init_scan(&mpi512, buf_512, sizeof(buf_512));
	if (rc < 0) {
		gnutls_assert();
		return rc;
	}

	/* Store salt and password in BUF_I */
	p_size = ((pwlen / 64) * 64) + 64;

	if (p_size > sizeof(buf_i) - 64)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	p = buf_i;
	for (i = 0; i < 64; i++)
		*p++ = salt[i % salt_size];
	if (pw) {
		for (i = j = 0; i < p_size; i += 2) {
			*p++ = 0;
			*p++ = pw[j];
			if (++j > pwlen)	/* Note, that we include the trailing (0) */
				j = 0;
		}
	} else
		memset(p, 0, p_size);

	i_size = 64 + p_size;
	mac_len = _gnutls_mac_get_algo_len(me);

	for (;;) {
		rc = _gnutls_hash_init(&md, me);
		if (rc < 0) {
			gnutls_assert();
			goto cleanup;
		}
		memset(d, id & 0xff, 64);
		_gnutls_hash(&md, d, 64);
		_gnutls_hash(&md, buf_i, pw ? i_size : 64);
		_gnutls_hash_deinit(&md, hash);
		for (i = 1; i < iter; i++) {
			rc = _gnutls_hash_fast(me->id, hash, mac_len,
					       hash);
			if (rc < 0) {
				gnutls_assert();
				goto cleanup;
			}
		}
		for (i = 0; i < mac_len && cur_keylen < req_keylen; i++)
			keybuf[cur_keylen++] = hash[i];
		if (cur_keylen == req_keylen) {
			rc = 0;	/* ready */
			goto cleanup;
		}

		/* need more bytes. */
		for (i = 0; i < 64; i++)
			buf_b[i] = hash[i % mac_len];
		n = 64;
		rc = _gnutls_mpi_init_scan(&num_b1, buf_b, n);
		if (rc < 0) {
			gnutls_assert();
			goto cleanup;
		}

		rc = _gnutls_mpi_add_ui(num_b1, num_b1, 1);
		if (rc < 0) {
			gnutls_assert();
			goto cleanup;
		}
		
		for (i = 0; i < 128; i += 64) {
			n = 64;
			rc = _gnutls_mpi_init_scan(&num_ij, buf_i + i, n);
			if (rc < 0) {
				gnutls_assert();
				goto cleanup;
			}

			rc = _gnutls_mpi_addm(num_ij, num_ij, num_b1, mpi512);
			if (rc < 0) {
				gnutls_assert();
				goto cleanup;
			}

			n = 64;
#ifndef PKCS12_BROKEN_KEYGEN
			m = (_gnutls_mpi_get_nbits(num_ij) + 7) / 8;
#else
			m = n;
#endif
			memset(buf_i + i, 0, n - m);
			rc = _gnutls_mpi_print(num_ij, buf_i + i + n - m,
					       &n);
			if (rc < 0) {
				gnutls_assert();
				goto cleanup;
			}
			_gnutls_mpi_release(&num_ij);
		}
	}
      cleanup:
	_gnutls_mpi_release(&num_ij);
	_gnutls_mpi_release(&num_b1);
	_gnutls_mpi_release(&mpi512);

	return rc;
}
예제 #25
0
/* Generates a signature of all the previous sent packets in the 
 * handshake procedure. 
 * 20040227: now it works for SSL 3.0 as well
 * 20091031: works for TLS 1.2 too!
 *
 * For TLS1.x, x<2 returns negative for failure and zero or unspecified for success.
 * For TLS1.2 returns the signature algorithm used on success, or a negative error code;
 */
int
_gnutls_handshake_sign_crt_vrfy(gnutls_session_t session,
				gnutls_pcert_st * cert,
				gnutls_privkey_t pkey,
				gnutls_datum_t * signature)
{
	gnutls_datum_t dconcat;
	int ret;
	uint8_t concat[MAX_SIG_SIZE];
	digest_hd_st td_md5;
	digest_hd_st td_sha;
	const version_entry_st *ver = get_version(session);
	gnutls_pk_algorithm_t pk =
	    gnutls_privkey_get_pk_algorithm(pkey, NULL);

	if (unlikely(ver == NULL))
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	if (_gnutls_version_has_selectable_sighash(ver))
		return _gnutls_handshake_sign_crt_vrfy12(session, cert,
							 pkey, signature);

	ret = _gnutls_hash_init(&td_sha, hash_to_entry(GNUTLS_DIG_SHA1));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_hash(&td_sha,
		     session->internals.handshake_hash_buffer.data,
		     session->internals.handshake_hash_buffer.length);

	if (ver->id == GNUTLS_SSL3) {
		ret = _gnutls_generate_master(session, 1);
		if (ret < 0) {
			gnutls_assert();
			_gnutls_hash_deinit(&td_sha, NULL);
			return ret;
		}

		ret =
		    _gnutls_mac_deinit_ssl3_handshake(&td_sha, &concat[16],
						      session->security_parameters.
						      master_secret,
						      GNUTLS_MASTER_SIZE);
		if (ret < 0)
			return gnutls_assert_val(ret);
	} else
		_gnutls_hash_deinit(&td_sha, &concat[16]);

	/* ensure 1024 bit DSA keys are used */
	ret =
	    _gnutls_pubkey_compatible_with_sig(session, cert->pubkey, ver,
					       GNUTLS_SIGN_UNKNOWN);
	if (ret < 0)
		return gnutls_assert_val(ret);

	switch (pk) {
	case GNUTLS_PK_RSA:
		ret =
		    _gnutls_hash_init(&td_md5,
				      hash_to_entry(GNUTLS_DIG_MD5));
		if (ret < 0)
			return gnutls_assert_val(ret);

		_gnutls_hash(&td_md5,
			     session->internals.handshake_hash_buffer.data,
			     session->internals.handshake_hash_buffer.
			     length);

		if (ver->id == GNUTLS_SSL3) {
			ret =
			    _gnutls_mac_deinit_ssl3_handshake(&td_md5,
							      concat,
							      session->security_parameters.
							      master_secret,
							      GNUTLS_MASTER_SIZE);
			if (ret < 0)
				return gnutls_assert_val(ret);
		} else
			_gnutls_hash_deinit(&td_md5, concat);

		dconcat.data = concat;
		dconcat.size = 36;
		break;
	case GNUTLS_PK_DSA:
	case GNUTLS_PK_EC:

		dconcat.data = &concat[16];
		dconcat.size = 20;
		break;

	default:
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
	}
	ret =
	    sign_tls_hash(session, NULL, cert, pkey, &dconcat, signature);
	if (ret < 0) {
		gnutls_assert();
	}

	return ret;
}
예제 #26
0
파일: verify.c 프로젝트: dezelin/maily
/* if hash==MD5 then we do RSA-MD5
 * if hash==SHA then we do RSA-SHA
 * params[0] is modulus
 * params[1] is public key
 */
static int
_pkcs1_rsa_verify_sig (const gnutls_datum_t * text,
                       const gnutls_datum_t * prehash,
                       const gnutls_datum_t * signature, bigint_t * params,
                       int params_len)
{
  gnutls_mac_algorithm_t hash = GNUTLS_MAC_UNKNOWN;
  int ret;
  opaque digest[MAX_HASH_SIZE], md[MAX_HASH_SIZE], *cmp;
  int digest_size;
  digest_hd_st hd;
  gnutls_datum_t decrypted;

  ret =
    _gnutls_pkcs1_rsa_decrypt (&decrypted, signature, params, params_len, 1);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  /* decrypted is a BER encoded data of type DigestInfo
   */

  digest_size = sizeof (digest);
  if ((ret =
       decode_ber_digest_info (&decrypted, &hash, digest, &digest_size)) != 0)
    {
      gnutls_assert ();
      _gnutls_free_datum (&decrypted);
      return ret;
    }

  _gnutls_free_datum (&decrypted);

  if (digest_size != _gnutls_hash_get_algo_len (hash))
    {
      gnutls_assert ();
      return GNUTLS_E_ASN1_GENERIC_ERROR;
    }

  if (prehash && prehash->data && prehash->size == digest_size)
    {
      cmp = prehash->data;
    }
  else
    {
      if (!text)
        {
          gnutls_assert ();
          return GNUTLS_E_INVALID_REQUEST;
        }

      ret = _gnutls_hash_init (&hd, hash);
      if (ret < 0)
        {
          gnutls_assert ();
          return ret;
        }

      _gnutls_hash (&hd, text->data, text->size);
      _gnutls_hash_deinit (&hd, md);

      cmp = md;
    }

  if (memcmp (cmp, digest, digest_size) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_PK_SIG_VERIFY_FAILED;
    }

  return 0;
}
예제 #27
0
파일: literal.c 프로젝트: nobled/gnutls
static cdk_error_t
literal_decode (void *data, FILE * in, FILE * out)
{
  literal_filter_t *pfx = data;
  cdk_stream_t si, so;
  cdk_packet_t pkt;
  cdk_pkt_literal_t pt;
  byte buf[BUFSIZE];
  ssize_t nread;
  int bufsize;
  cdk_error_t rc;

  _cdk_log_debug ("literal filter: decode\n");

  if (!pfx || !in || !out)
    return CDK_Inv_Value;

  rc = _cdk_stream_fpopen (in, STREAMCTL_READ, &si);
  if (rc)
    return rc;

  cdk_pkt_new (&pkt);
  rc = cdk_pkt_read (si, pkt);
  if (rc || pkt->pkttype != CDK_PKT_LITERAL)
    {
      cdk_pkt_release (pkt);
      cdk_stream_close (si);
      return !rc ? CDK_Inv_Packet : rc;
    }

  rc = _cdk_stream_fpopen (out, STREAMCTL_WRITE, &so);
  if (rc)
    {
      cdk_pkt_release (pkt);
      cdk_stream_close (si);
      return rc;
    }

  pt = pkt->pkt.literal;
  pfx->mode = pt->mode;

  if (pfx->filename && pt->namelen > 0)
    {
      /* The name in the literal packet is more authorative. */
      cdk_free (pfx->filename);
      pfx->filename = dup_trim_filename (pt->name);
    }
  else if (!pfx->filename && pt->namelen > 0)
    pfx->filename = dup_trim_filename (pt->name);
  else if (!pt->namelen && !pfx->filename && pfx->orig_filename)
    {
      /* In this case, we need to derrive the output file name
         from the original name and cut off the OpenPGP extension.
         If this is not possible, we return an error. */
      if (!stristr (pfx->orig_filename, ".gpg") &&
          !stristr (pfx->orig_filename, ".pgp") &&
          !stristr (pfx->orig_filename, ".asc"))
        {
          cdk_pkt_release (pkt);
          cdk_stream_close (si);
          cdk_stream_close (so);
          _cdk_log_debug
            ("literal filter: no file name and no PGP extension\n");
          return CDK_Inv_Mode;
        }
      _cdk_log_debug ("literal filter: derrive file name from original\n");
      pfx->filename = dup_trim_filename (pfx->orig_filename);
      pfx->filename[strlen (pfx->filename) - 4] = '\0';
    }

  while (!feof (in))
    {
      _cdk_log_debug ("literal_decode: part on %d size %lu\n",
                      (int) pfx->blkmode.on, (unsigned long)pfx->blkmode.size);
      if (pfx->blkmode.on)
        bufsize = pfx->blkmode.size;
      else
        bufsize = pt->len < DIM (buf) ? pt->len : DIM (buf);
      nread = cdk_stream_read (pt->buf, buf, bufsize);
      if (nread == EOF)
        {
          rc = CDK_File_Error;
          break;
        }
      if (pfx->md_initialized)
        _gnutls_hash (&pfx->md, buf, nread);
      cdk_stream_write (so, buf, nread);
      pt->len -= nread;
      if (pfx->blkmode.on)
        {
          pfx->blkmode.size = _cdk_pkt_read_len (in, &pfx->blkmode.on);
          if ((ssize_t) pfx->blkmode.size == EOF)
            return CDK_Inv_Packet;
        }
      if (pt->len <= 0 && !pfx->blkmode.on)
        break;
    }

  cdk_stream_close (si);
  cdk_stream_close (so);
  cdk_pkt_release (pkt);
  return rc;
}
예제 #28
0
파일: gnutls_sig.c 프로젝트: bf4/pidgin-mac
/* Generates a signature of all the random data and the parameters.
 * Used in DHE_* ciphersuites.
 */
int
_gnutls_verify_sig_params (gnutls_session_t session, gnutls_cert * cert,
			   const gnutls_datum_t * params,
			   gnutls_datum_t * signature)
{
  gnutls_datum_t dconcat;
  int ret;
  digest_hd_st td_md5;
  digest_hd_st td_sha;
  opaque concat[36];
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);

  if (ver < GNUTLS_TLS1_2)
    {
      ret = _gnutls_hash_init (&td_md5, GNUTLS_MAC_MD5);
      if (ret < 0)
	{
	  gnutls_assert ();
	  return ret;
	}

      _gnutls_hash (&td_md5, session->security_parameters.client_random,
		    GNUTLS_RANDOM_SIZE);
      _gnutls_hash (&td_md5, session->security_parameters.server_random,
		    GNUTLS_RANDOM_SIZE);
      _gnutls_hash (&td_md5, params->data, params->size);
    }

  ret = _gnutls_hash_init (&td_sha, GNUTLS_MAC_SHA1);
  if (ret < 0)
    {
      gnutls_assert ();
      if (ver < GNUTLS_TLS1_2)
	_gnutls_hash_deinit (&td_md5, NULL);
      return ret;
    }

  _gnutls_hash (&td_sha, session->security_parameters.client_random,
		GNUTLS_RANDOM_SIZE);
  _gnutls_hash (&td_sha, session->security_parameters.server_random,
		GNUTLS_RANDOM_SIZE);
  _gnutls_hash (&td_sha, params->data, params->size);

  if (ver < GNUTLS_TLS1_2)
    {
      _gnutls_hash_deinit (&td_md5, concat);
      _gnutls_hash_deinit (&td_sha, &concat[16]);
      dconcat.size = 36;
    }
  else
    {
#if 1
      /* Use NULL parameters. */
      memcpy (concat,
	      "\x30\x21\x30\x09\x06\x05\x2b\x0e\x03\x02\x1a\x05\x00\x04\x14",
	      15);
      _gnutls_hash_deinit (&td_sha, &concat[15]);
      dconcat.size = 35;
#else
      /* No parameters field. */
      memcpy (concat,
	      "\x30\x1f\x30\x07\x06\x05\x2b\x0e\x03\x02\x1a\x04\x14", 13);
      _gnutls_hash_deinit (&td_sha, &concat[13]);
      dconcat.size = 33;
#endif
    }

  dconcat.data = concat;

  ret = _gnutls_verify_sig (cert, &dconcat, signature, dconcat.size - 20);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return ret;

}
예제 #29
0
파일: verify.c 프로젝트: Chronic-Dev/gnutls
static cdk_error_t
file_verify_clearsign (cdk_ctx_t hd, const char *file, const char *output)
{
  cdk_stream_t inp = NULL, out = NULL, tmp = NULL;
  digest_hd_st md;
  char buf[512], chk[512];
  const char *s;
  int i, is_signed = 0, nbytes;
  int digest_algo = 0;
  int err;
  cdk_error_t rc;

  memset(&md, 0, sizeof(md));

  if (output)
    {
      rc = cdk_stream_create (output, &out);
      if (rc)
	return rc;
    }

  rc = cdk_stream_open (file, &inp);
  if (rc)
    {
      if (output)
	cdk_stream_close (out);
      return rc;
    }

  s = "-----BEGIN PGP SIGNED MESSAGE-----";
  while (!cdk_stream_eof (inp))
    {
      nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1);
      if (!nbytes || nbytes == -1)
	break;
      if (!strncmp (buf, s, strlen (s)))
	{
	  is_signed = 1;
	  break;
	}
    }

  if (cdk_stream_eof (inp) && !is_signed)
    {
      rc = CDK_Armor_Error;
      goto leave;
    }

  while (!cdk_stream_eof (inp))
    {
      nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1);
      if (!nbytes || nbytes == -1)
	break;
      if (nbytes == 1)		/* Empty line */
	break;
      else if (!strncmp (buf, "Hash: ", 6))
	{
	  for (i = 0; digest_table[i].name; i++)
	    {
	      if (!strcmp (buf + 6, digest_table[i].name))
		{
		  digest_algo = digest_table[i].algo;
		  break;
		}
	    }
	}
    }

  if (digest_algo && _gnutls_hash_get_algo_len (digest_algo) <= 0)
    {
      rc = CDK_Inv_Algo;
      goto leave;
    }

  if (!digest_algo)
    digest_algo = GNUTLS_DIG_MD5;

  err = _gnutls_hash_init (&md, digest_algo);
  if (err < 0)
    {
      rc = map_gnutls_error (err);
      goto leave;
    }

  s = "-----BEGIN PGP SIGNATURE-----";
  while (!cdk_stream_eof (inp))
    {
      nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1);
      if (!nbytes || nbytes == -1)
	break;
      if (!strncmp (buf, s, strlen (s)))
	break;
      else
	{
	  cdk_stream_peek (inp, (byte *) chk, DIM (chk) - 1);
	  i = strncmp (chk, s, strlen (s));
	  if (strlen (buf) == 0 && i == 0)
	    continue;		/* skip last '\n' */
	  _cdk_trim_string (buf, i == 0 ? 0 : 1);
	  _gnutls_hash (&md, buf, strlen (buf));
	}
      if (!strncmp (buf, "- ", 2))	/* FIXME: handle it recursive. */
	memmove (buf, buf + 2, nbytes - 2);
      if (out)
	{
	  if (strstr (buf, "\r\n"))
	    buf[strlen (buf) - 2] = '\0';
	  cdk_stream_write (out, buf, strlen (buf));
	  _cdk_stream_puts (out, _cdk_armor_get_lineend ());
	}
    }

  /* We create a temporary stream object to store the
     signature data in there. */
  rc = cdk_stream_tmp_new (&tmp);
  if (rc)
    goto leave;

  s = "-----BEGIN PGP SIGNATURE-----\n";
  _cdk_stream_puts (tmp, s);
  while (!cdk_stream_eof (inp))
    {
      nbytes = _cdk_stream_gets (inp, buf, DIM (buf) - 1);
      if (!nbytes || nbytes == -1)
	break;
      if (nbytes < (int) (DIM (buf) - 3))
	{
	  buf[nbytes - 1] = '\n';
	  buf[nbytes] = '\0';
	}
      cdk_stream_write (tmp, buf, nbytes);
    }

  /* FIXME: This code is not very elegant. */
  cdk_stream_tmp_set_mode (tmp, STREAMCTL_READ);
  cdk_stream_seek (tmp, 0);
  cdk_stream_set_armor_flag (tmp, 0);
  cdk_stream_read (tmp, NULL, 0);

  /* the digest handle will be closed there. */
  rc = _cdk_proc_packets (hd, tmp, NULL, NULL, NULL, &md);

leave:
  _gnutls_hash_deinit (&md, NULL);
  cdk_stream_close (out);
  cdk_stream_close (tmp);
  cdk_stream_close (inp);
  return rc;
}
예제 #30
0
/* Generates a signature of all the random data and the parameters.
 * Used in DHE_* ciphersuites.
 */
int
_gnutls_handshake_sign_data(gnutls_session_t session,
			    gnutls_pcert_st * cert, gnutls_privkey_t pkey,
			    gnutls_datum_t * params,
			    gnutls_datum_t * signature,
			    gnutls_sign_algorithm_t * sign_algo)
{
	gnutls_datum_t dconcat;
	int ret;
	digest_hd_st td_sha;
	uint8_t concat[MAX_SIG_SIZE];
	const version_entry_st *ver = get_version(session);
	const mac_entry_st *hash_algo;

	*sign_algo = _gnutls_session_get_sign_algo(session, cert);
	if (*sign_algo == GNUTLS_SIGN_UNKNOWN) {
		gnutls_assert();
		return GNUTLS_E_UNKNOWN_PK_ALGORITHM;
	}

	gnutls_sign_algorithm_set_server(session, *sign_algo);

	hash_algo =
	    hash_to_entry(gnutls_sign_get_hash_algorithm(*sign_algo));
	if (hash_algo == NULL)
		return gnutls_assert_val(GNUTLS_E_UNKNOWN_HASH_ALGORITHM);

	_gnutls_handshake_log
	    ("HSK[%p]: signing handshake data: using %s\n", session,
	     gnutls_sign_algorithm_get_name(*sign_algo));

	ret = _gnutls_hash_init(&td_sha, hash_algo);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_hash(&td_sha, session->security_parameters.client_random,
		     GNUTLS_RANDOM_SIZE);
	_gnutls_hash(&td_sha, session->security_parameters.server_random,
		     GNUTLS_RANDOM_SIZE);
	_gnutls_hash(&td_sha, params->data, params->size);

	switch (gnutls_privkey_get_pk_algorithm(pkey, NULL)) {
	case GNUTLS_PK_RSA:
		if (!_gnutls_version_has_selectable_sighash(ver)) {
			digest_hd_st td_md5;

			ret =
			    _gnutls_hash_init(&td_md5,
					      hash_to_entry
					      (GNUTLS_DIG_MD5));
			if (ret < 0) {
				gnutls_assert();
				return ret;
			}

			_gnutls_hash(&td_md5,
				     session->security_parameters.
				     client_random, GNUTLS_RANDOM_SIZE);
			_gnutls_hash(&td_md5,
				     session->security_parameters.
				     server_random, GNUTLS_RANDOM_SIZE);
			_gnutls_hash(&td_md5, params->data, params->size);

			_gnutls_hash_deinit(&td_md5, concat);
			_gnutls_hash_deinit(&td_sha, &concat[16]);

			dconcat.data = concat;
			dconcat.size = 36;
		} else {	/* TLS 1.2 way */

			_gnutls_hash_deinit(&td_sha, concat);

			dconcat.data = concat;
			dconcat.size =
			    _gnutls_hash_get_algo_len(hash_algo);
		}
		break;
	case GNUTLS_PK_DSA:
	case GNUTLS_PK_EC:
		_gnutls_hash_deinit(&td_sha, concat);

		if (!IS_SHA((gnutls_digest_algorithm_t)hash_algo->id)) {
			gnutls_assert();
			return GNUTLS_E_INTERNAL_ERROR;
		}
		dconcat.data = concat;
		dconcat.size = _gnutls_hash_get_algo_len(hash_algo);
		break;

	default:
		gnutls_assert();
		_gnutls_hash_deinit(&td_sha, NULL);
		return GNUTLS_E_INTERNAL_ERROR;
	}

	ret =
	    sign_tls_hash(session, hash_algo, cert, pkey, &dconcat,
			  signature);
	if (ret < 0) {
		gnutls_assert();
	}

	return ret;

}