Ejemplo n.º 1
0
/**
 * cdk_pk_get_fingerprint:
 * @pk: the public key
 * @fpr: the buffer to hold the fingerprint
 *
 * Return the fingerprint of the given public key.
 * The buffer must be at least 20 octets.
 * This function should be considered deprecated and
 * the new cdk_pk_to_fingerprint() should be used whenever
 * possible to avoid overflows.
 **/
cdk_error_t
cdk_pk_get_fingerprint (cdk_pubkey_t pk, byte * fpr)
{
    digest_hd_st hd;
    int md_algo;
    int dlen = 0;
    int err;

    if (!pk || !fpr)
        return CDK_Inv_Value;

    if (pk->version < 4 && is_RSA (pk->pubkey_algo))
        md_algo = GNUTLS_DIG_MD5;   /* special */
    else
        md_algo = GNUTLS_DIG_SHA1;
    dlen = _gnutls_hash_get_algo_len (md_algo);
    err = _gnutls_hash_init (&hd, md_algo);
    if (err < 0)
    {
        gnutls_assert ();
        return map_gnutls_error (err);
    }
    _cdk_hash_pubkey (pk, &hd, 1);
    _gnutls_hash_deinit (&hd, fpr);
    if (dlen == 16)
        memset (fpr + 16, 0, 4);
    return 0;
}
Ejemplo n.º 2
0
int
pk_hash_data(gnutls_pk_algorithm_t pk, const mac_entry_st * hash,
	     gnutls_pk_params_st * params,
	     const gnutls_datum_t * data, gnutls_datum_t * digest)
{
	int ret;

	digest->size = _gnutls_hash_get_algo_len(hash);
	digest->data = gnutls_malloc(digest->size);
	if (digest->data == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	ret =
	    _gnutls_hash_fast((gnutls_digest_algorithm_t)hash->id, data->data, data->size,
			      digest->data);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	return 0;

      cleanup:
	gnutls_free(digest->data);
	return ret;
}
Ejemplo n.º 3
0
/**
 * gnutls_fingerprint:
 * @algo: is a digest algorithm
 * @data: is the data
 * @result: is the place where the result will be copied (may be null).
 * @result_size: should hold the size of the result. The actual size
 * of the returned result will also be copied there.
 *
 * This function will calculate a fingerprint (actually a hash), of
 * the given data.  The result is not printable data.  You should
 * convert it to hex, or to something else printable.
 *
 * This is the usual way to calculate a fingerprint of an X.509 DER
 * encoded certificate.  Note however that the fingerprint of an
 * OpenPGP certificate is not just a hash and cannot be calculated with this
 * function.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
 *   an error code is returned.
 **/
int
gnutls_fingerprint(gnutls_digest_algorithm_t algo,
		   const gnutls_datum_t * data, void *result,
		   size_t * result_size)
{
	int ret;
	int hash_len = _gnutls_hash_get_algo_len(hash_to_entry(algo));

	if (hash_len < 0 || (unsigned) hash_len > *result_size
	    || result == NULL) {
		*result_size = hash_len;
		return GNUTLS_E_SHORT_MEMORY_BUFFER;
	}
	*result_size = hash_len;

	if (result) {
		ret =
		    _gnutls_hash_fast(algo, data->data, data->size,
				      result);
		if (ret < 0)
			return gnutls_assert_val(ret);
	}

	return 0;
}
Ejemplo n.º 4
0
/**
 * cdk_s2k_new:
 * @ret_s2k: output for the new S2K object
 * @mode: the S2K mode (simple, salted, iter+salted)
 * @digest_algo: the hash algorithm
 * @salt: random salt
 * 
 * Create a new S2K object with the given parameter.
 * The @salt parameter must be always 8 octets.
 **/
cdk_error_t
cdk_s2k_new (cdk_s2k_t * ret_s2k, int mode, int digest_algo,
             const byte * salt)
{
  cdk_s2k_t s2k;

  if (!ret_s2k)
    return CDK_Inv_Value;

  if (mode != 0x00 && mode != 0x01 && mode != 0x03)
    return CDK_Inv_Mode;

  if (_gnutls_hash_get_algo_len (digest_algo) <= 0)
    return CDK_Inv_Algo;

  s2k = cdk_calloc (1, sizeof *s2k);
  if (!s2k)
    return CDK_Out_Of_Core;
  s2k->mode = mode;
  s2k->hash_algo = digest_algo;
  if (salt)
    memcpy (s2k->salt, salt, 8);
  *ret_s2k = s2k;
  return 0;
}
Ejemplo n.º 5
0
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;
}
Ejemplo n.º 6
0
/* 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;

    algo = _gnutls_dsa_q_to_hash (params[1]);
    if (hash)
    {
        /* SHA1 or better allowed */
        if (!hash->data || hash->size != _gnutls_hash_get_algo_len(algo))
        {
            gnutls_assert();
            _gnutls_debug_log("Hash size (%d) does not correspond to hash %s", (int)hash->size, gnutls_mac_get_name(algo));
            return GNUTLS_E_INVALID_REQUEST;
        }
        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;
}
Ejemplo n.º 7
0
/* this is _gnutls_handshake_verify_cert_vrfy for TLS 1.2
 */
