/* returns ciphertext which contains the headers too. This also
 * calculates the size in the header field.
 * 
 * If random pad != 0 then the random pad data will be appended.
 */
int
_gnutls_encrypt (gnutls_session_t session, const opaque * headers,
                 size_t headers_size, const opaque * data,
                 size_t data_size, opaque * ciphertext,
                 size_t ciphertext_size, content_type_t type, 
                 record_parameters_st * params)
{
  gnutls_datum_t comp;
  int free_comp = 0;
  int ret;

  if (data_size == 0 || is_write_comp_null (params) == 0)
    {
      comp.data = (opaque*)data;
      comp.size = data_size;
    }
  else
    {
      /* Here comp is allocated and must be 
       * freed.
       */
      free_comp = 1;
      
      comp.size = ciphertext_size - headers_size;
      comp.data = gnutls_malloc(comp.size);
      if (comp.data == NULL)
        return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
      
      ret = _gnutls_compress( &params->write.compression_state, data, data_size, comp.data, comp.size);
      if (ret < 0)
        {
          gnutls_free(comp.data);
          return gnutls_assert_val(ret);
        }
      
      comp.size = ret;
    }

  ret = compressed_to_ciphertext (session, &ciphertext[headers_size],
                                       ciphertext_size - headers_size,
                                       &comp, type, params);

  if (free_comp)
    gnutls_free(comp.data);

  if (ret < 0)
    return gnutls_assert_val(ret);

  /* copy the headers */
  memcpy (ciphertext, headers, headers_size);
  
  if(IS_DTLS(session))
    _gnutls_write_uint16 (ret, &ciphertext[11]);
  else
    _gnutls_write_uint16 (ret, &ciphertext[3]);

  return ret + headers_size;
}
Example #2
0
static int
pack_ticket(gnutls_session_t session, tls13_ticket_st *ticket, gnutls_datum_t *packed)
{
	uint8_t *p;
	gnutls_datum_t state;
	int ret;

	ret = _gnutls_session_pack(session, &state);
	if (ret < 0)
		return gnutls_assert_val(ret);

	packed->size = 2 + 4 + 4 +
		1 + ticket->prf->output_size +
		1 + ticket->nonce_size + 2 + state.size + 12;

	packed->data = gnutls_malloc(packed->size);
	if (!packed->data) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	p = packed->data;

	_gnutls_write_uint16(ticket->prf->id, p);
	p += 2;
	_gnutls_write_uint32(ticket->age_add, p);
	p += 4;
	_gnutls_write_uint32(ticket->lifetime, p);
	p += 4;
	*p = ticket->prf->output_size;
	p += 1;
	memcpy(p, ticket->resumption_master_secret, ticket->prf->output_size);
	p += ticket->prf->output_size;
	*p = ticket->nonce_size;

	p += 1;
	memcpy(p, ticket->nonce, ticket->nonce_size);
	p += ticket->nonce_size;

	_gnutls_write_uint16(state.size, p);
	p += 2;

	memcpy(p, state.data, state.size);
	p += state.size;

	_gnutls_write_uint32((uint64_t) ticket->creation_time.tv_sec >> 32, p);
	p += 4;
	_gnutls_write_uint32(ticket->creation_time.tv_sec & 0xFFFFFFFF, p);
	p += 4;
	_gnutls_write_uint32(ticket->creation_time.tv_nsec, p);

	ret = 0;

 cleanup:
	gnutls_free(state.data);
	return ret;
}
Example #3
0
File: psk.c Project: nobled/gnutls
/* Set the PSK premaster secret.
 */
int
_gnutls_set_psk_session_key (gnutls_session_t session,
    gnutls_datum_t * ppsk /* key */,
    gnutls_datum_t * dh_secret)
{
  gnutls_datum_t pwd_psk = { NULL, 0 };
  size_t dh_secret_size;
  uint8_t * p;
  int ret;

  if (dh_secret == NULL)
    dh_secret_size = ppsk->size;
  else
    dh_secret_size = dh_secret->size;

  /* set the session key
   */
  session->key.key.size = 4 + dh_secret_size + ppsk->size;
  session->key.key.data = gnutls_malloc (session->key.key.size);
  if (session->key.key.data == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_MEMORY_ERROR;
      goto error;
    }

  /* format of the premaster secret:
   * (uint16_t) psk_size
   * psk_size bytes of (0)s
   * (uint16_t) psk_size
   * the psk
   */
  p = session->key.key.data;
  _gnutls_write_uint16 (dh_secret_size, p);
  p+=2;
  if (dh_secret == NULL)
    memset (p, 0, dh_secret_size);
  else
    memcpy (p, dh_secret->data, dh_secret->size);

  p += dh_secret_size;
  _gnutls_write_uint16 (ppsk->size, p);
  if (ppsk->data != NULL)
    memcpy (p+2, ppsk->data, ppsk->size);

  ret = 0;

error:
  _gnutls_free_datum (&pwd_psk);
  return ret;
}
Example #4
0
/* returns ciphertext which contains the headers too. This also
 * calculates the size in the header field.
 * 
 */
int
_gnutls_encrypt(gnutls_session_t session,
		const uint8_t *data, size_t data_size,
		size_t min_pad,
		mbuffer_st *bufel,
		content_type_t type, record_parameters_st *params)
{
	gnutls_datum_t plaintext;
	const version_entry_st *vers = get_version(session);
	int ret;

	plaintext.data = (uint8_t *) data;
	plaintext.size = data_size;

	if (vers && vers->tls13_sem) {
		/* it fills the header, as it is included in the authenticated
		 * data of the AEAD cipher. */
		ret =
		    encrypt_packet_tls13(session,
					 _mbuffer_get_udata_ptr(bufel),
					 _mbuffer_get_udata_size(bufel),
					 &plaintext, min_pad, type,
					 params);
		if (ret < 0)
			return gnutls_assert_val(ret);
	} else {
		ret =
		    encrypt_packet(session,
				   _mbuffer_get_udata_ptr(bufel),
				   _mbuffer_get_udata_size
				   (bufel), &plaintext, min_pad, type,
				   params);
		if (ret < 0)
			return gnutls_assert_val(ret);

	}

	if (IS_DTLS(session))
		_gnutls_write_uint16(ret,
				     ((uint8_t *)
				      _mbuffer_get_uhead_ptr(bufel)) + 11);
	else
		_gnutls_write_uint16(ret,
				     ((uint8_t *)
				      _mbuffer_get_uhead_ptr(bufel)) + 3);

	_mbuffer_set_udata_size(bufel, ret);
	_mbuffer_set_uhead_size(bufel, 0);

	return _mbuffer_get_udata_size(bufel);
}
Example #5
0
void
_gnutls_write_datum16 (opaque * dest, gnutls_datum_t dat)
{
  _gnutls_write_uint16 (dat.size, dest);
  if (dat.data != NULL)
    memcpy (&dest[2], dat.data, dat.size);
}
Example #6
0
/* generates a SignatureAndHashAlgorithm structure with length as prefix
 * by using the setup priorities.
 */
