Exemple #1
0
/**
  * gnutls_psk_set_client_credentials - Used to set the username/password, in a gnutls_psk_client_credentials_t structure
  * @res: is a #gnutls_psk_client_credentials_t structure.
  * @username: is the user's zero-terminated userid
  * @key: is the user's key
  * @format: indicate the format of the key, either
  * %GNUTLS_PSK_KEY_RAW or %GNUTLS_PSK_KEY_HEX.
  *
  * This function sets the username and password, in a
  * gnutls_psk_client_credentials_t structure.  Those will be used in
  * PSK authentication. @username should be an ASCII string or UTF-8
  * strings prepared using the "SASLprep" profile of "stringprep".
  * The key can be either in raw byte format or in Hex (not with the
  * '0x' prefix).
  *
  * Returns: %GNUTLS_E_SUCCESS on success, or an error code.
  **/
int
gnutls_psk_set_client_credentials (gnutls_psk_client_credentials_t res,
				   const char *username,
				   const gnutls_datum_t * key,
				   gnutls_psk_key_flags flags)
{
  int ret;

  if (username == NULL || key == NULL || key->data == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  ret = _gnutls_set_datum (&res->username, username, strlen (username));
  if (ret < 0)
    return ret;

  if (flags == GNUTLS_PSK_KEY_RAW)
    {
      if (_gnutls_set_datum (&res->key, key->data, key->size) < 0)
	{
	  gnutls_assert ();
	  ret = GNUTLS_E_MEMORY_ERROR;
	  goto error;
	}
    }
  else
    {				/* HEX key */
      size_t size;
      size = res->key.size = key->size / 2;
      res->key.data = gnutls_malloc (size);
      if (res->key.data == NULL)
	{
	  gnutls_assert ();
	  ret = GNUTLS_E_MEMORY_ERROR;
	  goto error;
	}

      ret = gnutls_hex_decode (key, (char *) res->key.data, &size);
      res->key.size = (unsigned int) size;
      if (ret < 0)
	{
	  gnutls_assert ();
	  goto error;
	}

    }

  return 0;

error:
  _gnutls_free_datum (&res->username);

  return ret;
}
Exemple #2
0
/**
 * gnutls_dh_get_group:
 * @session: is a gnutls session
 * @raw_gen: will hold the generator.
 * @raw_prime: will hold the prime.
 *
 * This function will return the group parameters used in the last
 * Diffie-Hellman key exchange with the peer.  These are the prime and
 * the generator used.  This function should be used for both
 * anonymous and ephemeral Diffie-Hellman.  The output parameters must
 * be freed with gnutls_free().
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
 *   an error code is returned.
 **/
int
gnutls_dh_get_group(gnutls_session_t session,
		    gnutls_datum_t * raw_gen, gnutls_datum_t * raw_prime)
{
	dh_info_st *dh;
	int ret;
	anon_auth_info_t anon_info;
	cert_auth_info_t cert_info;
	psk_auth_info_t psk_info;

	switch (gnutls_auth_get_type(session)) {
	case GNUTLS_CRD_ANON:
		anon_info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
		if (anon_info == NULL)
			return GNUTLS_E_INTERNAL_ERROR;
		dh = &anon_info->dh;
		break;
	case GNUTLS_CRD_PSK:
		psk_info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
		if (psk_info == NULL)
			return GNUTLS_E_INTERNAL_ERROR;
		dh = &psk_info->dh;
		break;
	case GNUTLS_CRD_CERTIFICATE:
		cert_info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
		if (cert_info == NULL)
			return GNUTLS_E_INTERNAL_ERROR;
		dh = &cert_info->dh;
		break;
	default:
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	ret = _gnutls_set_datum(raw_prime, dh->prime.data, dh->prime.size);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	ret =
	    _gnutls_set_datum(raw_gen, dh->generator.data,
			      dh->generator.size);
	if (ret < 0) {
		gnutls_assert();
		_gnutls_free_datum(raw_prime);
		return ret;
	}

	return 0;
}
Exemple #3
0
/**
 * gnutls_pkcs12_bag_set_key_id:
 * @bag: The bag
 * @indx: The bag's element to add the id
 * @id: the ID
 *
 * This function will add the given key ID, to the specified, by the
 * index, bag element. The key ID will be encoded as a 'Local key
 * identifier' bag attribute, which is usually used to distinguish
 * the local private key and the certificate pair.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value. or a negative error code on error.
 **/
int
gnutls_pkcs12_bag_set_key_id(gnutls_pkcs12_bag_t bag, unsigned indx,
			     const gnutls_datum_t * id)
{
	int ret;


	if (bag == NULL) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	if (indx > bag->bag_elements - 1) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	ret = _gnutls_set_datum(&bag->element[indx].local_key_id,
				id->data, id->size);

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

	return 0;
}
Exemple #4
0
/**
 * gnutls_session_set_data:
 * @session: is a #gnutls_session_t type.
 * @session_data: is a pointer to space to hold the session.
 * @session_data_size: is the session's size
 *
 * Sets all session parameters, in order to resume a previously
 * established session.  The session data given must be the one
 * returned by gnutls_session_get_data().  This function should be
 * called before gnutls_handshake().
 *
 * Keep in mind that session resuming is advisory. The server may
 * choose not to resume the session, thus a full handshake will be
 * performed.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
 *   an error code is returned.
 **/
int
gnutls_session_set_data(gnutls_session_t session,
			const void *session_data, size_t session_data_size)
{
	int ret;
	gnutls_datum_t psession;

	psession.data = (uint8_t *) session_data;
	psession.size = session_data_size;

	if (session_data == NULL || session_data_size == 0) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}
	ret = _gnutls_session_unpack(session, &psession);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	session->internals.resumption_requested = 1;

	if (session->internals.resumption_data.data != NULL)
		gnutls_free(session->internals.resumption_data.data);
	_gnutls_set_datum(&session->internals.resumption_data, session_data, session_data_size);

	return 0;
}
Exemple #5
0
/**
 * gnutls_session_get_data2:
 * @session: is a #gnutls_session_t type.
 * @data: is a pointer to a datum that will hold the session.
 *
 * Returns all session parameters needed to be stored to support resumption.
 * The client should call this, and store the returned session data. A session
 * may be resumed later by calling gnutls_session_set_data().  
 *
 * The returned @data are allocated and must be released using gnutls_free().
 *
 * This function will fail if called prior to handshake completion. In
 * case of false start TLS, the handshake completes only after data have
 * been successfully received from the peer.
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
 *   an error code is returned.
 **/
int
gnutls_session_get_data2(gnutls_session_t session, gnutls_datum_t *data)
{

	int ret;

	if (data == NULL) {
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
	}

	if (gnutls_session_is_resumed(session) && session->internals.resumption_data.data) {
		ret = _gnutls_set_datum(data, session->internals.resumption_data.data, session->internals.resumption_data.size);
		if (ret < 0)
			return gnutls_assert_val(ret);

		return 0;
	}

	if (session->internals.resumable == RESUME_FALSE)
		return GNUTLS_E_INVALID_SESSION;

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

	return 0;
}
Exemple #6
0
/* Reads the DER signed data from the certificate and allocates space and
 * returns them into signed_data.
 */
int
_gnutls_x509_get_signed_data(ASN1_TYPE src,  const gnutls_datum *der,
			     const char *src_name,
			     gnutls_datum_t * signed_data)
{
	int start, end, result;

	if (der == NULL || der->size == 0) {
		return _gnutls_x509_der_encode(src, src_name, signed_data, 0);
	}

	/* Get the signed data
	 */
	result = asn1_der_decoding_startEnd(src, der->data, der->size,
					    src_name, &start, &end);
	if (result != ASN1_SUCCESS) {
		result = _gnutls_asn2err(result);
		gnutls_assert();
		goto cleanup;
	}

	result =
	    _gnutls_set_datum(signed_data, &der->data[start],
			      end - start + 1);

	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	result = 0;

      cleanup:
	return result;
}
Exemple #7
0
/**
 * gnutls_x509_crl_get_raw_issuer_dn:
 * @crl: should contain a gnutls_x509_crl_t structure
 * @dn: will hold the starting point of the DN
 *
 * This function will return a pointer to the DER encoded DN structure
 * and the length.
 *
 * Returns: a negative error code on error, and (0) on success.
 *
 * Since: 2.12.0
 **/
int
gnutls_x509_crl_get_raw_issuer_dn(gnutls_x509_crl_t crl,
				  gnutls_datum_t * dn)
{
	return _gnutls_set_datum(dn, crl->raw_issuer_dn.data,
				 crl->raw_issuer_dn.size);
}
Exemple #8
0
int _gnutls13_recv_session_ticket(gnutls_session_t session, gnutls_buffer_st *buf)
{
	int ret;
	uint8_t value;
	tls13_ticket_st *ticket = &session->internals.tls13_ticket;
	gnutls_datum_t t;
	size_t val;

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

	_gnutls_free_datum(&ticket->ticket);
	memset(ticket, 0, sizeof(tls13_ticket_st));

	_gnutls_handshake_log("HSK[%p]: parsing session ticket message\n", session);

	/* ticket_lifetime */
	ret = _gnutls_buffer_pop_prefix32(buf, &val, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);
	ticket->lifetime = val;

	/* ticket_age_add */
	ret = _gnutls_buffer_pop_prefix32(buf, &val, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);
	ticket->age_add = val;

	/* ticket_nonce */
	ret = _gnutls_buffer_pop_prefix8(buf, &value, 0);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ticket->nonce_size = value;
	ret = _gnutls_buffer_pop_data(buf, ticket->nonce, ticket->nonce_size);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* ticket */
	ret = _gnutls_buffer_pop_datum_prefix16(buf, &t);
	if (ret < 0)
		return gnutls_assert_val(ret);

	gnutls_free(ticket->ticket.data);
	ret = _gnutls_set_datum(&ticket->ticket, t.data, t.size);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* Extensions */
	ret = _gnutls_extv_parse(session, parse_nst_extension, buf->data, buf->length);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* Record the ticket arrival time */
	gnutls_gettime(&ticket->arrival_time);

	return 0;
}
Exemple #9
0
int _gnutls_pk_params_copy(gnutls_pk_params_st * dst,
			   const gnutls_pk_params_st * src)
{
	unsigned int i, j;
	dst->params_nr = 0;

	if (src == NULL || src->params_nr == 0) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	dst->flags = src->flags;
	dst->algo = src->algo;

	for (i = 0; i < src->params_nr; i++) {
		dst->params[i] = _gnutls_mpi_copy(src->params[i]);
		if (dst->params[i] == NULL) {
			goto fail;
		}

		dst->params_nr++;
	}

	if (_gnutls_set_datum(&dst->raw_priv, src->raw_priv.data, src->raw_priv.size) < 0) {
		gnutls_assert();
		goto fail;
	}

	if (_gnutls_set_datum(&dst->raw_pub, src->raw_pub.data, src->raw_pub.size) < 0) {
		gnutls_assert();
		goto fail;
	}

	if (src->seed_size) {
		dst->seed_size = src->seed_size;
		memcpy(dst->seed, src->seed, src->seed_size);
	}

	return 0;

fail:
	for (j = 0; j < i; j++)
		_gnutls_mpi_release(&dst->params[j]);
	return GNUTLS_E_MEMORY_ERROR;
}
Exemple #10
0
/**
 * gnutls_x509_crl_get_raw_issuer_dn:
 * @crl: should contain a gnutls_x509_crl_t structure
 * @dn: will hold the starting point of the DN
 *
 * This function will return a pointer to the DER encoded DN structure
 * and the length.
 *
 * Returns: a negative error code on error, and (0) on success.
 *
 * Since: 2.12.0
 **/
int
gnutls_x509_crl_get_raw_issuer_dn(gnutls_x509_crl_t crl,
				  gnutls_datum_t * dn)
{
	if (crl->raw_issuer_dn.size != 0) {
		return _gnutls_set_datum(dn, crl->raw_issuer_dn.data,
					 crl->raw_issuer_dn.size);
	} else {
		return _gnutls_x509_get_raw_field(crl->crl, "tbsCertList.issuer.rdnSequence", dn);
	}
}
static
int name_constraints_add(gnutls_x509_name_constraints_t nc,
		       gnutls_x509_subject_alt_name_t type,
		       const gnutls_datum_t * name,
		       unsigned permitted)
{
	struct name_constraints_node_st * tmp, *prev = NULL;
	int ret;

	if (type != GNUTLS_SAN_DNSNAME && type != GNUTLS_SAN_RFC822NAME &&
		type != GNUTLS_SAN_DN && type != GNUTLS_SAN_URI && type != GNUTLS_SAN_IPADDRESS)
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

	if (type == GNUTLS_SAN_IPADDRESS && (name->size != 8 && name->size != 32)) {
		return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
	}

	if (permitted != 0)
		prev = tmp = nc->permitted;
	else
		prev = tmp = nc->excluded;

	while(tmp != NULL) {
		tmp = tmp->next;
		if (tmp != NULL)
			prev = tmp;
	}

	tmp = gnutls_malloc(sizeof(struct name_constraints_node_st));
	if (tmp == NULL)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	tmp->next = NULL;
	tmp->type = type;
	ret = _gnutls_set_datum(&tmp->name, name->data, name->size);
	if (ret < 0) {
		gnutls_assert();
		gnutls_free(tmp);
		return ret;
	}

	if (prev == NULL) {
		if (permitted != 0)
			nc->permitted = tmp;
		else
			nc->excluded = tmp;
	} else
		prev->next = tmp;

	return 0;
}
Exemple #12
0
/**
  * gnutls_pkcs12_bag_set_data - This function inserts data into the bag
  * @bag: The bag
  * @type: The data's type
  * @data: the data to be copied.
  *
  * This function will insert the given data of the given type into the
  * bag. 
  *
  * Returns the index of the added bag on success, or a negative
  * value on error.
  *
  **/
int
gnutls_pkcs12_bag_set_data (gnutls_pkcs12_bag_t bag,
			    gnutls_pkcs12_bag_type_t type,
			    const gnutls_datum_t * data)
{
  int ret;
  if (bag == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  if (bag->bag_elements == MAX_BAG_ELEMENTS - 1)
    {
      gnutls_assert ();
      /* bag is full */
      return GNUTLS_E_MEMORY_ERROR;
    }

  if (bag->bag_elements == 1)
    {
      /* A bag with a key or an encrypted bag, must have
       * only one element.
       */

      if (bag->element[0].type == GNUTLS_BAG_PKCS8_KEY ||
	  bag->element[0].type == GNUTLS_BAG_PKCS8_ENCRYPTED_KEY ||
	  bag->element[0].type == GNUTLS_BAG_ENCRYPTED)
	{
	  gnutls_assert ();
	  return GNUTLS_E_INVALID_REQUEST;
	}
    }

  ret =
    _gnutls_set_datum (&bag->element[bag->bag_elements].data,
		       data->data, data->size);

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

  bag->element[bag->bag_elements].type = type;

  bag->bag_elements++;

  return bag->bag_elements - 1;
}
Exemple #13
0
/* Reads the DER signed data from the certificate and allocates space and
 * returns them into signed_data.
 */
int
_gnutls_x509_get_signed_data(ASN1_TYPE src,  const gnutls_datum *_der,
			     const char *src_name,
			     gnutls_datum_t * signed_data)
{
	int start, end, result;
	gnutls_datum_t der;
	unsigned need_free = 0;

	if (_der == NULL || _der->size == 0) {
		result = _gnutls_x509_der_encode(src, "", &der, 0);
		if (result < 0) {
			gnutls_assert();
			return result;
		}
		need_free = 1;
	} else {
		der.data = _der->data;
		der.size = _der->size;
	}

	/* Get the signed data
	 */
	result = asn1_der_decoding_startEnd(src, der.data, der.size,
					    src_name, &start, &end);
	if (result != ASN1_SUCCESS) {
		result = _gnutls_asn2err(result);
		gnutls_assert();
		goto cleanup;
	}

	result =
	    _gnutls_set_datum(signed_data, &der.data[start],
			      end - start + 1);

	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	result = 0;

      cleanup:
	if (need_free != 0)
		_gnutls_free_datum(&der);

	return result;
}
Exemple #14
0
/**
 * gnutls_srp_set_server_fake_salt_seed:
 * @cred: is a #gnutls_srp_server_credentials_t type
 * @seed: is the seed data, only needs to be valid until the function
 * returns; size of the seed must be greater than zero
 * @salt_length: is the length of the generated fake salts
 *
 * This function sets the seed that is used to generate salts for
 * invalid (non-existent) usernames.
 *
 * In order to prevent attackers from guessing valid usernames,
 * when a user does not exist gnutls generates a salt and a verifier
 * and proceeds with the protocol as usual.
 * The authentication will ultimately fail, but the client cannot tell
 * whether the username is valid (exists) or invalid.
 *
 * If an attacker learns the seed, given a salt (which is part of the
 * handshake) which was generated when the seed was in use, it can tell
 * whether or not the authentication failed because of an unknown username.
 * This seed cannot be used to reveal application data or passwords.
 *
 * @salt_length should represent the salt length your application uses.
 * Generating fake salts longer than 20 bytes is not supported.
 *
 * By default the seed is a random value, different each time a
 * #gnutls_srp_server_credentials_t is allocated and fake salts are
 * 16 bytes long.
 *
 * Since: 3.3.0
 **/
void
gnutls_srp_set_server_fake_salt_seed(gnutls_srp_server_credentials_t cred,
				     const gnutls_datum_t * seed,
				     unsigned int salt_length)
{
	_gnutls_free_datum(&cred->fake_salt_seed);
	_gnutls_set_datum(&cred->fake_salt_seed, seed->data, seed->size);

	/* Cap the salt length at the output size of the MAC algorithm
	 * we are using to generate the fake salts.
	 */
	const mac_entry_st * me = mac_to_entry(SRP_FAKE_SALT_MAC);
	const size_t mac_len = me->output_size;

	cred->fake_salt_length = (salt_length < mac_len ? salt_length : mac_len);
}
Exemple #15
0
/**
 * gnutls_dh_get_pubkey:
 * @session: is a gnutls session
 * @raw_key: will hold the public key.
 *
 * This function will return the peer's public key used in the last
 * Diffie-Hellman key exchange.  This function should be used for both
 * anonymous and ephemeral Diffie-Hellman.  The output parameters must
 * be freed with gnutls_free().
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
 *   an error code is returned.
 **/
int
gnutls_dh_get_pubkey(gnutls_session_t session, gnutls_datum_t * raw_key)
{
	dh_info_st *dh;
	anon_auth_info_t anon_info;
	cert_auth_info_t cert_info;
	cert_auth_info_t psk_info;

	switch (gnutls_auth_get_type(session)) {
	case GNUTLS_CRD_ANON:
		{
			anon_info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
			if (anon_info == NULL)
				return GNUTLS_E_INTERNAL_ERROR;
			dh = &anon_info->dh;
			break;
		}
	case GNUTLS_CRD_PSK:
		{
			psk_info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
			if (psk_info == NULL)
				return GNUTLS_E_INTERNAL_ERROR;
			dh = &psk_info->dh;
			break;
		}
	case GNUTLS_CRD_CERTIFICATE:
		{

			cert_info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
			if (cert_info == NULL)
				return GNUTLS_E_INTERNAL_ERROR;
			dh = &cert_info->dh;
			break;
		}
	default:
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	return _gnutls_set_datum(raw_key, dh->public_key.data,
				 dh->public_key.size);
}
Exemple #16
0
/* Reads the DER signed data from the certificate and allocates space and
 * returns them into signed_data.
 */
int
_gnutls_x509_get_signed_data (ASN1_TYPE src, const char *src_name,
                              gnutls_datum_t * signed_data)
{
  gnutls_datum_t der;
  int start, end, result;

  result = _gnutls_x509_der_encode (src, "", &der, 0);
  if (result < 0)
    {
      gnutls_assert ();
      return result;
    }

  /* Get the signed data
   */
  result = asn1_der_decoding_startEnd (src, der.data, der.size,
                                       src_name, &start, &end);
  if (result != ASN1_SUCCESS)
    {
      result = _gnutls_asn2err (result);
      gnutls_assert ();
      goto cleanup;
    }

  result = _gnutls_set_datum (signed_data, &der.data[start], end - start + 1);

  if (result < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  result = 0;

cleanup:
  _gnutls_free_datum (&der);

  return result;
}
Exemple #17
0
/*-
  * _gnutls_x509_crl_get_raw_issuer_dn - This function returns the issuer's DN DER encoded
  * @crl: should contain a gnutls_x509_crl_t structure
  * @dn: will hold the starting point of the DN
  *
  * This function will return a pointer to the DER encoded DN structure and
  * the length.
  *
  * Returns a negative value on error, and zero on success.
  *
  -*/
int
_gnutls_x509_crl_get_raw_issuer_dn (gnutls_x509_crl_t crl,
				    gnutls_datum_t * dn)
{
  ASN1_TYPE c2 = ASN1_TYPE_EMPTY;
  int result, len1;
  int start1, end1;
  gnutls_datum_t crl_signed_data;

  if (crl == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INVALID_REQUEST;
    }

  /* get the issuer of 'crl'
   */
  if ((result =
       asn1_create_element (_gnutls_get_pkix (), "PKIX1.TBSCertList",
			    &c2)) != ASN1_SUCCESS)
    {
      gnutls_assert ();
      return _gnutls_asn2err (result);
    }

  result =
    _gnutls_x509_get_signed_data (crl->crl, "tbsCertList", &crl_signed_data);
  if (result < 0)
    {
      gnutls_assert ();
      goto cleanup;
    }

  result =
    asn1_der_decoding (&c2, crl_signed_data.data, crl_signed_data.size, NULL);
  if (result != ASN1_SUCCESS)
    {
      /* couldn't decode DER */
      gnutls_assert ();
      asn1_delete_structure (&c2);
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  result =
    asn1_der_decoding_startEnd (c2, crl_signed_data.data,
				crl_signed_data.size, "issuer",
				&start1, &end1);

  if (result != ASN1_SUCCESS)
    {
      gnutls_assert ();
      result = _gnutls_asn2err (result);
      goto cleanup;
    }

  len1 = end1 - start1 + 1;

  _gnutls_set_datum (dn, &crl_signed_data.data[start1], len1);

  result = 0;

cleanup:
  asn1_delete_structure (&c2);
  _gnutls_free_datum (&crl_signed_data);
  return result;
}
Exemple #18
0
static int
parse_cert_list(gnutls_session_t session, uint8_t * data, size_t data_size)
{
	int len, ret;
	uint8_t *p = data;
	cert_auth_info_t info;
	gnutls_certificate_credentials_t cred;
	ssize_t dsize = data_size, size;
	int i;
	unsigned npeer_certs, npeer_ocsp, j;
	crt_cert_ctx_st ctx;
	gnutls_datum_t *peer_certs = NULL;
	gnutls_datum_t *peer_ocsp = NULL;
	unsigned nentries = 0;

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

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

	if (data == NULL || data_size == 0) {
		/* no certificate was sent */
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
	}

	info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
	if (info == NULL)
		return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);

	DECR_LEN(dsize, 3);
	size = _gnutls_read_uint24(p);
	p += 3;

	if (size != dsize)
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	if (size == 0)
		return gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_FOUND);

	i = dsize;

	while (i > 0) {
		DECR_LEN(dsize, 3);
		len = _gnutls_read_uint24(p);
		if (len == 0)
			return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

		DECR_LEN(dsize, len);
		p += len + 3;
		i -= len + 3;

		DECR_LEN(dsize, 2);
		len = _gnutls_read_uint16(p);
		DECR_LEN(dsize, len);

		i -= len + 2;
		p += len + 2;

		nentries++;
	}

	if (dsize != 0)
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	/* this is unnecessary - keeping to avoid a regression due to a re-org
	 * of the loop above */
	if (nentries == 0)
		return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	npeer_ocsp = 0;
	npeer_certs = 0;

	/* Ok we now allocate the memory to hold the
	 * certificate list
	 */
	peer_certs = gnutls_calloc(nentries, sizeof(gnutls_datum_t));
	if (peer_certs == NULL)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	peer_ocsp = gnutls_calloc(nentries, sizeof(gnutls_datum_t));
	if (peer_ocsp == NULL) {
		ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
		goto cleanup;
	}

	p = data+3;

	/* Now we start parsing the list (again).
	 * We don't use DECR_LEN since the list has
	 * been parsed before.
	 */

	ctx.session = session;

	for (j = 0; j < nentries; j++) {
		len = _gnutls_read_uint24(p);
		p += 3;

		ret = _gnutls_set_datum(&peer_certs[j], p, len);
		if (ret < 0) {
			gnutls_assert();
			ret = GNUTLS_E_CERTIFICATE_ERROR;
			goto cleanup;
		}
		npeer_certs++;

		p += len;

		len = _gnutls_read_uint16(p);

		ctx.ocsp = &peer_ocsp[j];
		ctx.idx = j;

		ret = _gnutls_extv_parse(&ctx, parse_cert_extension, p, len+2);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		p += len+2;
		npeer_ocsp++;
	}

	/* The OCSP entries match the certificate entries, although
	 * the contents of each OCSP entry may be NULL.
	 */
	for(j=0;j<info->ncerts;j++)
		gnutls_free(info->raw_certificate_list[j].data);
	gnutls_free(info->raw_certificate_list);

	for(j=0;j<info->nocsp;j++)
		gnutls_free(info->raw_ocsp_list[j].data);
	gnutls_free(info->raw_ocsp_list);


	info->raw_certificate_list = peer_certs;
	info->ncerts = npeer_certs;

	info->raw_ocsp_list = peer_ocsp;
	info->nocsp = npeer_ocsp;

	return 0;

 cleanup:
	for(j=0;j<npeer_certs;j++)
		gnutls_free(peer_certs[j].data);

	for(j=0;j<npeer_ocsp;j++)
		gnutls_free(peer_ocsp[j].data);
	gnutls_free(peer_certs);
	gnutls_free(peer_ocsp);
	return ret;

}
Exemple #19
0
/**
 * cdk_pk_verify:
 * @pk: the public key
 * @sig: signature
 * @md: the message digest
 *
 * Verify the signature in @sig and compare it with the message digest in @md.
 **/
cdk_error_t
cdk_pk_verify(cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte * md)
{
	gnutls_datum_t s_sig = { NULL, 0 }, di = {
	NULL, 0};
	byte *encmd = NULL;
	cdk_error_t rc;
	int ret, algo;
	unsigned int i;
	gnutls_pk_params_st params;
	const mac_entry_st *me;

	if (!pk || !sig || !md) {
		gnutls_assert();
		return CDK_Inv_Value;
	}

	if (is_DSA(pk->pubkey_algo))
		algo = GNUTLS_PK_DSA;
	else if (is_RSA(pk->pubkey_algo))
		algo = GNUTLS_PK_RSA;
	else {
		gnutls_assert();
		return CDK_Inv_Value;
	}

	rc = sig_to_datum(&s_sig, sig);
	if (rc) {
		gnutls_assert();
		goto leave;
	}

	me = mac_to_entry(sig->digest_algo);
	rc = _gnutls_set_datum(&di, md, _gnutls_hash_get_algo_len(me));
	if (rc < 0) {
		rc = gnutls_assert_val(CDK_Out_Of_Core);
		goto leave;
	}

	rc = pk_prepare_hash(algo, me, &di);
	if (rc < 0) {
		rc = gnutls_assert_val(CDK_General_Error);
		goto leave;
	}

	params.params_nr = cdk_pk_get_npkey(pk->pubkey_algo);
	for (i = 0; i < params.params_nr; i++)
		params.params[i] = pk->mpi[i];
	params.flags = 0;
	ret = _gnutls_pk_verify(algo, &di, &s_sig, &params);

	if (ret < 0) {
		gnutls_assert();
		rc = map_gnutls_error(ret);
		goto leave;
	}

	rc = 0;

      leave:
	_gnutls_free_datum(&s_sig);
	_gnutls_free_datum(&di);
	cdk_free(encmd);
	return rc;
}
Exemple #20
0
/* This will create a PKCS1 or DSA signature, as defined in the TLS protocol.
 * Cert is the certificate of the corresponding private key. It is only checked if
 * it supports signing.
 */
static int
sign_tls_hash(gnutls_session_t session, const mac_entry_st * hash_algo,
	      gnutls_pcert_st * cert, gnutls_privkey_t pkey,
	      const gnutls_datum_t * hash_concat,
	      gnutls_datum_t * signature)
{
	const version_entry_st *ver = get_version(session);
	unsigned int key_usage = 0;

	/* If our certificate supports signing
	 */
	if (cert != NULL) {
		gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage);

		if (key_usage != 0)
			if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) {
				gnutls_assert();
				_gnutls_audit_log(session,
						  "Peer's certificate does not allow digital signatures. Key usage violation detected (ignored).\n");
			}

		/* External signing. Deprecated. To be removed. */
		if (!pkey) {
			int ret;

			if (!session->internals.sign_func)
				return
				    gnutls_assert_val
				    (GNUTLS_E_INSUFFICIENT_CREDENTIALS);

			if (!_gnutls_version_has_selectable_sighash(ver))
				return (*session->internals.sign_func)
				    (session,
				     session->internals.sign_func_userdata,
				     cert->type, &cert->cert, hash_concat,
				     signature);
			else {
				gnutls_datum_t digest;

				ret =
				    _gnutls_set_datum(&digest,
						      hash_concat->data,
						      hash_concat->size);
				if (ret < 0)
					return gnutls_assert_val(ret);

				ret =
				    pk_prepare_hash
				    (gnutls_pubkey_get_pk_algorithm
				     (cert->pubkey, NULL), hash_algo,
				     &digest);
				if (ret < 0) {
					gnutls_assert();
					goto es_cleanup;
				}

				ret = (*session->internals.sign_func)
				    (session,
				     session->internals.sign_func_userdata,
				     cert->type, &cert->cert, &digest,
				     signature);
			      es_cleanup:
				gnutls_free(digest.data);

				return ret;
			}
		}
	}

	if (!_gnutls_version_has_selectable_sighash(ver))
		return gnutls_privkey_sign_raw_data(pkey, 0, hash_concat,
						    signature);
	else
		return gnutls_privkey_sign_hash(pkey, 
						(gnutls_digest_algorithm_t)hash_algo->id,
						0, hash_concat, signature);
}
Exemple #21
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 #22
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;
}
Exemple #23
0
/* This function is to be called after handshake, when master_secret,
 *  client_random and server_random have been initialized. 
 * This function creates the keys and stores them into pending session.
 * (session->cipher_specs)
 */