static int
_gnutls_handshake_verify_cert_vrfy12 (gnutls_session_t session,
                                      gnutls_pcert_st*  cert,
                                      gnutls_datum_t * signature,
                                      gnutls_sign_algorithm_t sign_algo)
{
  int ret;
  opaque concat[MAX_SIG_SIZE];
  digest_hd_st td;
  gnutls_datum_t dconcat;
  gnutls_sign_algorithm_t _sign_algo;
  gnutls_digest_algorithm_t hash_algo;
  digest_hd_st *handshake_td;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);
  gnutls_pk_algorithm_t pk = gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);

  handshake_td = &session->internals.handshake_mac_handle.tls12.sha1;
  hash_algo = handshake_td->algorithm;
  _sign_algo =
    _gnutls_x509_pk_to_sign (pk, hash_algo);

  if (_sign_algo != sign_algo)
    {
      handshake_td = &session->internals.handshake_mac_handle.tls12.sha256;
      hash_algo = handshake_td->algorithm;
      _sign_algo =
        _gnutls_x509_pk_to_sign (pk, hash_algo);
      if (sign_algo != _sign_algo)
        {
          gnutls_assert ();
          return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM;
        }
    }

  ret = _gnutls_hash_copy (&td, handshake_td);
  if (ret < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_HASH_FAILED;
    }

  _gnutls_hash_deinit (&td, concat);

  dconcat.data = concat;
  dconcat.size = _gnutls_hash_get_algo_len (hash_algo);

  ret =
    verify_tls_hash (ver, cert, &dconcat, signature, 0, pk);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return ret;

}
Ejemplo n.º 8
0
int
_gnutls_epoch_set_keys (gnutls_session_t session, uint16_t epoch)
{
  int hash_size;
  int IV_size;
  int key_size, export_flag;
  gnutls_cipher_algorithm_t cipher_algo;
  gnutls_mac_algorithm_t mac_algo;
  gnutls_compression_method_t comp_algo;
  record_parameters_st *params;
  int ret;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);

  ret = _gnutls_epoch_get (session, epoch, &params);
  if (ret < 0)
    return gnutls_assert_val (ret);

  if (params->initialized)
    return 0;

  _gnutls_record_log
    ("REC[%p]: Initializing epoch #%u\n", session, params->epoch);

  cipher_algo = params->cipher_algorithm;
  mac_algo = params->mac_algorithm;
  comp_algo = params->compression_algorithm;

  if (_gnutls_cipher_is_ok (cipher_algo) != 0
      || _gnutls_mac_is_ok (mac_algo) != 0)
    return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR);

  if (_gnutls_compression_is_ok (comp_algo) != 0)
    return gnutls_assert_val (GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM);

  IV_size = _gnutls_cipher_get_iv_size (cipher_algo);
  key_size = gnutls_cipher_get_key_size (cipher_algo);
  export_flag = _gnutls_cipher_get_export_flag (cipher_algo);
  hash_size = _gnutls_hash_get_algo_len (mac_algo);

  ret = _gnutls_set_keys
    (session, params, hash_size, IV_size, key_size, export_flag);
  if (ret < 0)
    return gnutls_assert_val (ret);

  ret = _gnutls_init_record_state (params, ver, 1, &params->read);
  if (ret < 0)
    return gnutls_assert_val (ret);

  ret = _gnutls_init_record_state (params, ver, 0, &params->write);
  if (ret < 0)
    return gnutls_assert_val (ret);

  _gnutls_record_log ("REC[%p]: Epoch #%u ready\n", session, params->epoch);

  params->initialized = 1;
  return 0;
}
Ejemplo n.º 9
0
static void
handle_set_digest (cdk_ctx_t hd, int digest)
{
  if (!hd)
    return;
  if (_gnutls_hash_get_algo_len (digest) <= 0)
    digest = DEFAULT_DIGEST_ALGO;
  hd->digest_algo = digest;
}
Ejemplo n.º 10
0
/* the same as _gnutls_handshake_sign_cert_vrfy except that it is made for TLS 1.2
 */
static int
_gnutls_handshake_sign_cert_vrfy12 (gnutls_session_t session,
                                    gnutls_pcert_st* cert, gnutls_privkey_t pkey,
                                    gnutls_datum_t * signature)
{
  gnutls_datum_t dconcat;
  int ret;
  opaque concat[MAX_SIG_SIZE];
  digest_hd_st td;
  gnutls_sign_algorithm_t sign_algo;
  gnutls_digest_algorithm_t hash_algo;
  digest_hd_st *handshake_td;

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

  hash_algo = _gnutls_sign_get_hash_algorithm (sign_algo);

  _gnutls_debug_log ("sign handshake cert vrfy: picked %s with %s\n",
                    gnutls_sign_algorithm_get_name (sign_algo),
                    gnutls_mac_get_name (hash_algo));

  if ((gnutls_mac_algorithm_t)hash_algo == session->internals.handshake_mac_handle.tls12.sha1.algorithm)
    handshake_td = &session->internals.handshake_mac_handle.tls12.sha1;
  else if ((gnutls_mac_algorithm_t)hash_algo == session->internals.handshake_mac_handle.tls12.sha256.algorithm)
    handshake_td = &session->internals.handshake_mac_handle.tls12.sha256;
  else
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); /* too bad we only support SHA1 and SHA256 */

  ret = _gnutls_hash_copy (&td, handshake_td);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  _gnutls_hash_deinit (&td, concat);

  dconcat.data = concat;
  dconcat.size = _gnutls_hash_get_algo_len (hash_algo);

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

  return sign_algo;
}
Ejemplo n.º 11
0
static void
handle_set_s2k (cdk_ctx_t hd, int mode, int digest)
{
  if (!hd)
    return;
  if (_gnutls_hash_get_algo_len (digest) <= 0)
    digest = DEFAULT_DIGEST_ALGO;
  if (mode != CDK_S2K_SIMPLE &&
      mode != CDK_S2K_SALTED && mode != CDK_S2K_ITERSALTED)
    mode = CDK_S2K_ITERSALTED;
  hd->_s2k.mode = mode;
  hd->_s2k.digest_algo = digest;
}
Ejemplo n.º 12
0
/**
 * gnutls_store_commitment:
 * @db_name: A file specifying the stored keys (use NULL for the default)
 * @tdb: A storage structure or NULL to use the default
 * @host: The peer's name
 * @service: non-NULL if this key is specific to a service (e.g. http)
 * @hash_algo: The hash algorithm type
 * @hash: The raw hash
 * @expiration: The expiration time (use 0 to disable expiration)
 * @flags: should be 0.
 *
 * This function will store the provided hash commitment to 
 * the list of stored public keys. The key with the given
 * hash will be considered valid until the provided expiration time.
 *
 * The @store variable if non-null specifies a custom backend for
 * the storage of entries. If it is NULL then the
 * default file backend will be used.
 *
 * Note that this function is not thread safe with the default backend.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 *
 * Since: 3.0
 **/
