Esempio n. 1
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_hmac_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);

  params->record_sw_size = 0;

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

  params->initialized = 1;
  return 0;
}
Esempio n. 2
0
/* returns overhead imposed by the record layer (encryption/compression)
 * etc. It does not include the record layer headers, since the caller
 * needs to cope with rounding to multiples of blocksize, and the header
 * is outside that.
 *
 * blocksize: will contain the block size when padding may be required or 1
 *
 * It may return a negative error code on error.
 */
static int record_overhead_rt(gnutls_session_t session, unsigned int *blocksize)
{
record_parameters_st *params;
int total = 0, ret, iv_size;

  if (session->internals.initial_negotiation_completed == 0)
    return GNUTLS_E_INVALID_REQUEST;

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

  /* requires padding */
  iv_size = _gnutls_cipher_get_iv_size(params->cipher_algorithm);

  if (_gnutls_cipher_is_block (params->cipher_algorithm) == CIPHER_BLOCK)
    {
      *blocksize = iv_size;

      total += iv_size; /* iv_size == block_size in DTLS */

      /* We always pad with at least one byte; never 0. */
      total++;
    }
  else
    {
      *blocksize = 1;
    }
  
  if (params->mac_algorithm == GNUTLS_MAC_AEAD)
    total += _gnutls_cipher_get_tag_size(params->cipher_algorithm);
  else
    {
      ret = _gnutls_hmac_get_algo_len(params->mac_algorithm);
      if (ret < 0)
        return gnutls_assert_val(ret);
      total+=ret;
    }

  if (params->compression_algorithm != GNUTLS_COMP_NULL)
    total += EXTRA_COMP_SIZE;

  return total;
}
Esempio n. 3
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);
}
Esempio n. 4
0
int _gnutls_epoch_set_keys(gnutls_session_t session, uint16_t epoch)
{
	int hash_size;
	int IV_size;
	int key_size;
	gnutls_compression_method_t comp_algo;
	record_parameters_st *params;
	int ret;
	const version_entry_st *ver = get_version(session);

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

	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);

	comp_algo = params->compression_algorithm;

	if (_gnutls_cipher_is_ok(params->cipher) == 0
	    || _gnutls_mac_is_ok(params->mac) == 0)
		return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);

	if (_gnutls_cipher_priority(session, params->cipher->id) < 0)
		return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);

	if (_gnutls_mac_priority(session, params->mac->id) < 0)
		return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);

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

	if (!_gnutls_version_has_explicit_iv(ver) &&
	    _gnutls_cipher_type(params->cipher) == CIPHER_BLOCK) {
		IV_size = _gnutls_cipher_get_iv_size(params->cipher);
	} else {
		IV_size = _gnutls_cipher_get_implicit_iv_size(params->cipher);
	}

	key_size = _gnutls_cipher_get_key_size(params->cipher);
	hash_size = _gnutls_mac_get_key_size(params->mac);
	params->etm = session->security_parameters.etm;

	ret = _gnutls_set_keys
	    (session, params, hash_size, IV_size, key_size);
	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);

	params->record_sw_size = 0;

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

	params->initialized = 1;
	return 0;
}
Esempio n. 5
0
static int
decrypt_packet_tls13(gnutls_session_t session,
		     gnutls_datum_t *ciphertext,
		     gnutls_datum_t *plain,
		     content_type_t *type, record_parameters_st *params,
		     gnutls_uint64 *sequence)
{
	uint8_t nonce[MAX_CIPHER_IV_SIZE];
	size_t length, length_to_decrypt;
	int ret;
	const version_entry_st *ver = get_version(session);
	unsigned int tag_size = params->read.aead_tag_size;
	unsigned iv_size;
	unsigned j;
	volatile unsigned length_set;
	uint8_t aad[5];

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

	if (params->cipher->id == GNUTLS_CIPHER_NULL) {
		if (plain->size < ciphertext->size)
			return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

		length = ciphertext->size;
		memcpy(plain->data, ciphertext->data, length);

		return length;
	}

	iv_size = _gnutls_cipher_get_iv_size(params->cipher);

	/* The way AEAD ciphers are defined in RFC5246, it allows
	 * only stream ciphers.
	 */
	if (unlikely(ciphertext->size < tag_size))
		return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);

	if (unlikely(params->read.iv_size != iv_size || iv_size < 8))
		return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);

	memcpy(nonce, params->read.iv, params->read.iv_size);
	memxor(&nonce[iv_size-8], UINT64DATA(*sequence), 8);

	length =
	    ciphertext->size - tag_size;

	length_to_decrypt = ciphertext->size;

	if (unlikely
	    ((unsigned) length_to_decrypt > plain->size)) {
			_gnutls_audit_log(session,
				  "Received %u bytes, while expecting less than %u\n",
				  (unsigned int) length_to_decrypt,
				  (unsigned int) plain->size);
		return
		    gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
	}

	aad[0] = GNUTLS_APPLICATION_DATA;
	aad[1] = 0x03;
	aad[2] = 0x03;
	_gnutls_write_uint16(ciphertext->size, &aad[3]);

	ret = gnutls_aead_cipher_decrypt(&params->read.ctx.aead,
					 nonce, iv_size,
					 aad, sizeof(aad),
					 tag_size,
					 ciphertext->data, length_to_decrypt,
					 plain->data, &length);
	if (unlikely(ret < 0))
		return gnutls_assert_val(ret);

	/* 1 octet for content type */
	if (length > max_decrypted_size(session) + 1) {
		_gnutls_audit_log
		    (session, "Received packet with illegal length: %u\n",
		     (unsigned int) length);

		return gnutls_assert_val(GNUTLS_E_RECORD_OVERFLOW);
	}

	length_set = 0;

	/* now figure the actual data size. We intentionally iterate through all data,
	 * to avoid leaking the padding length due to timing differences in processing.
	 */
	for (j=length;j>0;j--) {
		if (plain->data[j-1]!=0 && length_set == 0) {
			*type = plain->data[j-1];
			length = j-1;
			length_set = 1;
			if (!(session->internals.flags & GNUTLS_SAFE_PADDING_CHECK))
				break;
		}
	}

	if (!length_set)
		return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);

	return length;
}