Exemplo n.º 1
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;
}
Exemplo n.º 2
0
int
_gnutls_encrypt_session_ticket(gnutls_session_t session,
			       const gnutls_datum_t *state,
			       gnutls_datum_t *ticket_data)
{
	cipher_hd_st cipher_hd;
	gnutls_datum_t IV;
	gnutls_datum_t encrypted_state = {NULL,0};
	uint8_t iv[TICKET_IV_SIZE];
	gnutls_datum_t stek_cipher_key, stek_mac_key, stek_key_name;
	struct ticket_st ticket;
	int ret;

	encrypted_state.size = ((state->size + TICKET_BLOCK_SIZE - 1) / TICKET_BLOCK_SIZE) * TICKET_BLOCK_SIZE;
	ticket_data->size = TICKET_KEY_NAME_SIZE + TICKET_IV_SIZE + 2 +
	    encrypted_state.size + TICKET_MAC_SIZE;
	ticket_data->data = gnutls_calloc(1, ticket_data->size);
	if (!ticket_data->data) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}
	encrypted_state.data = ticket_data->data + TICKET_KEY_NAME_SIZE + TICKET_IV_SIZE + 2;
	memcpy(encrypted_state.data, state->data, state->size);

	/* Retrieve ticket encryption keys */
	if (_gnutls_get_session_ticket_encryption_key(session,
						      &stek_key_name,
						      &stek_mac_key,
						      &stek_cipher_key) < 0) {
		ret = GNUTLS_E_ENCRYPTION_FAILED;
		goto cleanup;
	}

	/* Encrypt state */
	IV.data = iv;
	IV.size = TICKET_IV_SIZE;

	ret = gnutls_rnd(GNUTLS_RND_NONCE, iv, TICKET_IV_SIZE);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret =
	    _gnutls_cipher_init(&cipher_hd,
				cipher_to_entry(TICKET_CIPHER),
				&stek_cipher_key, &IV, 1);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = _gnutls_cipher_encrypt(&cipher_hd, encrypted_state.data,
				     encrypted_state.size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup2;
	}


	/* Fill the ticket structure to compute MAC. */
	memcpy(ticket.key_name, stek_key_name.data, stek_key_name.size);
	memcpy(ticket.IV, IV.data, IV.size);
	ticket.encrypted_state_len = encrypted_state.size;
	ticket.encrypted_state = encrypted_state.data;

	ret = digest_ticket(&stek_mac_key, &ticket, ticket.mac);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup2;
	}

	encrypted_state.data = NULL;

	pack_ticket(&ticket, ticket_data);

	ret = 0;

cleanup2:
	_gnutls_cipher_deinit(&cipher_hd);

cleanup:
	_gnutls_free_datum(&encrypted_state);

	return ret;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
static int
encrypt_ticket(gnutls_session_t session, session_ticket_ext_st * priv,
               struct ticket_st *ticket)
{
    cipher_hd_st cipher_hd;
    gnutls_datum_t key, IV;
    gnutls_datum_t state = {NULL,0}, encrypted_state = {NULL,0};
    uint8_t iv[IV_SIZE];
    gnutls_datum_t mac_secret;
    uint32_t t;
    int ret;

    /* Pack security parameters. */
    ret = _gnutls_session_pack(session, &state);
    if (ret < 0) {
        gnutls_assert();
        return ret;
    }

    encrypted_state.size = ((state.size + BLOCK_SIZE - 1) / BLOCK_SIZE) * BLOCK_SIZE;
    encrypted_state.data = gnutls_calloc(1, encrypted_state.size);
    if (!encrypted_state.data) {
        gnutls_assert();
        ret = GNUTLS_E_MEMORY_ERROR;
        goto cleanup;
    }
    memcpy(encrypted_state.data, state.data, state.size);

    /* Encrypt state */
    key.data = (void *) &priv->key[KEY_POS];
    key.size = CIPHER_KEY_SIZE;
    IV.data = iv;
    IV.size = IV_SIZE;

    t = gnutls_time(0);
    memcpy(iv, &t, 4);
    ret = gnutls_rnd(GNUTLS_RND_NONCE, iv+4, IV_SIZE-4);
    if (ret < 0) {
        gnutls_assert();
        goto cleanup;
    }

    ret =
        _gnutls_cipher_init(&cipher_hd,
                            cipher_to_entry(CIPHER),
                            &key, &IV, 1);
    if (ret < 0) {
        gnutls_assert();
        goto cleanup;
    }

    ret = _gnutls_cipher_encrypt(&cipher_hd, encrypted_state.data,
                                 encrypted_state.size);
    if (ret < 0) {
        gnutls_assert();
        goto cleanup2;
    }


    /* Fill the ticket structure to compute MAC. */
    memcpy(ticket->key_name, &priv->key[NAME_POS], KEY_NAME_SIZE);
    memcpy(ticket->IV, IV.data, IV.size);
    ticket->encrypted_state_len = encrypted_state.size;
    ticket->encrypted_state = encrypted_state.data;

    mac_secret.data = &priv->key[MAC_SECRET_POS];
    mac_secret.size = MAC_SECRET_SIZE;
    ret = digest_ticket(&mac_secret, ticket, ticket->mac);
    if (ret < 0) {
        gnutls_assert();
        goto cleanup2;
    }

    encrypted_state.data = NULL;

    ret = 0;

cleanup2:
    _gnutls_cipher_deinit(&cipher_hd);

cleanup:
    _gnutls_free_datum(&state);
    _gnutls_free_datum(&encrypted_state);

    return ret;
}