int
_gnutls_sign_algorithm_write_params (gnutls_session_t session, opaque * data,
				     size_t max_data_size)
{
  opaque *p = data;
  int len, i, j;
  sign_algorithm_st aid;

  len = session->internals.priorities.sign_algo.algorithms * 2;
  if (max_data_size < len + 2)
    {
      gnutls_assert ();
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
    }

  _gnutls_write_uint16 (len, p);
  p += 2;

  for (i = j = 0; i < len; i += 2, j++)
    {
      aid =
	_gnutls_sign_to_tls_aid (session->internals.priorities.
				 sign_algo.priority[j]);
      *p = aid.hash_algorithm;
      p++;
      *p = aid.sign_algorithm;
      p++;

    }
  return len + 2;
}
Example #7
0
int
_gnutls_epoch_alloc (gnutls_session_t session, uint16_t epoch,
                     record_parameters_st ** out)
{
  record_parameters_st **slot;

  _gnutls_record_log ("REC[%p]: Allocating epoch #%u\n", session, epoch);

  slot = epoch_get_slot (session, epoch);

  /* If slot out of range or not empty. */
  if (slot == NULL)
    return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST);

  if (*slot != NULL)
    return gnutls_assert_val (GNUTLS_E_INVALID_REQUEST);

  *slot = gnutls_calloc (1, sizeof (record_parameters_st));
  if (*slot == NULL)
    return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);

  (*slot)->epoch = epoch;
  (*slot)->cipher_algorithm = GNUTLS_CIPHER_UNKNOWN;
  (*slot)->mac_algorithm = GNUTLS_MAC_UNKNOWN;
  (*slot)->compression_algorithm = GNUTLS_COMP_UNKNOWN;

  if (IS_DTLS (session))
    _gnutls_write_uint16 (epoch, UINT64DATA((*slot)->write.sequence_number));

  if (out != NULL)
    *out = *slot;

  return 0;
}
Example #8
0
int
_gnutls_buffer_append_prefix (gnutls_buffer_st * buf, int pfx_size, size_t data_size)
{
  opaque ss[4];

  if (pfx_size == 32)
    {
      _gnutls_write_uint32 (data_size, ss);
      pfx_size = 4;
    }
  else if (pfx_size == 24)
    {
      _gnutls_write_uint24 (data_size, ss);
      pfx_size = 3;
    }
  else if (pfx_size == 16)
    {
      _gnutls_write_uint16 (data_size, ss);
      pfx_size = 2;
    }
  else if (pfx_size == 8)
    {
      ss[0] = data_size;
      pfx_size = 1;
    }
  else
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

  return _gnutls_buffer_append_data (buf, ss, pfx_size);
}
Example #9
0
/* returns ciphertext which contains the headers too. This also
 * calculates the size in the header field.
 * 
 * If random pad != 0 then the random pad data will be appended.
 */
int
_gnutls_encrypt (gnutls_session_t session, const opaque * headers,
                 size_t headers_size, const opaque * data,
                 size_t data_size, opaque * ciphertext,
                 size_t ciphertext_size, content_type_t type, int random_pad,
                 record_parameters_st * params)
{
  gnutls_datum_t plain;
  gnutls_datum_t comp;
  int ret;
  int free_comp = 1;

  plain.data = (opaque *) data;
  plain.size = data_size;

  if (plain.size == 0 || is_write_comp_null (session) == 0)
    {
      comp = plain;
      free_comp = 0;
    }
  else
    {
      /* Here comp is allocated and must be 
       * freed.
       */
      ret = _gnutls_m_plaintext2compressed (session, &comp, &plain, params);
      if (ret < 0)
        {
          gnutls_assert ();
          return ret;
        }
    }

  ret = _gnutls_compressed2ciphertext (session, &ciphertext[headers_size],
                                       ciphertext_size - headers_size,
                                       comp, type, random_pad, params);

  if (free_comp)
    _gnutls_free_datum (&comp);

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


  /* copy the headers */
  memcpy (ciphertext, headers, headers_size);
  _gnutls_write_uint16 (ret, &ciphertext[3]);

  return ret + headers_size;
}
Example #10
0
/* Set the PSK premaster secret.
 */
static int
set_rsa_psk_session_key(gnutls_session_t session,
			gnutls_datum_t * ppsk, gnutls_datum_t * rsa_secret)
{
	unsigned char *p;
	size_t rsa_secret_size;
	int ret;


	rsa_secret_size = rsa_secret->size;

	/* set the session key
	 */
	session->key.key.size = 2 + rsa_secret_size + 2 + ppsk->size;
	session->key.key.data = gnutls_malloc(session->key.key.size);
	if (session->key.key.data == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto error;
	}

	/* format of the premaster secret:
	 * (uint16_t) other_secret size (48)
	 * other_secret: 2 byte version + 46 byte random
	 * (uint16_t) psk_size
	 * the psk
	 */
	_gnutls_write_uint16(rsa_secret_size, session->key.key.data);
	memcpy(&session->key.key.data[2], rsa_secret->data,
	       rsa_secret->size);
	p = &session->key.key.data[rsa_secret_size + 2];
	_gnutls_write_uint16(ppsk->size, p);
	if (ppsk->data != NULL)
		memcpy(p + 2, ppsk->data, ppsk->size);

	ret = 0;

      error:
	return ret;
}
Example #11
0
/* Format: 
 *      1 byte the credentials type
 *      4 bytes the size of the whole structure
 *      2 bytes the size of secret key in bits
 *      4 bytes the size of the prime
 *      x bytes the prime
 *      4 bytes the size of the generator
 *      x bytes the generator
 *      4 bytes the size of the public key
 *      x bytes the public key
 */
