Exemple #1
0
static int
proc_ecdhe_psk_server_kx(gnutls_session_t session, uint8_t * data,
			 size_t _data_size)
{

	int ret, psk_size;
	ssize_t data_size = _data_size;

	/* set auth_info */
	if ((ret =
	     _gnutls_auth_info_set(session, GNUTLS_CRD_PSK,
				   sizeof(psk_auth_info_st), 1)) < 0) {
		gnutls_assert();
		return ret;
	}

	DECR_LEN(data_size, 2);
	psk_size = _gnutls_read_uint16(data);
	DECR_LEN(data_size, psk_size);
	data += 2 + psk_size;

	ret = _gnutls_proc_ecdh_common_server_kx(session, data, data_size);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	return 0;
}
Exemple #2
0
int
proc_anon_server_kx (gnutls_session_t session, opaque * data,
                     size_t _data_size)
{

  int ret;

  /* set auth_info */
  if ((ret =
       _gnutls_auth_info_set (session, GNUTLS_CRD_ANON,
                              sizeof (anon_auth_info_st), 1)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  ret = _gnutls_proc_dh_common_server_kx (session, data, _data_size, 0);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  return 0;
}
Exemple #3
0
static int
gen_ecdhe_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
{
	int ret = 0;
	gnutls_certificate_credentials_t cred;

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

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

	ret =
	    _gnutls_ecdh_common_print_server_kx(session, data,
						_gnutls_session_ecc_curve_get
						(session));
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	/* Generate the signature. */
	return _gnutls_gen_dhe_signature(session, data, data->data,
					 data->length);
}
Exemple #4
0
/* just read the username from the client key exchange.
 */
int
_gnutls_proc_psk_client_kx (gnutls_session_t session, opaque * data,
                            size_t _data_size)
{
  ssize_t data_size = _data_size;
  int ret;
  gnutls_datum_t username;
  gnutls_psk_server_credentials_t cred;
  psk_auth_info_t info;

  cred = (gnutls_psk_server_credentials_t)
    _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL);

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

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

  DECR_LEN (data_size, 2);
  username.size = _gnutls_read_uint16 (&data[0]);

  DECR_LEN (data_size, username.size);

  username.data = &data[2];


  /* copy the username to the auth info structures
   */
  info = _gnutls_get_auth_info (session);

  if (username.size > MAX_USERNAME_SIZE)
    {
      gnutls_assert ();
      return GNUTLS_E_ILLEGAL_SRP_USERNAME;
    }

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

  ret = _gnutls_set_psk_session_key (session, NULL);
  if (ret < 0)
    {
      gnutls_assert ();
      goto error;
    }

  ret = 0;

error:
  return ret;
}
Exemple #5
0
static int
unpack_psk_auth_info (gnutls_session_t session, gnutls_buffer_st * ps)
{
  size_t username_size, hint_size;
  int ret;
  psk_auth_info_t info;

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

  info = _gnutls_get_auth_info (session);
  if (info == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  BUFFER_POP_NUM (ps, username_size);
  if (username_size > sizeof (info->username))
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  BUFFER_POP (ps, info->username, username_size);

  BUFFER_POP_NUM (ps, hint_size);
  if (hint_size > sizeof (info->hint))
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }
  BUFFER_POP (ps, info->hint, hint_size);

  BUFFER_POP_NUM (ps, info->dh.secret_bits);

  BUFFER_POP_DATUM (ps, &info->dh.prime);
  BUFFER_POP_DATUM (ps, &info->dh.generator);
  BUFFER_POP_DATUM (ps, &info->dh.public_key);

  ret = 0;

error:
  _gnutls_free_datum (&info->dh.prime);
  _gnutls_free_datum (&info->dh.generator);
  _gnutls_free_datum (&info->dh.public_key);

  return ret;
}
Exemple #6
0
static int
gen_dhe_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
{
	bigint_t g, p;
	const bigint_t *mpis;
	int ret = 0;
	gnutls_certificate_credentials_t cred;
	gnutls_dh_params_t dh_params;

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


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

	dh_params =
	    _gnutls_get_dh_params(cred->dh_params, cred->params_func,
				  session);
	mpis = _gnutls_dh_params_to_mpi(dh_params);
	if (mpis == NULL) {
		gnutls_assert();
		return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
	}

	p = mpis[0];
	g = mpis[1];

	_gnutls_dh_set_group(session, g, p);

	ret = _gnutls_set_dh_pk_params(session, g, p, dh_params->q_bits);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret =
	    _gnutls_dh_common_print_server_kx(session, data);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	/* Generate the signature. */
	return _gnutls_gen_dhe_signature(session, data, data->data,
					 data->length);
}
Exemple #7
0
/* just read the hint from the server key exchange.
 */
static int
_gnutls_proc_psk_server_kx(gnutls_session_t session, uint8_t * data,
			   size_t _data_size)
{
	ssize_t data_size = _data_size;
	int ret;
	gnutls_datum_t hint;
	gnutls_psk_client_credentials_t cred;
	psk_auth_info_t info;

	cred = (gnutls_psk_client_credentials_t)
	    _gnutls_get_cred(session, GNUTLS_CRD_PSK);

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

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

	DECR_LENGTH_RET(data_size, 2, 0);
	hint.size = _gnutls_read_uint16(&data[0]);

	DECR_LEN(data_size, hint.size);

	hint.data = &data[2];

	/* copy the hint to the auth info structures
	 */
	info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
	if (info == NULL) {
		gnutls_assert();
		return GNUTLS_E_INTERNAL_ERROR;
	}

	if (hint.size > sizeof(info->hint)-1) {
		gnutls_assert();
		return GNUTLS_E_ILLEGAL_SRP_USERNAME;
	}

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

	ret = 0;

	return ret;
}
Exemple #8
0
static int
gen_dhe_psk_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
{
	bigint_t g, p;
	const bigint_t *mpis;
	int ret;
	gnutls_dh_params_t dh_params;
	gnutls_psk_server_credentials_t cred;

	cred = (gnutls_psk_server_credentials_t)
	    _gnutls_get_cred(session, GNUTLS_CRD_PSK, NULL);
	if (cred == NULL) {
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	dh_params =
	    _gnutls_get_dh_params(cred->dh_params, cred->params_func,
				  session);
	mpis = _gnutls_dh_params_to_mpi(dh_params);
	if (mpis == NULL) {
		gnutls_assert();
		return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
	}

	p = mpis[0];
	g = mpis[1];

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

	_gnutls_dh_set_group(session, g, p);

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

	ret =
	    _gnutls_dh_common_print_server_kx(session, g, p,
					      dh_params->q_bits, data);
	if (ret < 0)
		gnutls_assert();

	return ret;
}
Exemple #9
0
static int
unpack_srp_auth_info (gnutls_session_t session,
		      const gnutls_datum_t * packed_session)
{
  size_t username_size;
  int ret;
  srp_server_auth_info_t info;

  if (packed_session->data[0] != GNUTLS_CRD_SRP)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  username_size =
    _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]);

  if (username_size == 0)
    return 0;			/* nothing to be done */

  /* a simple check for integrity */
  if (username_size + 4 + PACK_HEADER_SIZE > packed_session->size)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

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

  info = _gnutls_get_auth_info (session);
  if (info == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  memcpy (info->username,
	  &packed_session->data[PACK_HEADER_SIZE + sizeof (uint32_t)],
	  username_size);

  return 0;
}
Exemple #10
0
static int
unpack_anon_auth_info (gnutls_session_t session, gnutls_buffer_st * ps)
{
  int ret;
  size_t pack_size;
  anon_auth_info_t info = NULL;

  BUFFER_POP_NUM (ps, pack_size);

  if (pack_size == 0)
    return 0;                   /* nothing to be done */

  /* client and server have the same auth_info here
   */
  ret =
    _gnutls_auth_info_set (session, GNUTLS_CRD_ANON,
                           sizeof (anon_auth_info_st), 1);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  info = _gnutls_get_auth_info (session);
  if (info == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  BUFFER_POP_NUM (ps, info->dh.secret_bits);

  BUFFER_POP_DATUM (ps, &info->dh.prime);
  BUFFER_POP_DATUM (ps, &info->dh.generator);
  BUFFER_POP_DATUM (ps, &info->dh.public_key);

  return 0;

error:
  if (info)
    {
      _gnutls_free_datum (&info->dh.prime);
      _gnutls_free_datum (&info->dh.generator);
      _gnutls_free_datum (&info->dh.public_key);
    }

  return ret;
}
Exemple #11
0
static int
gen_anon_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
{
  bigint_t g, p;
  const bigint_t *mpis;
  int ret;
  gnutls_dh_params_t dh_params;
  gnutls_anon_server_credentials_t cred;

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

  dh_params =
    _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
  mpis = _gnutls_dh_params_to_mpi (dh_params);
  if (mpis == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
    }

  p = mpis[0];
  g = mpis[1];

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

  _gnutls_dh_set_group (session, g, p);

  ret = _gnutls_dh_common_print_server_kx (session, g, p, data, 0);
  if (ret < 0)
    {
      gnutls_assert ();
    }

  return ret;
}
Exemple #12
0
static int
unpack_srp_auth_info (gnutls_session_t session, gnutls_buffer_st * ps)
{
  size_t username_size;
  int ret;
  srp_server_auth_info_t info;

  BUFFER_POP_NUM (ps, username_size);
  if (username_size > sizeof (info->username))
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }


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

  info = _gnutls_get_auth_info (session);
  if (info == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  BUFFER_POP (ps, info->username, username_size);

  ret = 0;

error:
  return ret;
}
Exemple #13
0
static int
gen_ecdhe_psk_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
{
	int ret;

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

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

	ret = _gnutls_ecdh_common_print_server_kx(session, data,
						  _gnutls_session_ecc_curve_get
						  (session));
	if (ret < 0)
		gnutls_assert();

	return ret;
}
Exemple #14
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;
}
Exemple #15
0
static int
proc_psk_client_kx (gnutls_session_t session, opaque * data,
		    size_t _data_size)
{
  int bits;
  int ret;
  mpi_t p, g;
  gnutls_dh_params_t dh_params;
  const mpi_t *mpis;
  gnutls_psk_server_credentials_t cred;
  psk_auth_info_t info;
  gnutls_datum_t username;
  ssize_t data_size = _data_size;

  cred = (gnutls_psk_server_credentials_t)
    _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL);

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

  bits = _gnutls_dh_get_allowed_prime_bits (session);

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

  dh_params =
    _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
  mpis = _gnutls_dh_params_to_mpi (dh_params);
  if (mpis == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
    }

  p = mpis[0];
  g = mpis[1];

  DECR_LEN (data_size, 2);
  username.size = _gnutls_read_uint16 (&data[0]);

  DECR_LEN (data_size, username.size);

  username.data = &data[2];

  /* copy the username to the auth info structures
   */
  info = _gnutls_get_auth_info (session);

  if (username.size > MAX_SRP_USERNAME)
    {
      gnutls_assert ();
      return GNUTLS_E_ILLEGAL_SRP_USERNAME;
    }

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

  /* Adjust the data */
  data += username.size + 2;

  ret = _gnutls_proc_dh_common_client_kx (session, data, data_size, g, p);

  return ret;

}
Exemple #16
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,
			  gnutls_buffer_st * data)
{
	int ret;
	char *username;
	SRP_PWD_ENTRY *pwd_entry;
	srp_server_auth_info_t info;
	size_t tmp_size;
	extension_priv_data_t epriv;
	srp_ext_st *priv;

	ret =
	    _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRP,
					 &epriv);
	if (ret < 0) {		/* peer didn't send a username */
		gnutls_assert();
		return GNUTLS_E_UNKNOWN_SRP_USERNAME;
	}
	priv = epriv;

	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, GNUTLS_CRD_SRP);
	if (info == NULL)
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	username = info->username;

	_gnutls_str_cpy(username, MAX_USERNAME_SIZE, priv->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_init_scan_nz(&G, pwd_entry->g.data, tmp_size) < 0) {
		gnutls_assert();
		ret = GNUTLS_E_MPI_SCAN_FAILED;
		goto cleanup;
	}

	tmp_size = pwd_entry->n.size;
	if (_gnutls_mpi_init_scan_nz(&N, pwd_entry->n.data, tmp_size) < 0) {
		gnutls_assert();
		ret = GNUTLS_E_MPI_SCAN_FAILED;
		goto cleanup;
	}

	tmp_size = pwd_entry->v.size;
	if (_gnutls_mpi_init_scan_nz(&V, pwd_entry->v.data, tmp_size) < 0) {
		gnutls_assert();
		ret = GNUTLS_E_MPI_SCAN_FAILED;
		goto cleanup;
	}

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

	/* copy N (mod n) 
	 */
	ret =
	    _gnutls_buffer_append_data_prefix(data, 16, pwd_entry->n.data,
					      pwd_entry->n.size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* copy G (generator) to data 
	 */
	ret =
	    _gnutls_buffer_append_data_prefix(data, 16, pwd_entry->g.data,
					      pwd_entry->g.size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* copy the salt 
	 */
	ret =
	    _gnutls_buffer_append_data_prefix(data, 8,
					      pwd_entry->salt.data,
					      pwd_entry->salt.size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* Copy the B value
	 */

	ret = _gnutls_buffer_append_mpi(data, 16, B, 0);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	_gnutls_mpi_log("SRP B: ", B);

	ret = data->length;

      cleanup:
	_gnutls_srp_entry_free(pwd_entry);
	return ret;
}
Exemple #17
0
static int
gen_rsa_export_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
{
  gnutls_rsa_params_t rsa_params;
  const bigint_t *rsa_mpis;
  int ret = 0;
  gnutls_pcert_st *apr_cert_list;
  gnutls_privkey_t apr_pkey;
  int apr_cert_list_length;
  gnutls_datum_t signature, ddata;
  gnutls_certificate_credentials_t cred;
  gnutls_sign_algorithm_t sign_algo;
  unsigned int bits = 0;

  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.
   */
  gnutls_privkey_get_pk_algorithm (apr_pkey, &bits);
  if (apr_pkey && bits <= 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;
    }

  _gnutls_rsa_export_set_pubkey (session, rsa_mpis[1], rsa_mpis[0]);

  ret = _gnutls_buffer_append_mpi( data, 16, rsa_mpis[0], 0);
  if (ret < 0)
    return gnutls_assert_val(ret);

  ret = _gnutls_buffer_append_mpi( data, 16, rsa_mpis[1], 0);
  if (ret < 0)
    return gnutls_assert_val(ret);

  /* Generate the signature. */

  ddata.data = data->data;
  ddata.size = data->length;

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

  ret = _gnutls_buffer_append_data_prefix( data, 16, signature.data, signature.size);
  _gnutls_free_datum (&signature);

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

  return data->length;
}
Exemple #18
0
static int
unpack_psk_auth_info (gnutls_session_t session,
		      const gnutls_datum_t * packed_session)
{
  size_t username_size;
  size_t pack_size;
  int pos = 0, size, ret;
  psk_auth_info_t info;

  if (packed_session->data[0] != GNUTLS_CRD_PSK)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  pack_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]);
  pos += PACK_HEADER_SIZE + 4;


  if (pack_size == 0)
    return 0;			/* nothing to be done */

  /* a simple check for integrity */
  if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  /* client and serer have the same auth_info here
   */
  ret =
    _gnutls_auth_info_set (session, GNUTLS_CRD_PSK,
			   sizeof (psk_auth_info_st), 1);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  info = _gnutls_get_auth_info (session);
  if (info == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  username_size = _gnutls_read_uint32 (&packed_session->data[pos]);
  pos += 4;

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

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

  size = _gnutls_read_uint32 (&packed_session->data[pos]);
  pos += 4;
  ret = _gnutls_set_datum (&info->dh.prime, &packed_session->data[pos], size);
  if (ret < 0)
    {
      gnutls_assert ();
      goto error;
    }
  pos += size;

  size = _gnutls_read_uint32 (&packed_session->data[pos]);
  pos += 4;
  ret =
    _gnutls_set_datum (&info->dh.generator, &packed_session->data[pos], size);
  if (ret < 0)
    {
      gnutls_assert ();
      goto error;
    }
  pos += size;

  size = _gnutls_read_uint32 (&packed_session->data[pos]);
  pos += 4;
  ret =
    _gnutls_set_datum (&info->dh.public_key, &packed_session->data[pos],
		       size);
  if (ret < 0)
    {
      gnutls_assert ();
      goto error;
    }
  pos += size;

  return 0;

error:
  _gnutls_free_datum (&info->dh.prime);
  _gnutls_free_datum (&info->dh.generator);
  _gnutls_free_datum (&info->dh.public_key);
  return ret;
}
Exemple #19
0
/* Upack certificate info.
 */
static int
unpack_certificate_auth_info (gnutls_session_t session,
			      const gnutls_datum_t * packed_session)
{
  int pos = 0, size, ret;
  unsigned int i = 0, j;
  size_t pack_size;
  cert_auth_info_t info;

  if (packed_session->data[0] != GNUTLS_CRD_CERTIFICATE)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  pack_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]);
  pos += PACK_HEADER_SIZE + 4;

  if (pack_size == 0)
    return 0;			/* nothing to be done */

  /* a simple check for integrity */
  if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  /* client and server have the same auth_info here
   */
  ret =
    _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE,
			   sizeof (cert_auth_info_st), 1);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  info = _gnutls_get_auth_info (session);
  if (info == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

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

  size = _gnutls_read_uint32 (&packed_session->data[pos]);
  pos += 4;
  ret = _gnutls_set_datum (&info->dh.prime, &packed_session->data[pos], size);
  if (ret < 0)
    {
      gnutls_assert ();
      goto error;
    }
  pos += size;

  size = _gnutls_read_uint32 (&packed_session->data[pos]);
  pos += 4;
  ret =
    _gnutls_set_datum (&info->dh.generator, &packed_session->data[pos], size);
  if (ret < 0)
    {
      gnutls_assert ();
      goto error;
    }
  pos += size;

  size = _gnutls_read_uint32 (&packed_session->data[pos]);
  pos += 4;
  ret =
    _gnutls_set_datum (&info->dh.public_key, &packed_session->data[pos],
		       size);
  if (ret < 0)
    {
      gnutls_assert ();
      goto error;
    }
  pos += size;

  size = _gnutls_read_uint32 (&packed_session->data[pos]);
  pos += 4;
  ret =
    _gnutls_set_datum (&info->rsa_export.modulus,
		       &packed_session->data[pos], size);
  if (ret < 0)
    {
      gnutls_assert ();
      goto error;
    }
  pos += size;

  size = _gnutls_read_uint32 (&packed_session->data[pos]);
  pos += 4;
  ret =
    _gnutls_set_datum (&info->rsa_export.exponent,
		       &packed_session->data[pos], size);
  if (ret < 0)
    {
      gnutls_assert ();
      goto error;
    }
  pos += size;

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

  if (info->ncerts > 0)
    {
      info->raw_certificate_list =
	gnutls_calloc (1, sizeof (gnutls_datum_t) * info->ncerts);
      if (info->raw_certificate_list == NULL)
	{
	  gnutls_assert ();
	  ret = GNUTLS_E_MEMORY_ERROR;
	  goto error;
	}
    }

  for (i = 0; i < info->ncerts; i++)
    {
      size = _gnutls_read_uint32 (&packed_session->data[pos]);
      pos += sizeof (uint32_t);

      ret =
	_gnutls_set_datum (&info->raw_certificate_list[i],
			   &packed_session->data[pos], size);
      pos += size;

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


  return 0;

error:
  _gnutls_free_datum (&info->dh.prime);
  _gnutls_free_datum (&info->dh.generator);
  _gnutls_free_datum (&info->dh.public_key);

  _gnutls_free_datum (&info->rsa_export.modulus);
  _gnutls_free_datum (&info->rsa_export.exponent);

  for (j = 0; j < i; j++)
    _gnutls_free_datum (&info->raw_certificate_list[j]);

  gnutls_free (info->raw_certificate_list);

  return ret;

}
Exemple #20
0
static int
proc_ecdhe_psk_client_kx(gnutls_session_t session, uint8_t * data,
			 size_t _data_size)
{
	int ret;
	gnutls_psk_server_credentials_t cred;
	gnutls_datum_t psk_key;
	psk_auth_info_t info;
	gnutls_datum_t username;
	ssize_t data_size = _data_size;

	cred = (gnutls_psk_server_credentials_t)
	    _gnutls_get_cred(session, GNUTLS_CRD_PSK, NULL);

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

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

	DECR_LEN(data_size, 2);
	username.size = _gnutls_read_uint16(&data[0]);

	DECR_LEN(data_size, username.size);

	username.data = &data[2];

	/* copy the username to the auth info structures
	 */
	info = _gnutls_get_auth_info(session);

	if (username.size > MAX_USERNAME_SIZE) {
		gnutls_assert();
		return GNUTLS_E_ILLEGAL_SRP_USERNAME;
	}

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

	/* Adjust the data */
	data += username.size + 2;

	/* should never fail. It will always return a key even if it is
	 * a random one */
	ret =
	    _gnutls_psk_pwd_find_entry(session, info->username, &psk_key);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret = _gnutls_proc_ecdh_common_client_kx(session, data, data_size,
						 _gnutls_session_ecc_curve_get
						 (session), &psk_key);

	_gnutls_free_datum(&psk_key);

	return ret;
}
Exemple #21
0
static int
gen_dhe_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
{
  bigint_t g, p;
  const bigint_t *mpis;
  int ret = 0, data_size;
  gnutls_pcert_st *apr_cert_list;
  gnutls_privkey_t apr_pkey;
  int apr_cert_list_length;
  gnutls_datum_t signature = { NULL, 0 }, ddata;
  gnutls_certificate_credentials_t cred;
  gnutls_dh_params_t dh_params;
  gnutls_sign_algorithm_t sign_algo;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);

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

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

  if (!_gnutls_session_is_ecc (session))
    {
      dh_params =
        _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
      mpis = _gnutls_dh_params_to_mpi (dh_params);
      if (mpis == NULL)
        {
          gnutls_assert ();
          return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
        }

      p = mpis[0];
      g = mpis[1];

      _gnutls_dh_set_group (session, g, p);

      ret = _gnutls_dh_common_print_server_kx (session, g, p, dh_params->q_bits, data);
    }
  else
    {
      ret = _gnutls_ecdh_common_print_server_kx (session, data, _gnutls_session_ecc_curve_get(session));
    }

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

  /* Generate the signature. */

  ddata.data = data->data;
  ddata.size = data->length;

  if (apr_cert_list_length > 0)
    {
      if ((ret =
           _gnutls_handshake_sign_data (session, &apr_cert_list[0],
                                        apr_pkey, &ddata, &signature,
                                        &sign_algo)) < 0)
        {
          gnutls_assert ();
          goto cleanup;
        }
    }
  else
    {
      gnutls_assert ();
      ret = data_size;         /* do not put a signature - ILLEGAL! */
      goto cleanup;
    }

  if (_gnutls_version_has_selectable_sighash (ver))
    {
      const sign_algorithm_st *aid;
      uint8_t p[2];

      if (sign_algo == GNUTLS_SIGN_UNKNOWN)
        {
          ret = GNUTLS_E_UNKNOWN_ALGORITHM;
          goto cleanup;
        }

      aid = _gnutls_sign_to_tls_aid (sign_algo);
      if (aid == NULL)
        {
          gnutls_assert();
          ret = GNUTLS_E_UNKNOWN_ALGORITHM;
          goto cleanup;
        }
      
      p[0] = aid->hash_algorithm;
      p[1] = aid->sign_algorithm;
      
      ret = _gnutls_buffer_append_data(data, p, 2);
      if (ret < 0)
        {
          gnutls_assert();
          goto cleanup;
        }
    }

  ret = _gnutls_buffer_append_data_prefix(data, 16, signature.data, signature.size);
  if (ret < 0)
    {
      gnutls_assert();
    }

  ret = data->length;

cleanup:
  _gnutls_free_datum (&signature);
  return ret;

}
Exemple #22
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;
}
Exemple #23
0
static int
gen_dhe_server_kx (gnutls_session_t session, opaque ** data)
{
  bigint_t g, p;
  const bigint_t *mpis;
  int ret = 0, data_size;
  gnutls_cert *apr_cert_list;
  gnutls_privkey_t apr_pkey;
  int apr_cert_list_length;
  gnutls_datum_t signature = { NULL, 0 }, ddata;
  gnutls_certificate_credentials_t cred;
  gnutls_dh_params_t dh_params;
  gnutls_sign_algorithm_t sign_algo;
  gnutls_protocol_t ver = gnutls_protocol_get_version (session);

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

  dh_params =
    _gnutls_get_dh_params (cred->dh_params, cred->params_func, session);
  mpis = _gnutls_dh_params_to_mpi (dh_params);
  if (mpis == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_NO_TEMPORARY_DH_PARAMS;
    }

  p = mpis[0];
  g = mpis[1];

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

  _gnutls_dh_set_group (session, g, p);

  ret = _gnutls_dh_common_print_server_kx (session, g, p, data, 0);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }
  data_size = ret;

  /* Generate the signature. */

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

  if (apr_cert_list_length > 0)
    {
      if ((ret =
           _gnutls_handshake_sign_data (session, &apr_cert_list[0],
                                        apr_pkey, &ddata, &signature,
                                        &sign_algo)) < 0)
        {
          gnutls_assert ();
          goto cleanup;
        }
    }
  else
    {
      gnutls_assert ();
      ret = data_size;         /* do not put a signature - ILLEGAL! */
      goto cleanup;
    }

  *data = gnutls_realloc_fast (*data, data_size + signature.size + 4);
  if (*data == NULL)
    {
      gnutls_assert ();
      ret = GNUTLS_E_MEMORY_ERROR;
      goto cleanup;
    }

  if (_gnutls_version_has_selectable_sighash (ver))
    {
      const sign_algorithm_st *aid;

      if (sign_algo == GNUTLS_SIGN_UNKNOWN)
        {
          ret = GNUTLS_E_UNKNOWN_ALGORITHM;
          goto cleanup;
        }

      aid = _gnutls_sign_to_tls_aid (sign_algo);
      if (aid == NULL)
        {
          gnutls_assert();
          ret = GNUTLS_E_UNKNOWN_ALGORITHM;
          goto cleanup;
        }
      
      (*data)[data_size++] = aid->hash_algorithm;
      (*data)[data_size++] = aid->sign_algorithm;
    }

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

  _gnutls_free_datum (&signature);

  return data_size;

