예제 #1
0
static
int digest_ticket(const gnutls_datum_t * key, struct ticket_st *ticket,
	      uint8_t * digest)
{
	mac_hd_st digest_hd;
	uint16_t length16;
	int ret;

	ret = _gnutls_mac_init(&digest_hd, mac_to_entry(TICKET_MAC_ALGO),
			      key->data, key->size);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	_gnutls_mac(&digest_hd, ticket->key_name, TICKET_KEY_NAME_SIZE);
	_gnutls_mac(&digest_hd, ticket->IV, TICKET_IV_SIZE);
	length16 = _gnutls_conv_uint16(ticket->encrypted_state_len);
	_gnutls_mac(&digest_hd, &length16, 2);
	_gnutls_mac(&digest_hd, ticket->encrypted_state,
		   ticket->encrypted_state_len);
	_gnutls_mac_deinit(&digest_hd, digest);

	return 0;
}
예제 #2
0
/* generates the authentication data (data to be hashed only
 * and are not to be send). Returns their size.
 */
static inline int
make_preamble (opaque * uint64_data, opaque type, int length,
               opaque ver, opaque * preamble)
{
  opaque minor = _gnutls_version_get_minor (ver);
  opaque major = _gnutls_version_get_major (ver);
  opaque *p = preamble;
  uint16_t c_length;

  c_length = _gnutls_conv_uint16 (length);

  memcpy (p, uint64_data, 8);
  p += 8;
  *p = type;
  p++;
  if (ver != GNUTLS_SSL3)
    { /* TLS protocols */
      *p = major;
      p++;
      *p = minor;
      p++;
    }
  memcpy (p, &c_length, 2);
  p += 2;
  return p - preamble;
}
예제 #3
0
파일: cipher.c 프로젝트: gnutls/gnutls
/* generates the authentication data (data to be hashed only
 * and are not to be sent). Returns their size.
 */
int
_gnutls_make_preamble(uint8_t * uint64_data, uint8_t type, unsigned int length,
		      const version_entry_st * ver, uint8_t preamble[MAX_PREAMBLE_SIZE])
{
	uint8_t *p = preamble;
	uint16_t c_length;

	c_length = _gnutls_conv_uint16(length);

	memcpy(p, uint64_data, 8);
	p += 8;
	*p = type;
	p++;
#ifdef ENABLE_SSL3
	if (ver->id != GNUTLS_SSL3)
#endif
	{	/* TLS protocols */
		*p = ver->major;
		p++;
		*p = ver->minor;
		p++;
	}
	memcpy(p, &c_length, 2);
	p += 2;
	return p - preamble;
}
예제 #4
0
/* generates the authentication data (data to be hashed only
 * and are not to be sent). Returns their size.
 */
static inline int
make_preamble(uint8_t * uint64_data, uint8_t type, unsigned int length,
	      const version_entry_st * ver, uint8_t * preamble)
{
	uint8_t *p = preamble;
	uint16_t c_length;

	c_length = _gnutls_conv_uint16(length);

	memcpy(p, uint64_data, 8);
	p += 8;
	*p = type;
	p++;
	if (ver->id != GNUTLS_SSL3) {	/* TLS protocols */
		*p = ver->major;
		p++;
		*p = ver->minor;
		p++;
	}
	memcpy(p, &c_length, 2);
	p += 2;
	return p - preamble;
}
예제 #5
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;
}
예제 #6
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;
}
예제 #7
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;
}
예제 #8
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;
}