static int
pack_anon_auth_info (gnutls_session_t session, gnutls_datum_t * packed_session)
{
  anon_auth_info_t info = _gnutls_get_auth_info (session);
  int pos = 0;
  size_t pack_size;

  if (info == NULL && session->key->auth_info_size != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if (info)
    pack_size = 2 + 4 * 3 + info->dh.prime.size +
      info->dh.generator.size + info->dh.public_key.size;
  else
    pack_size = 0;

  packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);

  /* calculate the size and allocate the data.
   */
  packed_session->data =
    gnutls_malloc (packed_session->size + MAX_SEC_PARAMS);

  if (packed_session->data == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  packed_session->data[0] = GNUTLS_CRD_ANON;
  _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]);
  pos += 4 + PACK_HEADER_SIZE;

  if (pack_size > 0)
    {
      _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]);
      pos += 2;

      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime);
      pos += 4 + info->dh.prime.size;
      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator);
      pos += 4 + info->dh.generator.size;
      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key);
      pos += 4 + info->dh.public_key.size;

    }

  return 0;
}
Example #12
0
int
oprfi_send_server (gnutls_session_t session, opaque * data, size_t _data_size)
{
  opaque *p = data;
  int ret;
  ssize_t data_size = _data_size;
  size_t len;

  if (!session->security_parameters.extensions.oprfi_client ||
      !session->internals.oprfi_cb)
    return 0;

  /* Allocate buffer for outgoing data. */
  session->security_parameters.extensions.oprfi_server_len =
    session->security_parameters.extensions.oprfi_client_len;
  session->security_parameters.extensions.oprfi_server =
    gnutls_malloc (session->security_parameters.extensions.oprfi_server_len);
  if (!session->security_parameters.extensions.oprfi_server)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  /* Get outgoing data. */
  ret = session->internals.oprfi_cb
    (session, session->internals.oprfi_userdata,
     session->security_parameters.extensions.oprfi_client_len,
     session->security_parameters.extensions.oprfi_client,
     session->security_parameters.extensions.oprfi_server);
  if (ret < 0)
    {
      gnutls_assert ();
      gnutls_free (session->security_parameters.extensions.oprfi_server);
      return ret;
    }

  DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER);
  _gnutls_write_uint16 (session->security_parameters.extensions.
			oprfi_server_len, p);
  p += 2;

  DECR_LENGTH_RET (data_size,
		   session->security_parameters.extensions.oprfi_server_len,
		   GNUTLS_E_SHORT_MEMORY_BUFFER);

  memcpy (p, session->security_parameters.extensions.oprfi_server,
	  session->security_parameters.extensions.oprfi_server_len);

  return 2 + session->security_parameters.extensions.oprfi_server_len;
}
Example #13
0
static int
add_new_ca_to_rdn_seq(gnutls_x509_trust_list_t list,
		       gnutls_x509_crt_t ca)
{
	gnutls_datum_t tmp;
	size_t newsize;
	unsigned char *newdata, *p;

	/* Add DN of the last added CAs to the RDN sequence
	 * This will be sent to clients when a certificate
	 * request message is sent.
	 */

	/* FIXME: in case of a client it is not needed
	 * to do that. This would save time and memory.
	 * However we don't have that information available
	 * here.
	 * Further, this function is now much more efficient,
	 * so optimizing that is less important.
	 */
	tmp.data = ca->raw_dn.data;
	tmp.size = ca->raw_dn.size;

	newsize = list->x509_rdn_sequence.size + 2 + tmp.size;
	if (newsize < list->x509_rdn_sequence.size) {
		gnutls_assert();
		return GNUTLS_E_SHORT_MEMORY_BUFFER;
	}

	newdata =
	    gnutls_realloc_fast(list->x509_rdn_sequence.data,
				newsize);
	if (newdata == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	p = newdata + list->x509_rdn_sequence.size;
	_gnutls_write_uint16(tmp.size, p);
	if (tmp.data != NULL)
		memcpy(p + 2, tmp.data, tmp.size);

	list->x509_rdn_sequence.size = newsize;
	list->x509_rdn_sequence.data = newdata;

	return 0;
}
Example #14
0
/* generates a SignatureAndHashAlgorithm structure with length as prefix
 * by using the setup priorities.
 */
int
_gnutls_sign_algorithm_write_params(gnutls_session_t session,
				    uint8_t * data, size_t max_data_size)
{
	uint8_t *p = data, *len_p;
	unsigned int len, i, j;
	const sign_algorithm_st *aid;

	if (max_data_size <
	    (session->internals.priorities.sign_algo.algorithms * 2) + 2) {
		gnutls_assert();
		return GNUTLS_E_SHORT_MEMORY_BUFFER;
	}

	len = 0;
	len_p = p;

	p += 2;

	for (i = j = 0;
	     j < session->internals.priorities.sign_algo.algorithms;
	     i += 2, j++) {
		aid =
		    _gnutls_sign_to_tls_aid(session->internals.
					    priorities.sign_algo.
					    priority[j]);

		if (aid == NULL)
			continue;

		_gnutls_handshake_log
		    ("EXT[%p]: sent signature algo (%d.%d) %s\n", session,
		     aid->hash_algorithm, aid->sign_algorithm,
		     gnutls_sign_get_name(session->internals.priorities.
					  sign_algo.priority[j]));
		*p = aid->hash_algorithm;
		p++;
		*p = aid->sign_algorithm;
		p++;
		len += 2;
	}

	_gnutls_write_uint16(len, len_p);
	return len + 2;
}
Example #15
0
int
oprfi_send_client (gnutls_session_t session, opaque * data, size_t _data_size)
{
  opaque *p = data;
  ssize_t data_size = _data_size;
  int oprf_size = session->security_parameters.extensions.oprfi_client_len;

  if (oprf_size == 0)
    return 0;

  DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER);
  _gnutls_write_uint16 (oprf_size, p);
  p += 2;

  DECR_LENGTH_RET (data_size, oprf_size, GNUTLS_E_SHORT_MEMORY_BUFFER);

  memcpy (p, session->security_parameters.extensions.oprfi_client, oprf_size);

  return 2 + oprf_size;
}
Example #16
0
static void
pack_ticket(const struct ticket_st *ticket, gnutls_datum_t *ticket_data)
{
	uint8_t *p;

	p = ticket_data->data;

	memcpy(p, ticket->key_name, TICKET_KEY_NAME_SIZE);
	p += TICKET_KEY_NAME_SIZE;

	memcpy(p, ticket->IV, TICKET_IV_SIZE);
	p += TICKET_IV_SIZE;

	_gnutls_write_uint16(ticket->encrypted_state_len, p);
	p += 2;

	memcpy(p, ticket->encrypted_state, ticket->encrypted_state_len);
	p += ticket->encrypted_state_len;

	memcpy(p, ticket->mac, TICKET_MAC_SIZE);
}
Example #17
0
static int
add_new_ca_to_rdn_seq(gnutls_x509_trust_list_t list,
		       gnutls_x509_crt_t ca)
{
	gnutls_datum_t tmp;
	size_t newsize;
	unsigned char *newdata, *p;

	/* Add DN of the last added CAs to the RDN sequence
	 * This will be sent to clients when a certificate
	 * request message is sent.
	 */
	tmp.data = ca->raw_dn.data;
	tmp.size = ca->raw_dn.size;

	newsize = list->x509_rdn_sequence.size + 2 + tmp.size;
	if (newsize < list->x509_rdn_sequence.size) {
		gnutls_assert();
		return GNUTLS_E_SHORT_MEMORY_BUFFER;
	}

	newdata =
	    gnutls_realloc_fast(list->x509_rdn_sequence.data,
				newsize);
	if (newdata == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	p = newdata + list->x509_rdn_sequence.size;
	_gnutls_write_uint16(tmp.size, p);
	if (tmp.data != NULL)
		memcpy(p + 2, tmp.data, tmp.size);

	list->x509_rdn_sequence.size = newsize;
	list->x509_rdn_sequence.data = newdata;

	return 0;
}
Example #18
0
/*
 * Sends heartbeat data.
 */
static int
heartbeat_send_data(gnutls_session_t session, const void *data,
		    size_t data_size, uint8_t type)
{
	int ret, pos;
	uint8_t *response;

	response = gnutls_malloc(1 + 2 + data_size + DEFAULT_PAYLOAD_SIZE);
	if (response == NULL)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	pos = 0;
	response[pos++] = type;

	_gnutls_write_uint16(data_size, &response[pos]);
	pos += 2;

	memcpy(&response[pos], data, data_size);
	pos += data_size;

	ret =
	    gnutls_rnd(GNUTLS_RND_NONCE, &response[pos],
		       DEFAULT_PAYLOAD_SIZE);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}
	pos += DEFAULT_PAYLOAD_SIZE;

	ret =
	    _gnutls_send_int(session, GNUTLS_HEARTBEAT, -1,
			     EPOCH_WRITE_CURRENT, response, pos,
			     MBUFFER_FLUSH);

      cleanup:
	gnutls_free(response);
	return ret;
}
int
_gnutls_gen_extensions(gnutls_session_t session,
		       gnutls_buffer_st * extdata,
		       gnutls_ext_parse_type_t parse_type)
{
	int size;
	int pos, size_pos, ret;
	size_t i, init_size = extdata->length;

	pos = extdata->length;	/* we will store length later on */

	ret = _gnutls_buffer_append_prefix(extdata, 16, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);

	for (i = 0; i < extfunc_size; i++) {
		extension_entry_st *p = &extfunc[i];

		if (p->send_func == NULL)
			continue;

		if (parse_type != GNUTLS_EXT_ANY
		    && p->parse_type != parse_type)
			continue;

		ret = _gnutls_buffer_append_prefix(extdata, 16, p->type);
		if (ret < 0)
			return gnutls_assert_val(ret);

		size_pos = extdata->length;
		ret = _gnutls_buffer_append_prefix(extdata, 16, 0);
		if (ret < 0)
			return gnutls_assert_val(ret);

		size = p->send_func(session, extdata);
		/* returning GNUTLS_E_INT_RET_0 means to send an empty
		 * extension of this type.
		 */
		if (size > 0 || size == GNUTLS_E_INT_RET_0) {
			if (size == GNUTLS_E_INT_RET_0)
				size = 0;

			/* write the real size */
			_gnutls_write_uint16(size,
					     &extdata->data[size_pos]);

			/* add this extension to the extension list
			 */
			_gnutls_extension_list_add(session, p->type);

			_gnutls_handshake_log
			    ("EXT[%p]: Sending extension %s (%d bytes)\n",
			     session, p->name, size);
		} else if (size < 0) {
			gnutls_assert();
			return size;
		} else if (size == 0)
			extdata->length -= 4;	/* reset type and size */
	}

	/* remove any initial data, and the size of the header */
	size = extdata->length - init_size - 2;

	if (size > 0)
		_gnutls_write_uint16(size, &extdata->data[pos]);
	else if (size == 0)
		extdata->length -= 2;	/* the length bytes */

	return size;
}
Example #20
0
/* return A = g^a % N */
int
_gnutls_gen_srp_client_kx (gnutls_session_t session, opaque ** data)
{
  size_t n_a;
  int ret;
  uint8_t *data_a;
  char *username, *password;
  char buf[64];
  gnutls_srp_client_credentials_t cred;


  cred = (gnutls_srp_client_credentials_t)
    _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL);

  if (cred == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  if (session->internals.srp_username == NULL)
    {
      username = cred->username;
      password = cred->password;
    }
  else
    {
      username = session->internals.srp_username;
      password = session->internals.srp_password;
    }

  if (username == NULL || password == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  /* calc A = g^a % N 
   */
  if (G == NULL || N == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  A = _gnutls_calc_srp_A (&_a, G, N);
  if (A == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  /* Rest of SRP calculations 
   */

  /* calculate u */
  session->key->u = _gnutls_calc_srp_u (A, B, N);
  if (session->key->u == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  _gnutls_dump_mpi ("SRP U: ", session->key->u);

  /* S = (B - g^x) ^ (a + u * x) % N */
  S = _gnutls_calc_srp_S2 (B, G, session->key->x, _a, session->key->u, N);
  if (S == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  _gnutls_dump_mpi ("SRP B: ", B);

  _gnutls_mpi_release (&_b);
  _gnutls_mpi_release (&V);
  _gnutls_mpi_release (&session->key->u);
  _gnutls_mpi_release (&B);

  ret = _gnutls_mpi_dprint (&session->key->key, session->key->KEY);
  _gnutls_mpi_release (&S);

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

  if (_gnutls_mpi_print (NULL, &n_a, A) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_PRINT_FAILED;
    }

  (*data) = gnutls_malloc (n_a + 2);
  if ((*data) == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  /* copy A */
  data_a = (*data);
  if (_gnutls_mpi_print (&data_a[2], &n_a, A) != 0)
    {
      gnutls_free (*data);
      return GNUTLS_E_MPI_PRINT_FAILED;
    }

  _gnutls_hard_log ("INT: SRP A[%d]: %s\n", n_a,
		    _gnutls_bin2hex (&data_a[2], n_a, buf, sizeof (buf)));

  _gnutls_mpi_release (&A);

  _gnutls_write_uint16 (n_a, data_a);

  return n_a + 2;
}
Example #21
0
/* Send the first key exchange message ( g, n, s) and append the verifier algorithm number 
 * Data is allocated by the caller, and should have data_size size.
 */
int
_gnutls_gen_srp_server_kx (gnutls_session_t session, opaque ** data)
{
  int ret;
  uint8_t *data_n, *data_s;
  uint8_t *data_g;
  char *username;
  SRP_PWD_ENTRY *pwd_entry;
  srp_server_auth_info_t info;
  ssize_t data_size;
  size_t n_b, tmp_size;
  char buf[64];
  uint8_t *data_b;

  if ((ret =
       _gnutls_auth_info_set (session, GNUTLS_CRD_SRP,
			      sizeof (srp_server_auth_info_st), 1)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  info = _gnutls_get_auth_info (session);
  username = info->username;

  _gnutls_str_cpy (username, MAX_SRP_USERNAME,
		   session->security_parameters.extensions.srp_username);

  ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry);

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

  /* copy from pwd_entry to local variables (actually in session) */
  tmp_size = pwd_entry->g.size;
  if (_gnutls_mpi_scan_nz (&G, pwd_entry->g.data, &tmp_size) < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  tmp_size = pwd_entry->n.size;
  if (_gnutls_mpi_scan_nz (&N, pwd_entry->n.data, &tmp_size) < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  tmp_size = pwd_entry->v.size;
  if (_gnutls_mpi_scan_nz (&V, pwd_entry->v.data, &tmp_size) < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  /* Calculate:  B = (k*v + g^b) % N 
   */
  B = _gnutls_calc_srp_B (&_b, G, N, V);
  if (B == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  if (_gnutls_mpi_print (NULL, &n_b, B) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_PRINT_FAILED;
    }


  /* Allocate size to hold the N, g, s, B 
   */

  data_size = (pwd_entry->n.size + 2 + pwd_entry->g.size + 2 +
	       pwd_entry->salt.size + 1) + (n_b + 2);

  (*data) = gnutls_malloc (data_size);
  if ((*data) == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  /* copy N (mod n) 
   */
  data_n = *data;
  _gnutls_write_datum16 (data_n, pwd_entry->n);


  /* copy G (generator) to data 
   */
  data_g = &data_n[2 + pwd_entry->n.size];
  _gnutls_write_datum16 (data_g, pwd_entry->g);


  /* copy the salt 
   */
  data_s = &data_g[2 + pwd_entry->g.size];
  _gnutls_write_datum8 (data_s, pwd_entry->salt);


  /* Copy the B value
   */

  data_b = &data_s[1 + pwd_entry->salt.size];
  if (_gnutls_mpi_print (&data_b[2], &n_b, B) != 0) 
    {
      gnutls_assert();
      return GNUTLS_E_MPI_PRINT_FAILED;
    }

  _gnutls_write_uint16 (n_b, data_b);

  _gnutls_hard_log ("INT: SRP B[%d]: %s\n", n_b,
		    _gnutls_bin2hex (&data_b[2], n_b, buf, sizeof (buf)));

  _gnutls_srp_entry_free (pwd_entry);

  return data_size;
}
Example #22
0
/**
 * gnutls_dtls_cookie_send:
 * @key: is a random key to be used at cookie generation
 * @client_data: contains data identifying the client (i.e. address)
 * @client_data_size: The size of client's data
 * @prestate: The previous cookie returned by gnutls_dtls_cookie_verify()
 * @ptr: A transport pointer to be used by @push_func
 * @push_func: A function that will be used to reply
 *
 * This function can be used to prevent denial of service
 * attacks to a DTLS server by requiring the client to
 * reply using a cookie sent by this function. That way
 * it can be ensured that a client we allocated resources
 * for (i.e. #gnutls_session_t) is the one that the 
 * original incoming packet was originated from.
 *
 * Returns: the number of bytes sent, or a negative error code.  
 *
 * Since: 3.0
 **/
int gnutls_dtls_cookie_send(gnutls_datum_t* key, void* client_data, size_t client_data_size, 
  gnutls_dtls_prestate_st* prestate,
  gnutls_transport_ptr_t ptr, gnutls_push_func push_func)
{
uint8_t hvr[20+DTLS_HANDSHAKE_HEADER_SIZE+COOKIE_SIZE];
int hvr_size = 0, ret;
uint8_t digest[C_HASH_SIZE];

  if (key == NULL || key->data == NULL || key->size == 0)
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

/* send
 *  struct {
 *    ContentType type - 1 byte GNUTLS_HANDSHAKE;
 *    ProtocolVersion version; - 2 bytes (254,255)
 *    uint16 epoch; - 2 bytes (0, 0)
 *    uint48 sequence_number; - 4 bytes (0,0,0,0)
 *    uint16 length; - 2 bytes (COOKIE_SIZE+1+2)+DTLS_HANDSHAKE_HEADER_SIZE
 *    uint8_t fragment[DTLSPlaintext.length];
 *  } DTLSPlaintext;
 *
 *
 * struct {
 *    HandshakeType msg_type; 1 byte - GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST
 *    uint24 length; - COOKIE_SIZE+3
 *    uint16 message_seq; - 2 bytes (0,0)
 *    uint24 fragment_offset; - 3 bytes (0,0,0)
 *    uint24 fragment_length; - same as length
 * }
 *
 * struct {
 *   ProtocolVersion server_version;
 *   uint8_t cookie<0..32>;
 * } HelloVerifyRequest;
 */ 

  hvr[hvr_size++] = GNUTLS_HANDSHAKE;
  /* version */
  hvr[hvr_size++] = 254;
  hvr[hvr_size++] = 255;
  
  /* epoch + seq */
  memset(&hvr[hvr_size], 0, 8);
  hvr_size += 7;
  hvr[hvr_size++] = prestate->record_seq;

  /* length */
  _gnutls_write_uint16(DTLS_HANDSHAKE_HEADER_SIZE+COOKIE_SIZE+3, &hvr[hvr_size]);
  hvr_size += 2;

  /* now handshake headers */
  hvr[hvr_size++] = GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST;
  _gnutls_write_uint24(COOKIE_SIZE+3, &hvr[hvr_size]);
  hvr_size += 3;
  
  /* handshake seq */
  hvr[hvr_size++] = 0;
  hvr[hvr_size++] = prestate->hsk_write_seq;

  _gnutls_write_uint24(0, &hvr[hvr_size]);
  hvr_size += 3;

  _gnutls_write_uint24(COOKIE_SIZE+3, &hvr[hvr_size]);
  hvr_size += 3;

  /* version */
  hvr[hvr_size++] = 254;
  hvr[hvr_size++] = 255;
  hvr[hvr_size++] = COOKIE_SIZE;

  ret = _gnutls_hmac_fast(C_HASH, key->data, key->size, client_data, client_data_size, digest);
  if (ret < 0)
    return gnutls_assert_val(ret);

  memcpy(&hvr[hvr_size], digest, COOKIE_MAC_SIZE);
  hvr_size+= COOKIE_MAC_SIZE;

  ret = push_func(ptr, hvr, hvr_size);
  if (ret < 0)
    ret = GNUTLS_E_PUSH_ERROR;

  return ret;
}
Example #23
0
/* This function fragments and transmits a previously buffered
 * outgoing message. It accepts mtu_data which is a buffer to
 * be reused (should be set to NULL initially).
 */
static inline int
transmit_message (gnutls_session_t session,
		  mbuffer_st *bufel, uint8_t **buf)
{
  uint8_t *data, *mtu_data;
  int ret = 0;
  unsigned int offset, frag_len, data_size;
  const unsigned int mtu = gnutls_dtls_get_data_mtu(session) - DTLS_HANDSHAKE_HEADER_SIZE;

  if (bufel->type == GNUTLS_CHANGE_CIPHER_SPEC)
    {
      _gnutls_dtls_log ("DTLS[%p]: Sending Packet[%u] fragment %s(%d)\n",
			session, bufel->handshake_sequence,
			_gnutls_handshake2str (bufel->htype),
			bufel->htype);

      return _gnutls_send_int (session, bufel->type, -1,
        bufel->epoch, 
        _mbuffer_get_uhead_ptr(bufel), 
        _mbuffer_get_uhead_size(bufel), 0);
    }

  if (*buf == NULL) *buf = gnutls_malloc(mtu + DTLS_HANDSHAKE_HEADER_SIZE);
  if (*buf == NULL)
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

  mtu_data = *buf;

  data = _mbuffer_get_udata_ptr( bufel);
  data_size = _mbuffer_get_udata_size(bufel);

  /* Write fixed headers
   */

  /* Handshake type */
  mtu_data[0] = (uint8_t) bufel->htype;

  /* Total length */
  _gnutls_write_uint24 (data_size, &mtu_data[1]);

  /* Handshake sequence */
  _gnutls_write_uint16 (bufel->handshake_sequence, &mtu_data[4]);

  /* Chop up and send handshake message into mtu-size pieces. */
  for (offset=0; offset <= data_size; offset += mtu)
    {
      /* Calculate fragment length */
      if(offset + mtu > data_size)
        frag_len = data_size - offset;
      else
        frag_len = mtu;

      /* Fragment offset */
      _gnutls_write_uint24 (offset, &mtu_data[6]);

      /* Fragment length */
      _gnutls_write_uint24 (frag_len, &mtu_data[9]);

      memcpy (&mtu_data[DTLS_HANDSHAKE_HEADER_SIZE], data+offset, frag_len);

      _gnutls_dtls_log ("DTLS[%p]: Sending Packet[%u] fragment %s(%d) with "
			"length: %u, offset: %u, fragment length: %u\n",
			session, bufel->handshake_sequence,
			_gnutls_handshake2str (bufel->htype),
			bufel->htype, data_size, offset, frag_len);

      ret = _gnutls_send_int (session, bufel->type, bufel->htype, 
        bufel->epoch, mtu_data, DTLS_HANDSHAKE_HEADER_SIZE + frag_len, 0);
      if (ret < 0)
        {
          gnutls_assert();
          break;
        }
   }

  return ret;
}
Example #24
0
static int
gen_rsa_export_server_kx (gnutls_session_t session, opaque ** data)
{
  gnutls_rsa_params_t rsa_params;
  const bigint_t *rsa_mpis;
  size_t n_e, n_m;
  uint8_t *data_e, *data_m;
  int ret = 0, data_size;
  gnutls_cert *apr_cert_list;
  gnutls_privkey *apr_pkey;
  int apr_cert_list_length;
  gnutls_datum_t signature, ddata;
  cert_auth_info_t info;
  gnutls_certificate_credentials_t cred;

  cred = (gnutls_certificate_credentials_t)
    _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL);
  if (cred == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  /* find the appropriate certificate */
  if ((ret =
       _gnutls_get_selected_cert (session, &apr_cert_list,
				  &apr_cert_list_length, &apr_pkey)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  /* abort sending this message if we have a certificate
   * of 512 bits or less.
   */
  if (apr_pkey && _gnutls_mpi_get_nbits (apr_pkey->params[0]) <= 512)
    {
      gnutls_assert ();
      return GNUTLS_E_INT_RET_0;
    }

  rsa_params =
    _gnutls_certificate_get_rsa_params (cred->rsa_params, cred->params_func,
					session);
  rsa_mpis = _gnutls_rsa_params_to_mpi (rsa_params);
  if (rsa_mpis == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS;
    }

  if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE,
				    sizeof (cert_auth_info_st), 0)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  info = _gnutls_get_auth_info (session);
  _gnutls_rsa_export_set_pubkey (session, rsa_mpis[1], rsa_mpis[0]);

  _gnutls_mpi_print (rsa_mpis[0], NULL, &n_m);
  _gnutls_mpi_print (rsa_mpis[1], NULL, &n_e);

  (*data) = gnutls_malloc (n_e + n_m + 4);
  if (*data == NULL)
    {
      return GNUTLS_E_MEMORY_ERROR;
    }

  data_m = &(*data)[0];
  _gnutls_mpi_print (rsa_mpis[0], &data_m[2], &n_m);

  _gnutls_write_uint16 (n_m, data_m);

  data_e = &data_m[2 + n_m];
  _gnutls_mpi_print (rsa_mpis[1], &data_e[2], &n_e);

  _gnutls_write_uint16 (n_e, data_e);

  data_size = n_m + n_e + 4;


  /* Generate the signature. */

  ddata.data = *data;
  ddata.size = data_size;

  if (apr_cert_list_length > 0)
    {
      if ((ret =
	   _gnutls_tls_sign_params (session, &apr_cert_list[0],
				    apr_pkey, &ddata, &signature)) < 0)
	{
	  gnutls_assert ();
	  gnutls_free (*data);
	  *data = NULL;
	  return ret;
	}
    }
  else
    {
      gnutls_assert ();
      return data_size;		/* do not put a signature - ILLEGAL! */
    }

  *data = gnutls_realloc_fast (*data, data_size + signature.size + 2);
  if (*data == NULL)
    {
      _gnutls_free_datum (&signature);
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  _gnutls_write_datum16 (&((*data)[data_size]), signature);
  data_size += signature.size + 2;

  _gnutls_free_datum (&signature);

  return data_size;
}
Example #25
0
int
_gnutls_gen_extensions (gnutls_session_t session, opaque * data,
			size_t data_size)
{
  int size;
  uint16_t pos = 0;
  opaque *sdata;
  int sdata_size;
  size_t i;

  if (data_size < 2)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  /* allocate enough data for each extension.
   */
  sdata_size = data_size;
  sdata = gnutls_malloc (sdata_size);
  if (sdata == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  pos += 2;
  for (i = 0; i < extfunc_size; i++)
    {
      gnutls_extension_entry *p = &extfunc[i];

      if (p->send_func == NULL)
	continue;

      size = p->send_func (session, sdata, sdata_size);
      if (size > 0)
	{
	  if (data_size < pos + (size_t) size + 4)
	    {
	      gnutls_assert ();
	      gnutls_free (sdata);
	      return GNUTLS_E_INTERNAL_ERROR;
	    }

	  /* write extension type */
	  _gnutls_write_uint16 (p->type, &data[pos]);
	  pos += 2;

	  /* write size */
	  _gnutls_write_uint16 (size, &data[pos]);
	  pos += 2;

	  memcpy (&data[pos], sdata, size);
	  pos += size;

	  /* add this extension to the extension list
	   */
	  _gnutls_extension_list_add (session, p->type);

	  _gnutls_debug_log ("EXT[%p]: Sending extension %s\n",
			     session, p->name);
	}
      else if (size < 0)
	{
	  gnutls_assert ();
	  gnutls_free (sdata);
	  return size;
	}
    }

  size = pos;
  pos -= 2;			/* remove the size of the size header! */

  _gnutls_write_uint16 (pos, data);

  if (size == 2)
    {				/* empty */
      size = 0;
    }

  gnutls_free (sdata);
  return size;

}
Example #26
0
/* Format: 
 *      4 bytes the total security data size
 *      1 byte the entity type (client/server)
 *      1 byte the key exchange algorithm used
 *      1 byte the read cipher algorithm
 *      1 byte the read mac algorithm
 *      1 byte the read compression algorithm
 *
 *      1 byte the write cipher algorithm
 *      1 byte the write mac algorithm
 *      1 byte the write compression algorithm
 *
 *      1 byte the certificate type
 *      1 byte the protocol version
 *
 *      2 bytes the cipher suite
 *
 *      48 bytes the master secret
 *
 *      32 bytes the client random
 *      32 bytes the server random
 *
 *      1 byte the session ID size
 *      x bytes the session ID (32 bytes max)
 *
 *      4 bytes a timestamp
 *            -------------------
 *                MAX: 165 bytes
 *
 *      EXTENSIONS:
 *      2 bytes the record send size
 *      2 bytes the record recv size
 *
 *      1 byte the SRP username size
 *      x bytes the SRP username (MAX_SRP_USERNAME)
 *
 *      2 bytes the number of server name extensions (up to MAX_SERVER_NAME_EXTENSIONS)
 *      1 byte the first name type
 *      2 bytes the size of the first name 
 *      x bytes the first name (MAX_SERVER_NAME_SIZE)
 *       and so on...
 *
 *           --------------------
 *                MAX: 7+MAX_SRP_USERNAME+MAX_SERVER_NAME_EXTENSIONS*(3+MAX_SERVER_NAME_SIZE)
 */
static int
pack_security_parameters (gnutls_session_t session,
			  gnutls_datum_t * packed_session)
{
  int pos = 0;
  size_t len, init, i;

  /* move after the auth info stuff.
   */
  init =
    _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]) + 4 +
    PACK_HEADER_SIZE;

  pos = init + 4;		/* make some space to write later the size */

  packed_session->data[pos++] = session->security_parameters.entity;
  packed_session->data[pos++] = session->security_parameters.kx_algorithm;
  packed_session->data[pos++] =
    session->security_parameters.read_bulk_cipher_algorithm;
  packed_session->data[pos++] =
    session->security_parameters.read_mac_algorithm;
  packed_session->data[pos++] =
    session->security_parameters.read_compression_algorithm;
  packed_session->data[pos++] =
    session->security_parameters.write_bulk_cipher_algorithm;
  packed_session->data[pos++] =
    session->security_parameters.write_mac_algorithm;
  packed_session->data[pos++] =
    session->security_parameters.write_compression_algorithm;
  packed_session->data[pos++] =
    session->security_parameters.current_cipher_suite.suite[0];
  packed_session->data[pos++] =
    session->security_parameters.current_cipher_suite.suite[1];

  packed_session->data[pos++] = session->security_parameters.cert_type;
  packed_session->data[pos++] = session->security_parameters.version;

  memcpy (&packed_session->data[pos],
	  session->security_parameters.master_secret, TLS_MASTER_SIZE);
  pos += TLS_MASTER_SIZE;

  memcpy (&packed_session->data[pos],
	  session->security_parameters.client_random, TLS_RANDOM_SIZE);
  pos += TLS_RANDOM_SIZE;
  memcpy (&packed_session->data[pos],
	  session->security_parameters.server_random, TLS_RANDOM_SIZE);
  pos += TLS_RANDOM_SIZE;

  packed_session->data[pos++] = session->security_parameters.session_id_size;
  memcpy (&packed_session->data[pos], session->security_parameters.session_id,
	  session->security_parameters.session_id_size);
  pos += session->security_parameters.session_id_size;

  _gnutls_write_uint32 (session->security_parameters.timestamp,
			&packed_session->data[pos]);
  pos += 4;

  /* Extensions */
  _gnutls_write_uint16 (session->security_parameters.max_record_send_size,
			&packed_session->data[pos]);
  pos += 2;

  _gnutls_write_uint16 (session->security_parameters.max_record_recv_size,
			&packed_session->data[pos]);
  pos += 2;

  /* SRP */
  len =
    strlen ((char *) session->security_parameters.extensions.srp_username);
  packed_session->data[pos++] = len;
  memcpy (&packed_session->data[pos],
	  session->security_parameters.extensions.srp_username, len);
  pos += len;

  _gnutls_write_uint16 (session->security_parameters.extensions.
			server_names_size, &packed_session->data[pos]);
  pos += 2;

  for (i = 0; i < session->security_parameters.extensions.server_names_size;
       i++)
    {
      packed_session->data[pos++] =
	session->security_parameters.extensions.server_names[i].type;
      _gnutls_write_uint16 (session->security_parameters.extensions.
			    server_names[i].name_length,
			    &packed_session->data[pos]);
      pos += 2;

      memcpy (&packed_session->data[pos],
	      session->security_parameters.extensions.server_names[i].name,
	      session->security_parameters.extensions.server_names[i].
	      name_length);
      pos +=
	session->security_parameters.extensions.server_names[i].name_length;
    }

  /* write the total size */
  _gnutls_write_uint32 (pos - init - 4, &packed_session->data[init]);
  packed_session->size += pos - init;

  return 0;
}
Example #27
0
/* Format: 
 *      1 byte the credentials type
 *      4 bytes the size of the whole structure
 *        DH stuff
 *      2 bytes the size of secret key in bits
 *      4 bytes the size of the prime
 *      x bytes the prime
 *      4 bytes the size of the generator
 *      x bytes the generator
 *      4 bytes the size of the public key
 *      x bytes the public key
 *        RSA stuff
 *      4 bytes the size of the modulus
 *      x bytes the modulus
 *      4 bytes the size of the exponent
 *      x bytes the exponent
 *        CERTIFICATES
 *      4 bytes the length of the certificate list
 *      4 bytes the size of first certificate
 *      x bytes the certificate
 *       and so on...
 */
static int
pack_certificate_auth_info (gnutls_session_t session,
			    gnutls_datum_t * packed_session)
{
  unsigned int pos = 0, i;
  int cert_size, pack_size;
  cert_auth_info_t info = _gnutls_get_auth_info (session);


  if (info == NULL && session->key->auth_info_size != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if (info)
    {
      cert_size = 4;

      for (i = 0; i < info->ncerts; i++)
	cert_size += 4 + info->raw_certificate_list[i].size;

      pack_size = 2 + 4 + info->dh.prime.size +
	4 + info->dh.generator.size + 4 + info->dh.public_key.size +
	4 + info->rsa_export.modulus.size +
	4 + info->rsa_export.exponent.size + cert_size;
    }
  else
    pack_size = 0;

  packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);

  /* calculate the size and allocate the data.
   */
  packed_session->data =
    gnutls_malloc (packed_session->size + MAX_SEC_PARAMS);

  if (packed_session->data == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  packed_session->data[0] = GNUTLS_CRD_CERTIFICATE;
  _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]);
  pos += 4 + PACK_HEADER_SIZE;


  if (pack_size > 0)
    {

      _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]);
      pos += 2;

      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime);
      pos += 4 + info->dh.prime.size;
      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator);
      pos += 4 + info->dh.generator.size;
      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key);
      pos += 4 + info->dh.public_key.size;

      _gnutls_write_datum32 (&packed_session->data[pos],
			     info->rsa_export.modulus);
      pos += 4 + info->rsa_export.modulus.size;
      _gnutls_write_datum32 (&packed_session->data[pos],
			     info->rsa_export.exponent);
      pos += 4 + info->rsa_export.exponent.size;

      _gnutls_write_uint32 (info->ncerts, &packed_session->data[pos]);
      pos += 4;

      for (i = 0; i < info->ncerts; i++)
	{
	  _gnutls_write_datum32 (&packed_session->data[pos],
				 info->raw_certificate_list[i]);
	  pos += sizeof (uint32_t) + info->raw_certificate_list[i].size;
	}
    }

  return 0;
}
Example #28
0
static int
compute_psk_binder(gnutls_session_t session,
		   const mac_entry_st *prf, unsigned binders_length,
		   int exts_length, int ext_offset,
		   const gnutls_datum_t *psk, const gnutls_datum_t *client_hello,
		   bool resuming, void *out)
{
	int ret;
	unsigned client_hello_pos, extensions_len_pos;
	gnutls_buffer_st handshake_buf;
	uint8_t binder_key[MAX_HASH_SIZE];

	_gnutls_buffer_init(&handshake_buf);

	if (session->security_parameters.entity == GNUTLS_CLIENT) {
		if (session->internals.hsk_flags & HSK_HRR_RECEIVED) {
			ret = gnutls_buffer_append_data(&handshake_buf,
							(const void *) session->internals.handshake_hash_buffer.data,
							session->internals.handshake_hash_buffer.length);
			if (ret < 0) {
				gnutls_assert();
				goto error;
			}
		}

		client_hello_pos = handshake_buf.length;
		ret = gnutls_buffer_append_data(&handshake_buf, client_hello->data,
						client_hello->size);
		if (ret < 0) {
			gnutls_assert();
			goto error;
		}

		/* This is a ClientHello message */
		handshake_buf.data[client_hello_pos] = GNUTLS_HANDSHAKE_CLIENT_HELLO;

		/* At this point we have not yet added the binders to the ClientHello,
		 * but we have to overwrite the size field, pretending as if binders
		 * of the correct length were present.
		 */
		_gnutls_write_uint24(handshake_buf.length - client_hello_pos + binders_length - 2, &handshake_buf.data[client_hello_pos + 1]);
		_gnutls_write_uint16(handshake_buf.length - client_hello_pos + binders_length - ext_offset,
				     &handshake_buf.data[client_hello_pos + ext_offset]);
		extensions_len_pos = handshake_buf.length - client_hello_pos - exts_length - 2;
		_gnutls_write_uint16(exts_length + binders_length + 2,
				     &handshake_buf.data[client_hello_pos + extensions_len_pos]);
	} else {
		if (session->internals.hsk_flags & HSK_HRR_SENT) {
			if (unlikely(session->internals.handshake_hash_buffer.length <= client_hello->size)) {
				ret = gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
				goto error;
			}

			ret = gnutls_buffer_append_data(&handshake_buf,
							session->internals.handshake_hash_buffer.data,
							session->internals.handshake_hash_buffer.length - client_hello->size);
			if (ret < 0) {
				gnutls_assert();
				goto error;
			}
		}

		if (unlikely(client_hello->size <= binders_length)) {
			ret = gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
			goto error;
		}

		ret = gnutls_buffer_append_data(&handshake_buf,
						(const void *) client_hello->data,
						client_hello->size - binders_length);
		if (ret < 0) {
			gnutls_assert();
			goto error;
		}
	}

	ret = compute_binder_key(prf,
				 psk->data, psk->size, resuming,
				 binder_key);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = _gnutls13_compute_finished(prf, binder_key,
					 &handshake_buf,
					 out);
	if (ret < 0) {
		gnutls_assert();
		goto error;
	}

	ret = 0;
error:
	_gnutls_buffer_clear(&handshake_buf);
	return ret;
}
Example #29
0
static int
client_send_params(gnutls_session_t session,
		   gnutls_buffer_t extdata,
		   const gnutls_psk_client_credentials_t cred)
{
	int ret, ext_offset = 0;
	uint8_t binder_value[MAX_HASH_SIZE];
	size_t spos;
	gnutls_datum_t username = {NULL, 0};
	gnutls_datum_t user_key = {NULL, 0}, rkey = {NULL, 0};
	gnutls_datum_t client_hello;
	unsigned next_idx;
	const mac_entry_st *prf_res = NULL;
	const mac_entry_st *prf_psk = NULL;
	struct timespec cur_time;
	uint32_t ticket_age, ob_ticket_age;
	int free_username = 0;
	psk_auth_info_t info = NULL;
	unsigned psk_id_len = 0;
	unsigned binders_len, binders_pos;

	if (((session->internals.flags & GNUTLS_NO_TICKETS) ||
	    session->internals.tls13_ticket.ticket.data == NULL) &&
	    (!cred || !_gnutls_have_psk_credentials(cred, session))) {

		return 0;
	}

	binders_len = 0;

	/* placeholder to be filled later */
	spos = extdata->length;
	ret = _gnutls_buffer_append_prefix(extdata, 16, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* First, let's see if we have a session ticket to send */
	if (!(session->internals.flags & GNUTLS_NO_TICKETS) &&
	    session->internals.tls13_ticket.ticket.data != NULL) {
		/* We found a session ticket */
		if (unlikely(session->internals.tls13_ticket.prf == NULL)) {
			_gnutls13_session_ticket_unset(session);
			ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
			goto cleanup;
		}

		prf_res = session->internals.tls13_ticket.prf;

		gnutls_gettime(&cur_time);
		if (unlikely(_gnutls_timespec_cmp(&cur_time,
						  &session->internals.
						  tls13_ticket.
						  arrival_time) < 0)) {
			gnutls_assert();
			_gnutls13_session_ticket_unset(session);
			goto ignore_ticket;
		}

		/* Check whether the ticket is stale */
		ticket_age = timespec_sub_ms(&cur_time,
					     &session->internals.tls13_ticket.
					     arrival_time);
		if (ticket_age / 1000 > session->internals.tls13_ticket.lifetime) {
			_gnutls13_session_ticket_unset(session);
			goto ignore_ticket;
		}

		ret = compute_psk_from_ticket(&session->internals.tls13_ticket, &rkey);
		if (ret < 0) {
			_gnutls13_session_ticket_unset(session);
			goto ignore_ticket;
		}

		/* Calculate obfuscated ticket age, in milliseconds, mod 2^32 */
		ob_ticket_age = ticket_age + session->internals.tls13_ticket.age_add;

		if ((ret = _gnutls_buffer_append_data_prefix(extdata, 16,
							     session->internals.tls13_ticket.ticket.data,
							     session->internals.tls13_ticket.ticket.size)) < 0) {
			gnutls_assert();
			goto cleanup;
		}

		/* Now append the obfuscated ticket age */
		if ((ret = _gnutls_buffer_append_prefix(extdata, 32, ob_ticket_age)) < 0) {
			gnutls_assert();
			goto cleanup;
		}

		psk_id_len += 6 + session->internals.tls13_ticket.ticket.size;
		binders_len += 1 + _gnutls_mac_get_algo_len(prf_res);
	}

 ignore_ticket:
	if (cred && _gnutls_have_psk_credentials(cred, session)) {
		gnutls_datum_t tkey;

		if (cred->binder_algo == NULL) {
			gnutls_assert();
			ret = gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
			goto cleanup;
		}

		prf_psk = cred->binder_algo;

		ret = _gnutls_find_psk_key(session, cred, &username, &tkey, &free_username);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		if (username.size == 0 || username.size > UINT16_MAX) {
			ret = gnutls_assert_val(GNUTLS_E_INVALID_PASSWORD);
			goto cleanup;
		}

		if (!free_username) {
			/* we need to copy the key */
			ret = _gnutls_set_datum(&user_key, tkey.data, tkey.size);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}
		} else {
			user_key.data = tkey.data;
			user_key.size = tkey.size;
		}

		ret = _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
		assert(info != NULL);

		memcpy(info->username, username.data, username.size);
		info->username[username.size] = 0;

		if ((ret = _gnutls_buffer_append_data_prefix(extdata, 16,
							     username.data,
							     username.size)) < 0) {
			gnutls_assert();
			goto cleanup;
		}

		/* Now append the obfuscated ticket age */
		if ((ret = _gnutls_buffer_append_prefix(extdata, 32, 0)) < 0) {
			gnutls_assert();
			goto cleanup;
		}

		psk_id_len += 6 + username.size;
		binders_len += 1 + _gnutls_mac_get_algo_len(prf_psk);
	}

	/* if no tickets or identities to be sent */
	if (psk_id_len == 0) {
		/* reset extensions buffer */
		extdata->length = spos;
		return 0;
	}

	_gnutls_write_uint16(psk_id_len, &extdata->data[spos]);

	binders_pos = extdata->length-spos;
	ext_offset = _gnutls_ext_get_extensions_offset(session);

	/* Compute the binders. extdata->data points to the start
	 * of this client hello. */
	assert(extdata->length >= sizeof(mbuffer_st));
	assert(ext_offset >= (ssize_t)sizeof(mbuffer_st));
	ext_offset -= sizeof(mbuffer_st);
	client_hello.data = extdata->data+sizeof(mbuffer_st);
	client_hello.size = extdata->length-sizeof(mbuffer_st);

	next_idx = 0;

	ret = _gnutls_buffer_append_prefix(extdata, 16, binders_len);
	if (ret < 0) {
		gnutls_assert_val(ret);
		goto cleanup;
	}

	if (prf_res && rkey.size > 0) {
		ret = compute_psk_binder(session, prf_res,
					 binders_len, binders_pos,
					 ext_offset, &rkey, &client_hello, 1,
					 binder_value);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		/* Associate the selected pre-shared key with the session */
		gnutls_free(session->key.binders[next_idx].psk.data);
		session->key.binders[next_idx].psk.data = rkey.data;
		session->key.binders[next_idx].psk.size = rkey.size;
		rkey.data = NULL;

		session->key.binders[next_idx].prf = prf_res;
		session->key.binders[next_idx].resumption = 1;
		session->key.binders[next_idx].idx = next_idx;

		_gnutls_handshake_log("EXT[%p]: sent PSK resumption identity (%d)\n", session, next_idx);

		next_idx++;

		/* Add the binder */
		ret = _gnutls_buffer_append_data_prefix(extdata, 8, binder_value, prf_res->output_size);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		session->internals.hsk_flags |= HSK_TLS13_TICKET_SENT;
	}

	if (prf_psk && user_key.size > 0 && info) {
		ret = compute_psk_binder(session, prf_psk,
					 binders_len, binders_pos,
					 ext_offset, &user_key, &client_hello, 0,
					 binder_value);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		/* Associate the selected pre-shared key with the session */
		gnutls_free(session->key.binders[next_idx].psk.data);
		session->key.binders[next_idx].psk.data = user_key.data;
		session->key.binders[next_idx].psk.size = user_key.size;
		user_key.data = NULL;

		session->key.binders[next_idx].prf = prf_psk;
		session->key.binders[next_idx].resumption = 0;
		session->key.binders[next_idx].idx = next_idx;

		_gnutls_handshake_log("EXT[%p]: sent PSK identity '%s' (%d)\n", session, info->username, next_idx);

		next_idx++;

		/* Add the binder */
		ret = _gnutls_buffer_append_data_prefix(extdata, 8, binder_value, prf_psk->output_size);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}

	ret = 0;

cleanup:
	if (free_username)
		_gnutls_free_datum(&username);

	_gnutls_free_temp_key_datum(&user_key);
	_gnutls_free_temp_key_datum(&rkey);

	return ret;
}
Example #30
0
/* Format: 
 *      1 byte the credentials type
 *      4 bytes the size of the whole structure
 *      4 bytes the size of the PSK username (x)
 *      x bytes the PSK username
 *      2 bytes the size of secret key in bits
 *      4 bytes the size of the prime
 *      x bytes the prime
 *      4 bytes the size of the generator
 *      x bytes the generator
 *      4 bytes the size of the public key
 *      x bytes the public key
 */
static int
pack_psk_auth_info (gnutls_session_t session, gnutls_datum_t * packed_session)
{
  psk_auth_info_t info;
  int pack_size, username_size = 0, pos;

  info = _gnutls_get_auth_info (session);

  if (info == NULL && session->key->auth_info_size != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if (info)
    {
      username_size = strlen (info->username) + 1;	/* include the terminating null */
      pack_size = username_size +
	2 + 4 * 3 + info->dh.prime.size + info->dh.generator.size +
	info->dh.public_key.size;
    }
  else
    pack_size = 0;

  packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t);

  /* calculate the size and allocate the data.
   */
  packed_session->data =
    gnutls_malloc (packed_session->size + MAX_SEC_PARAMS);

  if (packed_session->data == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  pos = 0;

  packed_session->data[pos] = GNUTLS_CRD_PSK;
  pos++;

  _gnutls_write_uint32 (pack_size, &packed_session->data[pos]);
  pos += 4;


  if (pack_size > 0)
    {
      _gnutls_write_uint32 (username_size, &packed_session->data[pos]);
      pos += 4;

      memcpy (&packed_session->data[pos], info->username, username_size);
      pos += username_size;

      _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]);
      pos += 2;

      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime);
      pos += 4 + info->dh.prime.size;
      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator);
      pos += 4 + info->dh.generator.size;
      _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key);
      pos += 4 + info->dh.public_key.size;

    }


  return 0;
}