cleanup:
  _gnutls_free_datum (&signature);
  gnutls_free(*data);
  return ret;

}
Exemple #24
0
/* Upack certificate info.
 */
static int
unpack_certificate_auth_info (gnutls_session_t session, gnutls_buffer_st * ps)
{
  int ret;
  unsigned int i = 0, j = 0;
  size_t pack_size;
  cert_auth_info_t info = NULL;

  BUFFER_POP_NUM (ps, pack_size);

  if (pack_size == 0)
    return 0;                   /* nothing to be done */

  /* client and server have the same auth_info here
   */
  ret =
    _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE,
                           sizeof (cert_auth_info_st), 1);
  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  info = _gnutls_get_auth_info (session);
  if (info == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INTERNAL_ERROR;
    }

  BUFFER_POP_NUM (ps, info->dh.secret_bits);

  BUFFER_POP_DATUM (ps, &info->dh.prime);
  BUFFER_POP_DATUM (ps, &info->dh.generator);
  BUFFER_POP_DATUM (ps, &info->dh.public_key);
  BUFFER_POP_DATUM (ps, &info->rsa_export.modulus);
  BUFFER_POP_DATUM (ps, &info->rsa_export.exponent);

  BUFFER_POP_NUM (ps, info->ncerts);

  if (info->ncerts > 0)
    {
      info->raw_certificate_list =
        gnutls_calloc (info->ncerts, sizeof (gnutls_datum_t));
      if (info->raw_certificate_list == NULL)
        {
          gnutls_assert ();
          ret = GNUTLS_E_MEMORY_ERROR;
          goto error;
        }
    }

  for (i = 0; i < info->ncerts; i++)
    {
      BUFFER_POP_DATUM (ps, &info->raw_certificate_list[i]);
    }

  return 0;

error:
  if (info)
    {
      _gnutls_free_datum (&info->dh.prime);
      _gnutls_free_datum (&info->dh.generator);
      _gnutls_free_datum (&info->dh.public_key);

      _gnutls_free_datum (&info->rsa_export.modulus);
      _gnutls_free_datum (&info->rsa_export.exponent);

      for (j = 0; j < i; j++)
        _gnutls_free_datum (&info->raw_certificate_list[j]);

      gnutls_free (info->raw_certificate_list);
    }

  return ret;

}