int
gnutls_store_commitment(const char *db_name,
			gnutls_tdb_t tdb,
			const char *host,
			const char *service,
			gnutls_digest_algorithm_t hash_algo,
			const gnutls_datum_t * hash,
			time_t expiration, unsigned int flags)
{
	FILE *fd = NULL;
	int ret;
	char local_file[MAX_FILENAME];
	const mac_entry_st *me = hash_to_entry(hash_algo);

	if (me == NULL || _gnutls_digest_is_secure(me) == 0)
		return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);

	if (_gnutls_hash_get_algo_len(me) != hash->size)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	if (db_name == NULL && tdb == NULL) {
		ret =
		    _gnutls_find_config_path(local_file,
					     sizeof(local_file));
		if (ret < 0)
			return gnutls_assert_val(ret);

		_gnutls_debug_log("Configuration path: %s\n", local_file);
		mkdir(local_file, 0700);

		ret = find_config_file(local_file, sizeof(local_file));
		if (ret < 0)
			return gnutls_assert_val(ret);
		db_name = local_file;
	}

	if (tdb == NULL)
		tdb = &default_tdb;

	_gnutls_debug_log("Configuration file: %s\n", db_name);

	tdb->cstore(db_name, host, service, expiration, 
		(gnutls_digest_algorithm_t)me->id, hash);

	ret = 0;

	if (fd != NULL)
		fclose(fd);

	return ret;
}
Ejemplo n.º 13
0
/* the same as _gnutls_handshake_sign_crt_vrfy except that it is made for TLS 1.2
 */
static int
_gnutls_handshake_sign_crt_vrfy12(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];
	gnutls_sign_algorithm_t sign_algo;
	const mac_entry_st *me;

	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_client(session, sign_algo);

	me = hash_to_entry(gnutls_sign_get_hash_algorithm(sign_algo));

	_gnutls_debug_log("sign handshake cert vrfy: picked %s with %s\n",
			  gnutls_sign_algorithm_get_name(sign_algo),
			  _gnutls_mac_get_name(me));

	ret =
	    _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id,
			      session->internals.handshake_hash_buffer.
			      data,
			      session->internals.handshake_hash_buffer.
			      length, concat);
	if (ret < 0)
		return gnutls_assert_val(ret);

	dconcat.data = concat;
	dconcat.size = _gnutls_hash_get_algo_len(me);

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

	return sign_algo;
}
Ejemplo n.º 14
0
/* this is _gnutls_handshake_verify_crt_vrfy for TLS 1.2
 */