static int
_gnutls_set_keys (gnutls_session_t session, record_parameters_st * params,
                  int hash_size, int IV_size, int key_size, int export_flag)
{
  /* FIXME: This function is too long
   */
  uint8_t rnd[2 * GNUTLS_RANDOM_SIZE];
  uint8_t rrnd[2 * GNUTLS_RANDOM_SIZE];
  int pos, ret;
  int block_size;
  char buf[65];
  /* avoid using malloc */
  uint8_t key_block[2 * MAX_HASH_SIZE + 2 * MAX_CIPHER_KEY_SIZE +
                   2 * MAX_CIPHER_BLOCK_SIZE];
  record_state_st *client_write, *server_write;

  if (session->security_parameters.entity == GNUTLS_CLIENT)
    {
      client_write = &params->write;
      server_write = &params->read;
    }
  else
    {
      client_write = &params->read;
      server_write = &params->write;
    }
      
  block_size = 2 * hash_size + 2 * key_size;
  if (export_flag == 0)
    block_size += 2 * IV_size;

  memcpy (rnd, session->security_parameters.server_random,
          GNUTLS_RANDOM_SIZE);
  memcpy (&rnd[GNUTLS_RANDOM_SIZE],
          session->security_parameters.client_random, GNUTLS_RANDOM_SIZE);

  memcpy (rrnd, session->security_parameters.client_random,
          GNUTLS_RANDOM_SIZE);
  memcpy (&rrnd[GNUTLS_RANDOM_SIZE],
          session->security_parameters.server_random, GNUTLS_RANDOM_SIZE);

  if (session->security_parameters.version == GNUTLS_SSL3)
    {                           /* SSL 3 */
      ret =
        _gnutls_ssl3_generate_random
        (session->security_parameters.master_secret, GNUTLS_MASTER_SIZE, rnd,
         2 * GNUTLS_RANDOM_SIZE, block_size, key_block);
    }
  else
    {                           /* TLS 1.0 */
      ret =
        _gnutls_PRF (session, session->security_parameters.master_secret,
                     GNUTLS_MASTER_SIZE, keyexp, keyexp_length,
                     rnd, 2 * GNUTLS_RANDOM_SIZE, block_size, key_block);
    }

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

  _gnutls_hard_log ("INT: KEY BLOCK[%d]: %s\n", block_size,
                    _gnutls_bin2hex (key_block, block_size, buf,
                                     sizeof (buf), NULL));

  pos = 0;
  if (hash_size > 0)
    {

      if (_gnutls_set_datum
          (&client_write->mac_secret, &key_block[pos], hash_size) < 0)
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);

      pos += hash_size;

      if (_gnutls_set_datum
          (&server_write->mac_secret, &key_block[pos], hash_size) < 0)
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);

      pos += hash_size;
    }

  if (key_size > 0)
    {
      uint8_t key1[EXPORT_FINAL_KEY_SIZE];
      uint8_t key2[EXPORT_FINAL_KEY_SIZE];
      uint8_t *client_write_key, *server_write_key;
      int client_write_key_size, server_write_key_size;

      if (export_flag == 0)
        {
          client_write_key = &key_block[pos];
          client_write_key_size = key_size;

          pos += key_size;

          server_write_key = &key_block[pos];
          server_write_key_size = key_size;

          pos += key_size;

        }
      else
        {                       /* export */
          client_write_key = key1;
          server_write_key = key2;

          /* generate the final keys */

          if (session->security_parameters.version == GNUTLS_SSL3)
            {                   /* SSL 3 */
              ret =
                _gnutls_ssl3_hash_md5 (&key_block[pos],
                                       key_size, rrnd,
                                       2 * GNUTLS_RANDOM_SIZE,
                                       EXPORT_FINAL_KEY_SIZE,
                                       client_write_key);

            }
          else
            {                   /* TLS 1.0 */
              ret =
                _gnutls_PRF (session, &key_block[pos], key_size,
                             cliwrite, cliwrite_length,
                             rrnd,
                             2 * GNUTLS_RANDOM_SIZE,
                             EXPORT_FINAL_KEY_SIZE, client_write_key);
            }

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

          client_write_key_size = EXPORT_FINAL_KEY_SIZE;
          pos += key_size;

          if (session->security_parameters.version == GNUTLS_SSL3)
            {                   /* SSL 3 */
              ret =
                _gnutls_ssl3_hash_md5 (&key_block[pos], key_size,
                                       rnd, 2 * GNUTLS_RANDOM_SIZE,
                                       EXPORT_FINAL_KEY_SIZE,
                                       server_write_key);
            }
          else
            {                   /* TLS 1.0 */
              ret =
                _gnutls_PRF (session, &key_block[pos], key_size,
                             servwrite, servwrite_length,
                             rrnd, 2 * GNUTLS_RANDOM_SIZE,
                             EXPORT_FINAL_KEY_SIZE, server_write_key);
            }

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

          server_write_key_size = EXPORT_FINAL_KEY_SIZE;
          pos += key_size;
        }

      if (_gnutls_set_datum
          (&client_write->key, client_write_key, client_write_key_size) < 0)
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);

      _gnutls_hard_log ("INT: CLIENT WRITE KEY [%d]: %s\n",
                        client_write_key_size,
                        _gnutls_bin2hex (client_write_key,
                                         client_write_key_size, buf,
                                         sizeof (buf), NULL));

      if (_gnutls_set_datum
          (&server_write->key, server_write_key, server_write_key_size) < 0)
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);

      _gnutls_hard_log ("INT: SERVER WRITE KEY [%d]: %s\n",
                        server_write_key_size,
                        _gnutls_bin2hex (server_write_key,
                                         server_write_key_size, buf,
                                         sizeof (buf), NULL));

    }


  /* IV generation in export and non export ciphers.
   */
  if (IV_size > 0 && export_flag == 0)
    {
      if (_gnutls_set_datum
          (&client_write->IV, &key_block[pos], IV_size) < 0)
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);

      pos += IV_size;

      if (_gnutls_set_datum
          (&server_write->IV, &key_block[pos], IV_size) < 0)
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);

    }
  else if (IV_size > 0 && export_flag != 0)
    {
      uint8_t iv_block[MAX_CIPHER_BLOCK_SIZE * 2];

      if (session->security_parameters.version == GNUTLS_SSL3)
        {                       /* SSL 3 */
          ret = _gnutls_ssl3_hash_md5 ("", 0,
                                       rrnd, GNUTLS_RANDOM_SIZE * 2,
                                       IV_size, iv_block);

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


          ret = _gnutls_ssl3_hash_md5 ("", 0, rnd,
                                       GNUTLS_RANDOM_SIZE * 2,
                                       IV_size, &iv_block[IV_size]);

        }
      else
        {                       /* TLS 1.0 */
          ret = _gnutls_PRF (session, (uint8_t*)"", 0,
                             ivblock, ivblock_length, rrnd,
                             2 * GNUTLS_RANDOM_SIZE, IV_size * 2, iv_block);
        }

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

      if (_gnutls_set_datum (&client_write->IV, iv_block, IV_size) < 0)
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);

      if (_gnutls_set_datum
          (&server_write->IV, &iv_block[IV_size], IV_size) < 0)
        return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
    }

  return 0;
}
Exemple #24
0
/**
 * gnutls_x509_crl_import:
 * @crl: The structure to store the parsed CRL.
 * @data: The DER or PEM encoded CRL.
 * @format: One of DER or PEM
 *
 * This function will convert the given DER or PEM encoded CRL
 * to the native #gnutls_x509_crl_t format. The output will be stored in 'crl'.
 *
 * If the CRL is PEM encoded it should have a header of "X509 CRL".
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_x509_crl_import(gnutls_x509_crl_t crl,
		       const gnutls_datum_t * data,
		       gnutls_x509_crt_fmt_t format)
{
	int result = 0;

	if (crl == NULL) {
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	_gnutls_free_datum(&crl->der);

	/* If the CRL is in PEM format then decode it
	 */
	if (format == GNUTLS_X509_FMT_PEM) {
		result =
		    _gnutls_fbase64_decode(PEM_CRL, data->data, data->size,
					   &crl->der);

		if (result < 0) {
			gnutls_assert();
			return result;
		}
	} else {
		result = _gnutls_set_datum(&crl->der, data->data, data->size);
		if (result < 0) {
			gnutls_assert();
			return result;
		}
	}

	if (crl->expanded) {
		result = crl_reinit(crl);
		if (result < 0) {
			gnutls_assert();
			goto cleanup;
		}
	}
	crl->expanded = 1;

	result =
	    asn1_der_decoding(&crl->crl, crl->der.data, crl->der.size, NULL);
	if (result != ASN1_SUCCESS) {
		result = _gnutls_asn2err(result);
		gnutls_assert();
		goto cleanup;
	}

	result = _gnutls_x509_get_raw_field2(crl->crl, &crl->der,
					  "tbsCertList.issuer.rdnSequence",
					  &crl->raw_issuer_dn);
	if (result < 0) {
		gnutls_assert();
		goto cleanup;
	}

	return 0;

      cleanup:
	_gnutls_free_datum(&crl->der);
	return result;
}
Exemple #25
0
/* This function is to be called after handshake, when master_secret,
 *  client_random and server_random have been initialized. 
 * This function creates the keys and stores them into pending session.
 * (session->cipher_specs)
 */