static int
_gnutls_handshake_verify_crt_vrfy12(gnutls_session_t session,
				    gnutls_pcert_st * cert,
				    gnutls_datum_t * signature,
				    gnutls_sign_algorithm_t sign_algo)
{
	int ret;
	uint8_t concat[MAX_HASH_SIZE];
	gnutls_datum_t dconcat;
	const version_entry_st *ver = get_version(session);
	gnutls_pk_algorithm_t pk =
	    gnutls_pubkey_get_pk_algorithm(cert->pubkey, NULL);
	const mac_entry_st *me;

	ret = _gnutls_session_sign_algo_enabled(session, sign_algo);
	if (ret < 0)
		return gnutls_assert_val(ret);

	gnutls_sign_algorithm_set_client(session, sign_algo);

	me = hash_to_entry(gnutls_sign_get_hash_algorithm(sign_algo));

	ret =
	    _gnutls_hash_fast((gnutls_digest_algorithm_t)me->id,
			      session->internals.handshake_hash_buffer.
			      data,
			      session->internals.
			      handshake_hash_buffer_prev_len, concat);
	if (ret < 0)
		return gnutls_assert_val(ret);

	dconcat.data = concat;
	dconcat.size = _gnutls_hash_get_algo_len(me);

	ret =
	    verify_tls_hash(session, ver, cert, &dconcat, signature, 0,
			    sign_algo, pk);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	return ret;

}
Ejemplo n.º 15
0
int
pk_hash_data (gnutls_pk_algorithm_t pk, gnutls_digest_algorithm_t hash,
              bigint_t * params,
              const gnutls_datum_t * data, gnutls_datum_t * digest)
{
  int ret;

  switch (pk)
    {
    case GNUTLS_PK_RSA:
      break;
    case GNUTLS_PK_DSA:
      if (params && hash != _gnutls_dsa_q_to_hash (params[1]))
        {
          gnutls_assert ();
          return GNUTLS_E_INVALID_REQUEST;
        }
      break;
    default:
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  digest->size = _gnutls_hash_get_algo_len (hash);
  digest->data = gnutls_malloc (digest->size);
  if (digest->data == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  ret = _gnutls_hash_fast (hash, data->data, data->size, digest->data);
  if (ret < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  return 0;

cleanup:
  gnutls_free (digest->data);
  return ret;
}
Ejemplo n.º 16
0
/* 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;
}
Ejemplo n.º 17
0
int
_gnutls_set_write_keys (gnutls_session_t session)
{
  int hash_size;
  int IV_size;
  int key_size, export_flag;
  gnutls_cipher_algorithm_t algo;
  gnutls_mac_algorithm_t mac_algo;

  mac_algo = session->security_parameters.write_mac_algorithm;
  algo = session->security_parameters.write_bulk_cipher_algorithm;

  hash_size = _gnutls_hash_get_algo_len (mac_algo);
  IV_size = _gnutls_cipher_get_iv_size (algo);
  key_size = gnutls_cipher_get_key_size (algo);
  export_flag = _gnutls_cipher_get_export_flag (algo);

  return _gnutls_set_keys (session, hash_size, IV_size, key_size,
			   export_flag);
}
Ejemplo n.º 18
0
/* Encode the given digest into a pkcs#1 compatible format. */
cdk_error_t
_cdk_digest_encode_pkcs1 (byte ** r_md, size_t * r_mdlen, int pk_algo,
                          const byte * md, int digest_algo, unsigned nbits)
{
  size_t dlen;

  if (!md || !r_md || !r_mdlen)
    return CDK_Inv_Value;

  dlen = _gnutls_hash_get_algo_len (digest_algo);
  if (dlen <= 0)
    return CDK_Inv_Algo;
  if (is_DSA (pk_algo))
    {                           /* DSS does not use a special encoding. */
      *r_md = cdk_malloc (dlen + 1);
      if (!*r_md)
        return CDK_Out_Of_Core;
      *r_mdlen = dlen;
      memcpy (*r_md, md, dlen);
      return 0;
    }
  else
    {
      const byte *asn;
      int asnlen;
      cdk_error_t rc;

      asnlen = _gnutls_get_digest_oid (digest_algo, &asn);
      if (asnlen < 0)
        return asnlen;

      rc = do_encode_md (r_md, r_mdlen, md, digest_algo, dlen,
                         nbits, asn, asnlen);
      return rc;
    }
  return 0;
}
Ejemplo n.º 19
0
/* 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;
}
Ejemplo n.º 20
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;

}
Ejemplo n.º 21
0
/* Deciphers the ciphertext packet, and puts the result to compress_data, of compress_size.
 * Returns the actual compressed packet size.
 */
int
_gnutls_ciphertext2compressed (gnutls_session_t session,
                               opaque * compress_data,
                               int compress_size,
                               gnutls_datum_t ciphertext, uint8_t type,
                               record_parameters_st * params)
{
  uint8_t MAC[MAX_HASH_SIZE];
  uint16_t c_length;
  uint8_t pad;
  int length;
  uint16_t blocksize;
  int ret, i, pad_failed = 0;
  opaque preamble[PREAMBLE_SIZE];
  int preamble_size;
  int ver = gnutls_protocol_get_version (session);
  int hash_size = _gnutls_hash_get_algo_len (params->mac_algorithm);

  blocksize = gnutls_cipher_get_block_size (params->cipher_algorithm);


  /* actual decryption (inplace)
   */
  switch (_gnutls_cipher_is_block (params->cipher_algorithm))
    {
    case CIPHER_STREAM:
      if ((ret =
           _gnutls_cipher_decrypt (&params->read.cipher_state,
                                   ciphertext.data, ciphertext.size)) < 0)
        {
          gnutls_assert ();
          return ret;
        }

      length = ciphertext.size - hash_size;

      break;
    case CIPHER_BLOCK:
      if ((ciphertext.size < blocksize) || (ciphertext.size % blocksize != 0))
        {
          gnutls_assert ();
          return GNUTLS_E_DECRYPTION_FAILED;
        }

      if ((ret =
           _gnutls_cipher_decrypt (&params->read.cipher_state,
                                   ciphertext.data, ciphertext.size)) < 0)
        {
          gnutls_assert ();
          return ret;
        }

      /* ignore the IV in TLS 1.1.
       */
      if (_gnutls_version_has_explicit_iv
          (session->security_parameters.version))
        {
          ciphertext.size -= blocksize;
          ciphertext.data += blocksize;

          if (ciphertext.size == 0)
            {
              gnutls_assert ();
              return GNUTLS_E_DECRYPTION_FAILED;
            }
        }

      pad = ciphertext.data[ciphertext.size - 1] + 1;   /* pad */

      if ((int) pad > (int) ciphertext.size - hash_size)
        {
          gnutls_assert ();
          _gnutls_record_log
            ("REC[%p]: Short record length %d > %d - %d (under attack?)\n",
             session, pad, ciphertext.size, hash_size);
          /* We do not fail here. We check below for the
           * the pad_failed. If zero means success.
           */
          pad_failed = GNUTLS_E_DECRYPTION_FAILED;
        }

      length = ciphertext.size - hash_size - pad;

      /* Check the pading bytes (TLS 1.x)
       */
      if (_gnutls_version_has_variable_padding (ver) && pad_failed == 0)
        for (i = 2; i < pad; i++)
          {
            if (ciphertext.data[ciphertext.size - i] !=
                ciphertext.data[ciphertext.size - 1])
              pad_failed = GNUTLS_E_DECRYPTION_FAILED;
          }
      break;
    default:
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  if (length < 0)
    length = 0;
  c_length = _gnutls_conv_uint16 ((uint16_t) length);

  /* Pass the type, version, length and compressed through
   * MAC.
   */
  if (params->mac_algorithm != GNUTLS_MAC_NULL)
    {
      digest_hd_st td;

      ret = mac_init (&td, params->mac_algorithm,
                      params->read.mac_secret.data,
                      params->read.mac_secret.size, ver);

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

      preamble_size =
        make_preamble (UINT64DATA
                       (params->read.sequence_number), type,
                       c_length, ver, preamble);
      mac_hash (&td, preamble, preamble_size, ver);
      if (length > 0)
        mac_hash (&td, ciphertext.data, length, ver);

      mac_deinit (&td, MAC, ver);
    }

  /* This one was introduced to avoid a timing attack against the TLS
   * 1.0 protocol.
   */
  if (pad_failed != 0)
    {
      gnutls_assert ();
      return pad_failed;
    }

  /* HMAC was not the same. 
   */
  if (memcmp (MAC, &ciphertext.data[length], hash_size) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_DECRYPTION_FAILED;
    }

  /* copy the decrypted stuff to compress_data.
   */
  if (compress_size < length)
    {
      gnutls_assert ();
      return GNUTLS_E_DECOMPRESSION_FAILED;
    }
  memcpy (compress_data, ciphertext.data, length);

  return length;
}
Ejemplo n.º 22
0
/* This is the actual encryption 
 * Encrypts the given compressed datum, and puts the result to cipher_data,
 * which has cipher_size size.
 * return the actual encrypted data length.
 */
int
_gnutls_compressed2ciphertext (gnutls_session_t session,
                               opaque * cipher_data, int cipher_size,
                               gnutls_datum_t compressed,
                               content_type_t _type, int random_pad,
                               record_parameters_st * params)
{
  uint8_t MAC[MAX_HASH_SIZE];
  uint16_t c_length;
  uint8_t pad;
  int length, ret;
  uint8_t type = _type;
  opaque preamble[PREAMBLE_SIZE];
  int preamble_size;
  int hash_size = _gnutls_hash_get_algo_len (params->mac_algorithm);
  int blocksize = gnutls_cipher_get_block_size (params->cipher_algorithm);
  cipher_type_t block_algo =
    _gnutls_cipher_is_block (params->cipher_algorithm);
  opaque *data_ptr;
  int ver = gnutls_protocol_get_version (session);


  /* Initialize MAC */

  c_length = _gnutls_conv_uint16 (compressed.size);

  if (params->mac_algorithm != GNUTLS_MAC_NULL)
    {                           /* actually when the algorithm in not the NULL one */
      digest_hd_st td;

      ret = mac_init (&td, params->mac_algorithm,
                      params->write.mac_secret.data,
                      params->write.mac_secret.size, ver);

      if (ret < 0)
        {
          gnutls_assert ();
          return ret;
        }
      preamble_size =
        make_preamble (UINT64DATA
                       (params->write.sequence_number),
                       type, c_length, ver, preamble);
      mac_hash (&td, preamble, preamble_size, ver);
      mac_hash (&td, compressed.data, compressed.size, ver);
      mac_deinit (&td, MAC, ver);
    }


  /* Calculate the encrypted length (padding etc.)
   */
  length =
    calc_enc_length (session, compressed.size, hash_size, &pad,
                     random_pad, block_algo, blocksize);
  if (length < 0)
    {
      gnutls_assert ();
      return length;
    }

  /* copy the encrypted data to cipher_data.
   */
  if (cipher_size < length)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  data_ptr = cipher_data;
  if (block_algo == CIPHER_BLOCK &&
      _gnutls_version_has_explicit_iv (session->security_parameters.version))
    {
      /* copy the random IV.
       */
      ret = _gnutls_rnd (GNUTLS_RND_NONCE, data_ptr, blocksize);
      if (ret < 0)
        {
          gnutls_assert ();
          return ret;
        }

      data_ptr += blocksize;
    }

  memcpy (data_ptr, compressed.data, compressed.size);
  data_ptr += compressed.size;

  if (hash_size > 0)
    {
      memcpy (data_ptr, MAC, hash_size);
      data_ptr += hash_size;
    }
  if (block_algo == CIPHER_BLOCK && pad > 0)
    {
      memset (data_ptr, pad - 1, pad);
    }


  /* Actual encryption (inplace).
   */
  ret =
    _gnutls_cipher_encrypt (&params->write.cipher_state, cipher_data, length);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return length;
}
Ejemplo n.º 23
0
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;
}
Ejemplo n.º 24
0
/* Deciphers the ciphertext packet, and puts the result to compress_data, of compress_size.
 * Returns the actual compressed packet size.
 */
int
_gnutls_ciphertext2compressed (gnutls_session_t session,
			       opaque * compress_data,
			       int compress_size,
			       gnutls_datum_t ciphertext, uint8_t type)
{
  uint8_t MAC[MAX_HASH_SIZE];
  uint16_t c_length;
  uint8_t pad;
  int length;
  digest_hd_st td;
  uint16_t blocksize;
  int ret, i, pad_failed = 0;
  uint8_t major, minor;
  gnutls_protocol_t ver;
  int hash_size =
    _gnutls_hash_get_algo_len (session->security_parameters.
			       read_mac_algorithm);

  ver = gnutls_protocol_get_version (session);
  minor = _gnutls_version_get_minor (ver);
  major = _gnutls_version_get_major (ver);

  blocksize =
    _gnutls_cipher_get_block_size (session->security_parameters.
				   read_bulk_cipher_algorithm);

  /* initialize MAC 
   */
  ret = mac_init (&td, session->security_parameters.read_mac_algorithm,
		  session->connection_state.read_mac_secret.data,
		  session->connection_state.read_mac_secret.size, ver);

  if (ret < 0
      && session->security_parameters.read_mac_algorithm != GNUTLS_MAC_NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  /* actual decryption (inplace)
   */
  switch (_gnutls_cipher_is_block
	  (session->security_parameters.read_bulk_cipher_algorithm))
    {
    case CIPHER_STREAM:
      if ((ret =
	   _gnutls_cipher_decrypt (&session->connection_state.
				   read_cipher_state, ciphertext.data,
				   ciphertext.size)) < 0)
	{
	  gnutls_assert ();
	  return ret;
	}

      length = ciphertext.size - hash_size;

      break;
    case CIPHER_BLOCK:
      if ((ciphertext.size < blocksize) || (ciphertext.size % blocksize != 0))
	{
	  gnutls_assert ();
	  return GNUTLS_E_DECRYPTION_FAILED;
	}

      if ((ret =
	   _gnutls_cipher_decrypt (&session->connection_state.
				   read_cipher_state, ciphertext.data,
				   ciphertext.size)) < 0)
	{
	  gnutls_assert ();
	  return ret;
	}

      /* ignore the IV in TLS 1.1.
       */
      if (session->security_parameters.version >= GNUTLS_TLS1_1)
	{
	  ciphertext.size -= blocksize;
	  ciphertext.data += blocksize;

	  if (ciphertext.size == 0)
	    {
	      gnutls_assert ();
	      return GNUTLS_E_DECRYPTION_FAILED;
	    }
	}

      pad = ciphertext.data[ciphertext.size - 1] + 1;	/* pad */

      if ((int) pad > (int) ciphertext.size - hash_size)
	{
	  gnutls_assert ();
	  _gnutls_record_log
	    ("REC[%x]: Short record length %d > %d - %d (under attack?)\n",
	     session, pad, ciphertext.size, hash_size);
	  /* We do not fail here. We check below for the
	   * the pad_failed. If zero means success.
	   */
	  pad_failed = GNUTLS_E_DECRYPTION_FAILED;
	}

      length = ciphertext.size - hash_size - pad;

      /* Check the pading bytes (TLS 1.x)
       */
      if (ver >= GNUTLS_TLS1 && pad_failed == 0)
	for (i = 2; i < pad; i++)
	  {
	    if (ciphertext.data[ciphertext.size - i] !=
		ciphertext.data[ciphertext.size - 1])
	      pad_failed = GNUTLS_E_DECRYPTION_FAILED;
	  }
      break;
    default:
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  if (length < 0)
    length = 0;
  c_length = _gnutls_conv_uint16 ((uint16_t) length);

  /* Pass the type, version, length and compressed through
   * MAC.
   */
  if (session->security_parameters.read_mac_algorithm != GNUTLS_MAC_NULL)
    {
      _gnutls_hmac (&td,
		    UINT64DATA (session->connection_state.
				read_sequence_number), 8);

      _gnutls_hmac (&td, &type, 1);
      if (ver >= GNUTLS_TLS1)
	{			/* TLS 1.x */
	  _gnutls_hmac (&td, &major, 1);
	  _gnutls_hmac (&td, &minor, 1);
	}
      _gnutls_hmac (&td, &c_length, 2);

      if (length > 0)
	_gnutls_hmac (&td, ciphertext.data, length);

      mac_deinit (&td, MAC, ver);
    }

  /* This one was introduced to avoid a timing attack against the TLS
   * 1.0 protocol.
   */
  if (pad_failed != 0)
    return pad_failed;

  /* HMAC was not the same. 
   */
  if (memcmp (MAC, &ciphertext.data[length], hash_size) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_DECRYPTION_FAILED;
    }

  /* copy the decrypted stuff to compress_data.
   */
  if (compress_size < length)
    {
      gnutls_assert ();
      return GNUTLS_E_DECOMPRESSION_FAILED;
    }
  memcpy (compress_data, ciphertext.data, length);

  return length;
}
Ejemplo n.º 25
0
/* This is the actual encryption 
 * Encrypts the given compressed datum, and puts the result to cipher_data,
 * which has cipher_size size.
 * return the actual encrypted data length.
 */
int
_gnutls_compressed2ciphertext (gnutls_session_t session,
			       opaque * cipher_data, int cipher_size,
			       gnutls_datum_t compressed,
			       content_type_t _type, int random_pad)
{
  uint8_t MAC[MAX_HASH_SIZE];
  uint16_t c_length;
  uint8_t pad;
  int length, ret;
  digest_hd_st td;
  uint8_t type = _type;
  uint8_t major, minor;
  int hash_size =
    _gnutls_hash_get_algo_len (session->security_parameters.
			       write_mac_algorithm);
  gnutls_protocol_t ver;
  int blocksize =
    _gnutls_cipher_get_block_size (session->security_parameters.
				   write_bulk_cipher_algorithm);
  cipher_type_t block_algo =
    _gnutls_cipher_is_block (session->security_parameters.
			     write_bulk_cipher_algorithm);
  opaque *data_ptr;


  ver = gnutls_protocol_get_version (session);
  minor = _gnutls_version_get_minor (ver);
  major = _gnutls_version_get_major (ver);


  /* Initialize MAC */
  ret = mac_init (&td, session->security_parameters.write_mac_algorithm,
		  session->connection_state.write_mac_secret.data,
		  session->connection_state.write_mac_secret.size, ver);

  if (ret < 0
      && session->security_parameters.write_mac_algorithm != GNUTLS_MAC_NULL)
    {
      gnutls_assert ();
      return ret;
    }

  c_length = _gnutls_conv_uint16 (compressed.size);

  if (session->security_parameters.write_mac_algorithm != GNUTLS_MAC_NULL)
    {				/* actually when the algorithm in not the NULL one */
      _gnutls_hmac (&td,
		    UINT64DATA (session->connection_state.
				write_sequence_number), 8);

      _gnutls_hmac (&td, &type, 1);
      if (ver >= GNUTLS_TLS1)
	{			/* TLS 1.0 or higher */
	  _gnutls_hmac (&td, &major, 1);
	  _gnutls_hmac (&td, &minor, 1);
	}
      _gnutls_hmac (&td, &c_length, 2);
      _gnutls_hmac (&td, compressed.data, compressed.size);
      mac_deinit (&td, MAC, ver);
    }


  /* Calculate the encrypted length (padding etc.)
   */
  length =
    calc_enc_length (session, compressed.size, hash_size, &pad,
		     random_pad, block_algo, blocksize);
  if (length < 0)
    {
      gnutls_assert ();
      return length;
    }

  /* copy the encrypted data to cipher_data.
   */
  if (cipher_size < length)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  data_ptr = cipher_data;
  if (block_algo == CIPHER_BLOCK &&
      session->security_parameters.version >= GNUTLS_TLS1_1)
    {
      /* copy the random IV.
       */
      ret = _gnutls_rnd (GNUTLS_RND_NONCE, data_ptr, blocksize);
      if (ret < 0)
	{
	  gnutls_assert ();
	  return ret;
	}

      data_ptr += blocksize;
    }

  memcpy (data_ptr, compressed.data, compressed.size);
  data_ptr += compressed.size;

  if (hash_size > 0)
    {
      memcpy (data_ptr, MAC, hash_size);
      data_ptr += hash_size;
    }
  if (block_algo == CIPHER_BLOCK && pad > 0)
    {
      memset (data_ptr, pad - 1, pad);
    }


  /* Actual encryption (inplace).
   */
  ret =
    _gnutls_cipher_encrypt (&session->connection_state.write_cipher_state,
			    cipher_data, length);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return length;
}
Ejemplo n.º 26
0
Archivo: pk.c Proyecto: intgr/gnutls
/* Given a signature and parameters, it should return
 * the hash algorithm used in the signature. This is a kludge
 * but until we deprecate gnutls_pubkey_get_verify_algorithm()
 * we depend on it.
 */
static int wrap_nettle_hash_algorithm (gnutls_pk_algorithm_t pk, 
    const gnutls_datum_t * sig, gnutls_pk_params_st * issuer_params,
    gnutls_digest_algorithm_t* hash_algo)
{
  uint8_t digest[MAX_HASH_SIZE];
  uint8_t digest_info[MAX_HASH_SIZE*3];
  gnutls_datum_t di;
  unsigned digest_size;
  mpz_t s;
  struct rsa_public_key pub;
  int ret;

  mpz_init(s);

  switch (pk)
    {
    case GNUTLS_PK_DSA:
    case GNUTLS_PK_EC:

      if (hash_algo)
        *hash_algo = _gnutls_dsa_q_to_hash (pk, issuer_params, NULL);

      ret = 0;
      break;
    case GNUTLS_PK_RSA:
      if (sig == NULL)
        {                       /* return a sensible algorithm */
          if (hash_algo)
            *hash_algo = GNUTLS_DIG_SHA256;
          return 0;
        }

      _rsa_params_to_pubkey (issuer_params, &pub);

      digest_size = sizeof(digest);
      
      nettle_mpz_set_str_256_u(s, sig->size, sig->data);
      
      digest_size = sizeof (digest_info);
      ret = extract_digest_info( &pub, &digest_size, digest_info, s);
      if (ret == 0)
        {
          ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
          gnutls_assert ();
          goto cleanup;
        }

      di.data = digest_info;
      di.size = digest_size;
      
      digest_size = sizeof(digest);
      if ((ret =
           decode_ber_digest_info (&di, hash_algo, digest,
                                   &digest_size)) < 0)
        {
          gnutls_assert ();
          goto cleanup;
        }

      if (digest_size != _gnutls_hash_get_algo_len (*hash_algo))
        {
          gnutls_assert ();
          ret = GNUTLS_E_PK_SIG_VERIFY_FAILED;
          goto cleanup;
        }

      ret = 0;
      break;

    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
    }

cleanup:
  mpz_clear(s);
  return ret;

}
Ejemplo n.º 27
0
/* Generates a signature of all the random data and the parameters.
 * Used in DHE_* ciphersuites.
 */
int
_gnutls_handshake_verify_data(gnutls_session_t session,
			      gnutls_pcert_st * cert,
			      const gnutls_datum_t * params,
			      gnutls_datum_t * signature,
			      gnutls_sign_algorithm_t sign_algo)
{
	gnutls_datum_t dconcat;
	int ret;
	digest_hd_st td_md5;
	digest_hd_st td_sha;
	uint8_t concat[MAX_SIG_SIZE];
	const version_entry_st *ver = get_version(session);
	gnutls_digest_algorithm_t hash_algo;
	const mac_entry_st *me;

	if (_gnutls_version_has_selectable_sighash(ver)) {
		_gnutls_handshake_log
		    ("HSK[%p]: verify handshake data: using %s\n", session,
		     gnutls_sign_algorithm_get_name(sign_algo));

		ret =
		    _gnutls_pubkey_compatible_with_sig(session,
						       cert->pubkey, ver,
						       sign_algo);
		if (ret < 0)
			return gnutls_assert_val(ret);

		ret =
		    _gnutls_session_sign_algo_enabled(session, sign_algo);
		if (ret < 0)
			return gnutls_assert_val(ret);

		hash_algo = gnutls_sign_get_hash_algorithm(sign_algo);
		me = hash_to_entry(hash_algo);
	} else {
		me = hash_to_entry(GNUTLS_DIG_MD5);
		ret = _gnutls_hash_init(&td_md5, me);
		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);

		me = hash_to_entry(GNUTLS_DIG_SHA1);
	}

	ret = _gnutls_hash_init(&td_sha, me);
	if (ret < 0) {
		gnutls_assert();
		if (!_gnutls_version_has_selectable_sighash(ver))
			_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 (!_gnutls_version_has_selectable_sighash(ver)) {
		_gnutls_hash_deinit(&td_md5, concat);
		_gnutls_hash_deinit(&td_sha, &concat[16]);
		dconcat.data = concat;
		dconcat.size = 36;
	} else {
		_gnutls_hash_deinit(&td_sha, concat);

		dconcat.data = concat;
		dconcat.size = _gnutls_hash_get_algo_len(me);
	}

	ret = verify_tls_hash(session, ver, cert, &dconcat, signature,
			      dconcat.size - _gnutls_hash_get_algo_len(me),
			      sign_algo,
			      gnutls_sign_get_pk_algorithm(sign_algo));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	return ret;

}
Ejemplo n.º 28
0
/* This will return the appropriate hash to verify the given signature.
 * If signature is NULL it will return an (or the) appropriate hash for
 * the given parameters.
 */
int
_gnutls_x509_verify_algorithm (gnutls_mac_algorithm_t * hash,
                               const gnutls_datum_t * signature,
                               gnutls_pk_algorithm pk,
                               bigint_t * issuer_params,
                               unsigned int issuer_params_size)
{
  opaque digest[MAX_HASH_SIZE];
  gnutls_datum_t decrypted;
  int digest_size;
  int ret;

  switch (pk)
    {
    case GNUTLS_PK_DSA:

      if (hash)
        *hash = _gnutls_dsa_q_to_hash (issuer_params[1], NULL);

      ret = 0;
      break;
    case GNUTLS_PK_RSA:
      if (signature == NULL)
        {                       /* return a sensible algorithm */
          if (hash)
            *hash = GNUTLS_DIG_SHA256;
          return 0;
        }

      ret =
        _gnutls_pkcs1_rsa_decrypt (&decrypted, signature,
                                   issuer_params, issuer_params_size, 1);


      if (ret < 0)
        {
          gnutls_assert ();
          goto cleanup;
        }

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

      _gnutls_free_datum (&decrypted);
      if (digest_size != _gnutls_hash_get_algo_len (*hash))
        {
          gnutls_assert ();
          ret = GNUTLS_E_ASN1_GENERIC_ERROR;
          goto cleanup;
        }

      ret = 0;
      break;

    default:
      gnutls_assert ();
      ret = GNUTLS_E_INTERNAL_ERROR;
    }

cleanup:

  return ret;

}
Ejemplo n.º 29
0
/* Initializes the write connection session
 * (write encrypted data)
 */
int
_gnutls_write_connection_state_init (gnutls_session_t session)
{
  int mac_size;
  int rc;

  _gnutls_uint64zero (session->connection_state.write_sequence_number);

/* Update internals from CipherSuite selected.
 * If we are resuming just copy the connection session
 */
  if (session->internals.resumed == RESUME_FALSE)
    {
      rc = _gnutls_set_write_cipher (session,
				     _gnutls_cipher_suite_get_cipher_algo
				     (&session->security_parameters.
				      current_cipher_suite));
      if (rc < 0)
	return rc;
      rc = _gnutls_set_write_mac (session,
				  _gnutls_cipher_suite_get_mac_algo
				  (&session->security_parameters.
				   current_cipher_suite));
      if (rc < 0)
	return rc;

      rc = _gnutls_set_kx (session,
			   _gnutls_cipher_suite_get_kx_algo
			   (&session->security_parameters.
			    current_cipher_suite));
      if (rc < 0)
	return rc;

      rc = _gnutls_set_write_compression (session,
					  session->internals.
					  compression_method);
      if (rc < 0)
	return rc;
    }
  else
    {				/* RESUME_TRUE */
      _gnutls_cpy_write_security_parameters (&session->
					     security_parameters,
					     &session->
					     internals.
					     resumed_security_parameters);
    }

  rc = _gnutls_set_write_keys (session);
  if (rc < 0)
    return rc;

  _gnutls_handshake_log ("HSK[%x]: Cipher Suite: %s\n", session,
			 _gnutls_cipher_suite_get_name (&session->
							security_parameters.
							current_cipher_suite));

  if (_gnutls_compression_is_ok
      (session->security_parameters.write_compression_algorithm) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
    }

  if (_gnutls_mac_is_ok
      (session->security_parameters.write_mac_algorithm) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }



  /* Free all the previous keys/ sessions etc.
   */
  if (session->connection_state.write_mac_secret.data != NULL)
    _gnutls_free_datum (&session->connection_state.write_mac_secret);

  if (session->connection_state.write_cipher_state != NULL)
    _gnutls_cipher_deinit (session->connection_state.write_cipher_state);

  if (session->connection_state.write_compression_state != NULL)
    _gnutls_comp_deinit (session->connection_state.
			 write_compression_state, 0);

  mac_size =
    _gnutls_hash_get_algo_len (session->security_parameters.
			       write_mac_algorithm);

  _gnutls_handshake_log
    ("HSK[%x]: Initializing internal [write] cipher sessions\n", session);

  switch (session->security_parameters.entity)
    {
    case GNUTLS_SERVER:
      /* initialize cipher session
       */
      session->connection_state.write_cipher_state =
	_gnutls_cipher_init (session->security_parameters.
			     write_bulk_cipher_algorithm,
			     &session->cipher_specs.
			     server_write_key,
			     &session->cipher_specs.server_write_IV);

      if (session->connection_state.write_cipher_state ==
	  GNUTLS_CIPHER_FAILED
	  && session->security_parameters.
	  write_bulk_cipher_algorithm != GNUTLS_CIPHER_NULL)
	{
	  gnutls_assert ();
	  return GNUTLS_E_INTERNAL_ERROR;
	}


      /* copy mac secrets from cipherspecs, to connection
       * session.
       */
      if (mac_size > 0)
	{
	  if (_gnutls_sset_datum (&session->connection_state.
				  write_mac_secret,
				  session->cipher_specs.
				  server_write_mac_secret.data,
				  session->cipher_specs.
				  server_write_mac_secret.size) < 0)
	    {
	      gnutls_assert ();
	      return GNUTLS_E_MEMORY_ERROR;
	    }

	}


      break;

    case GNUTLS_CLIENT:
      session->connection_state.write_cipher_state =
	_gnutls_cipher_init (session->security_parameters.
			     write_bulk_cipher_algorithm,
			     &session->cipher_specs.
			     client_write_key,
			     &session->cipher_specs.client_write_IV);

      if (session->connection_state.write_cipher_state ==
	  GNUTLS_CIPHER_FAILED
	  && session->security_parameters.
	  write_bulk_cipher_algorithm != GNUTLS_CIPHER_NULL)
	{
	  gnutls_assert ();
	  return GNUTLS_E_INTERNAL_ERROR;
	}

      /* copy mac secret to connection session
       */
      if (mac_size > 0)
	{
	  if (_gnutls_sset_datum (&session->connection_state.
				  write_mac_secret,
				  session->cipher_specs.
				  client_write_mac_secret.data,
				  session->cipher_specs.
				  client_write_mac_secret.size) < 0)
	    {
	      gnutls_assert ();
	      return GNUTLS_E_MEMORY_ERROR;
	    }
	}

      break;

    default:
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }


  session->connection_state.write_compression_state =
    _gnutls_comp_init (session->security_parameters.
		       write_compression_algorithm, 0);

  if (session->connection_state.write_compression_state == GNUTLS_COMP_FAILED)
    {
      gnutls_assert ();
      return GNUTLS_E_UNKNOWN_COMPRESSION_ALGORITHM;
    }

  return 0;
}
Ejemplo n.º 30
0
static int parse_commitment_line(char* line, 
                      const char* host, size_t host_len,
                      const char* service, size_t service_len,
                      time_t now,
                      const gnutls_datum_t *skey)
{
char* p, *kp;
char* savep = NULL;
size_t kp_len, phash_size;
time_t expiration;
int ret;
gnutls_digest_algorithm_t hash_algo;
uint8_t phash[MAX_HASH_SIZE];
uint8_t hphash[MAX_HASH_SIZE*2+1];

  /* read host */
  p = strtok_r(line, "|", &savep);
  if (p == NULL)
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
    
  if (p[0] != '*' && strcmp(p, host) != 0)
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

  /* read service */
  p = strtok_r(NULL, "|", &savep);
  if (p == NULL)
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
    
  if (p[0] != '*' && strcmp(p, service) != 0)
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

  /* read expiration */
  p = strtok_r(NULL, "|", &savep);
  if (p == NULL)
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
    
  expiration = (time_t)atol(p);
  if (expiration > 0 && now > expiration)
    return gnutls_assert_val(GNUTLS_E_EXPIRED);

  /* read hash algorithm */
  p = strtok_r(NULL, "|", &savep);
  if (p == NULL)
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

  hash_algo = (time_t)atol(p);
  if (_gnutls_digest_get_name(hash_algo) == NULL)
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);

  /* read hash */
  kp = strtok_r(NULL, "|", &savep);
  if (kp == NULL)
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
  
  p = strpbrk(kp, "\n \r\t|");
  if (p != NULL) *p = 0;

  /* hash and hex encode */
  ret = _gnutls_hash_fast (hash_algo, skey->data, skey->size, phash);
  if (ret < 0)
    return gnutls_assert_val(ret);
    
  phash_size = _gnutls_hash_get_algo_len(hash_algo);

  p = _gnutls_bin2hex (phash, phash_size,(void*) hphash,
                         sizeof(hphash), NULL);
  if (p == NULL)
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

  kp_len = strlen(kp);
  if (kp_len != phash_size*2)
    return gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH);

  if (memcmp(kp, hphash, kp_len) != 0)
    return gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH);

  /* key found and matches */
  return 0;
}