static int
_gnutls_set_keys(gnutls_session_t session, record_parameters_st * params,
		 int hash_size, int IV_size, int key_size)
{
	/* FIXME: This function is too long
	 */
	uint8_t rnd[2 * GNUTLS_RANDOM_SIZE];
	uint8_t rrnd[2 * GNUTLS_RANDOM_SIZE];
	int pos, ret;
	int block_size;
	char buf[65];
	/* avoid using malloc */
	uint8_t key_block[2 * MAX_HASH_SIZE + 2 * MAX_CIPHER_KEY_SIZE +
			  2 * MAX_CIPHER_BLOCK_SIZE];
	record_state_st *client_write, *server_write;

	if (session->security_parameters.entity == GNUTLS_CLIENT) {
		client_write = &params->write;
		server_write = &params->read;
	} else {
		client_write = &params->read;
		server_write = &params->write;
	}

	block_size = 2 * hash_size + 2 * key_size;
	block_size += 2 * IV_size;

	memcpy(rnd, session->security_parameters.server_random,
	       GNUTLS_RANDOM_SIZE);
	memcpy(&rnd[GNUTLS_RANDOM_SIZE],
	       session->security_parameters.client_random,
	       GNUTLS_RANDOM_SIZE);

	memcpy(rrnd, session->security_parameters.client_random,
	       GNUTLS_RANDOM_SIZE);
	memcpy(&rrnd[GNUTLS_RANDOM_SIZE],
	       session->security_parameters.server_random,
	       GNUTLS_RANDOM_SIZE);

	if (get_num_version(session) == GNUTLS_SSL3) {	/* SSL 3 */
		ret =
		    _gnutls_ssl3_generate_random
		    (session->security_parameters.master_secret,
		     GNUTLS_MASTER_SIZE, rnd, 2 * GNUTLS_RANDOM_SIZE,
		     block_size, key_block);
	} else {		/* TLS 1.0 */
		ret =
		    _gnutls_PRF(session,
				session->security_parameters.master_secret,
				GNUTLS_MASTER_SIZE, keyexp, keyexp_length,
				rnd, 2 * GNUTLS_RANDOM_SIZE, block_size,
				key_block);
	}

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

	_gnutls_hard_log("INT: KEY BLOCK[%d]: %s\n", block_size,
			 _gnutls_bin2hex(key_block, block_size, buf,
					 sizeof(buf), NULL));

	pos = 0;
	if (hash_size > 0) {

		if (_gnutls_set_datum
		    (&client_write->mac_secret, &key_block[pos],
		     hash_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		pos += hash_size;

		if (_gnutls_set_datum
		    (&server_write->mac_secret, &key_block[pos],
		     hash_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		pos += hash_size;
	}

	if (key_size > 0) {
		uint8_t *client_write_key, *server_write_key;
		int client_write_key_size, server_write_key_size;

		client_write_key = &key_block[pos];
		client_write_key_size = key_size;

		pos += key_size;

		server_write_key = &key_block[pos];
		server_write_key_size = key_size;

		pos += key_size;

		if (_gnutls_set_datum
		    (&client_write->key, client_write_key,
		     client_write_key_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		_gnutls_hard_log("INT: CLIENT WRITE KEY [%d]: %s\n",
				 client_write_key_size,
				 _gnutls_bin2hex(client_write_key,
						 client_write_key_size,
						 buf, sizeof(buf), NULL));

		if (_gnutls_set_datum
		    (&server_write->key, server_write_key,
		     server_write_key_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		_gnutls_hard_log("INT: SERVER WRITE KEY [%d]: %s\n",
				 server_write_key_size,
				 _gnutls_bin2hex(server_write_key,
						 server_write_key_size,
						 buf, sizeof(buf), NULL));

	}

	/* IV generation in export and non export ciphers.
	 */
	if (IV_size > 0) {
		if (_gnutls_set_datum
		    (&client_write->IV, &key_block[pos], IV_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

		pos += IV_size;

		if (_gnutls_set_datum
		    (&server_write->IV, &key_block[pos], IV_size) < 0)
			return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);


		_gnutls_hard_log("INT: CLIENT WRITE IV [%d]: %s\n",
				 client_write->IV.size,
				 _gnutls_bin2hex(client_write->IV.data,
						 client_write->IV.size,
						 buf, sizeof(buf), NULL));

		_gnutls_hard_log("INT: SERVER WRITE IV [%d]: %s\n",
				 server_write->IV.size,
				 _gnutls_bin2hex(server_write->IV.data,
						 server_write->IV.size,
						 buf, sizeof(buf), NULL));
	}

	return 0;
}
Exemple #26
0
int _gnutls_recv_server_certificate_status(gnutls_session_t session)
{
	uint8_t *data;
	int data_size;
	size_t r_size;
	gnutls_buffer_st buf;
	int ret;
	status_request_ext_st *priv = NULL;
	extension_priv_data_t epriv;

	ret =
	    _gnutls_ext_get_session_data(session,
					 GNUTLS_EXTENSION_STATUS_REQUEST,
					 &epriv);
	if (ret < 0)
		return 0;

	priv = epriv.ptr;

	if (!priv->expect_cstatus)
		return 0;

	ret = _gnutls_recv_handshake(session,
				     GNUTLS_HANDSHAKE_CERTIFICATE_STATUS,
				     0, &buf);
	if (ret < 0)
		return gnutls_assert_val_fatal(ret);

	priv->expect_cstatus = 0;

	data = buf.data;
	data_size = buf.length;

	/* minimum message is type (1) + response (3) + data */
	if (data_size == 0)
		return 0;
	else if (data_size < 4)
		return
		    gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);

	if (data[0] != 0x01) {
		gnutls_assert();
		_gnutls_handshake_log("EXT[%p]: unknown status_type %d\n",
				      session, data[0]);
		return 0;
	}
	DECR_LENGTH_COM(data_size, 1, ret =
			GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
			goto error);
	data++;

	DECR_LENGTH_COM(data_size, 3, ret =
			GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
			goto error);
	r_size = _gnutls_read_uint24(data);
	data += 3;

	DECR_LENGTH_COM(data_size, r_size, ret =
			GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
			goto error);

	ret = _gnutls_set_datum(&priv->response, data, r_size);
	if (ret < 0)
		goto error;

	ret = 0;

      error:
	_gnutls_buffer_clear(&buf);

	return ret;
}
Exemple #27
0
/* Generates the PSK client key exchange
 *
 * 
 * struct {
 *    select (KeyExchangeAlgorithm) {
 *       opaque psk_identity<0..2^16-1>;
 *    } exchange_keys;
 * } ClientKeyExchange;
 *
 */
int
_gnutls_gen_psk_client_kx (gnutls_session_t session, opaque ** data)
{
  int ret;
  gnutls_psk_client_credentials_t cred;

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

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

  if (cred->username.data == NULL && cred->key.data == NULL &&
      cred->get_function != NULL)
    {
      char *username;
      gnutls_datum_t key;

      ret = cred->get_function (session, &username, &key);
      if (ret)
        {
          gnutls_assert ();
          return ret;
        }

      ret = _gnutls_set_datum (&cred->username, username, strlen (username));
      gnutls_free (username);
      if (ret < 0)
        {
          gnutls_assert ();
          _gnutls_free_datum (&key);
          return ret;
        }

      ret = _gnutls_set_datum (&cred->key, key.data, key.size);
      _gnutls_free_datum (&key);
      if (ret < 0)
        {
          gnutls_assert ();
          return GNUTLS_E_MEMORY_ERROR;
        }
    }
  else if (cred->username.data == NULL || cred->key.data == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

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

  (*data) = gnutls_malloc (2 + cred->username.size);
  if ((*data) == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  _gnutls_write_datum16 (*data, cred->username);

  return (cred->username.size + 2);
}
Exemple #28
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;

}