Пример #1
0
/* Generates the PSK server key exchange
 *
 * struct {
 *     select (KeyExchangeAlgorithm) {
 *         // other cases for rsa, diffie_hellman, etc.
 *         case psk:  // NEW
 *             uint8_t psk_identity_hint<0..2^16-1>;
 *     };
 * } ServerKeyExchange;
 *
 */
int
_gnutls_gen_psk_server_kx (gnutls_session_t session, gnutls_buffer_st* data)
{
  gnutls_psk_server_credentials_t cred;
  gnutls_datum_t hint;

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

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

  /* Abort sending this message if there is no PSK identity hint. */
  if (cred->hint == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_INT_RET_0;
    }

  hint.data = (uint8_t*)cred->hint;
  hint.size = strlen (cred->hint);

  return _gnutls_buffer_append_data_prefix(data, 16, hint.data, hint.size);
}
Пример #2
0
/* Generates the PSK client key exchange
 *
 * 
 * struct {
 *    select (KeyExchangeAlgorithm) {
 *       uint8_t psk_identity<0..2^16-1>;
 *    } exchange_keys;
 * } ClientKeyExchange;
 *
 */
int
_gnutls_gen_psk_client_kx(gnutls_session_t session,
			  gnutls_buffer_st * data)
{
	int ret, free;
	gnutls_datum_t username = {NULL, 0};
	gnutls_datum_t key;
	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;
	}

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

	ret = _gnutls_find_psk_key(session, cred, &username, &key, &free);
	if (ret < 0)
		return gnutls_assert_val(ret);

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

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

	if (username.size > sizeof(info->username)-1) {
		gnutls_assert();
		ret = GNUTLS_E_ILLEGAL_SRP_USERNAME;
		goto cleanup;
	}

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


      cleanup:
	if (free) {
		gnutls_free(username.data);
		_gnutls_free_temp_key_datum(&key);
	}

	return ret;
}
Пример #3
0
int
_gnutls_gen_ecdh_common_client_kx_int (gnutls_session_t session, 
                                   gnutls_buffer_st* data, 
                                   gnutls_datum_t * psk_key)
{
  int ret;
  gnutls_datum_t out;
  int curve = _gnutls_session_ecc_curve_get(session);

  /* generate temporal key */
  ret = _gnutls_pk_generate(GNUTLS_PK_EC, curve, &session->key.ecdh_params);
  if (ret < 0)
    return gnutls_assert_val(ret);

  ret = _gnutls_ecc_ansi_x963_export(curve, session->key.ecdh_params.params[6] /* x */,
    session->key.ecdh_params.params[7] /* y */, &out);
  if (ret < 0)
    return gnutls_assert_val(ret);

  ret = _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size);
  
  _gnutls_free_datum(&out);
  
  if (ret < 0)
    return gnutls_assert_val(ret);

  /* generate pre-shared key */
  ret = calc_ecdh_key(session, psk_key);
  if (ret < 0)
    return gnutls_assert_val(ret);

  return data->length;
}
Пример #4
0
static int
client_send(gnutls_session_t session,
	    gnutls_buffer_st * extdata, status_request_ext_st * priv)
{
	int ret_len = 1 + 2;
	int ret;
	size_t i;

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

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

	for (i = 0; i < priv->responder_id_size; i++) {
		if (priv->responder_id[i].size <= 0)
			return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);

		ret = _gnutls_buffer_append_data_prefix(extdata, 16,
							priv->
							responder_id[i].
							data,
							priv->
							responder_id[i].
							size);
		if (ret < 0)
			return gnutls_assert_val(ret);

		ret_len += 2 + priv->responder_id[i].size;
	}

	ret = _gnutls_buffer_append_data_prefix(extdata, 16,
						priv->request_extensions.
						data,
						priv->request_extensions.
						size);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret_len += 2 + priv->request_extensions.size;

	return ret_len;
}
Пример #5
0
/* If the psk flag is set, then an empty psk_identity_hint will
 * be inserted */
int _gnutls_ecdh_common_print_server_kx(gnutls_session_t session,
					gnutls_buffer_st * data,
					gnutls_ecc_curve_t curve)
{
	uint8_t p;
	int ret;
	gnutls_datum_t out;

	if (curve == GNUTLS_ECC_CURVE_INVALID)
		return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES);

	/* just in case we are resuming a session */
	gnutls_pk_params_release(&session->key.ecdh_params);

	gnutls_pk_params_init(&session->key.ecdh_params);

	/* curve type */
	p = 3;

	ret = _gnutls_buffer_append_data(data, &p, 1);
	if (ret < 0)
		return gnutls_assert_val(ret);

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

	/* generate temporal key */
	ret =
	    _gnutls_pk_generate_keys(GNUTLS_PK_EC, curve,
				     &session->key.ecdh_params);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret =
	    _gnutls_ecc_ansi_x963_export(curve,
					 session->key.ecdh_params.
					 params[ECC_X] /* x */ ,
					 session->key.ecdh_params.
					 params[ECC_Y] /* y */ , &out);
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret =
	    _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size);

	_gnutls_free_datum(&out);

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

	return data->length;
}
Пример #6
0
/* Generates the PSK client key exchange
 *
 * 
 * struct {
 *    select (KeyExchangeAlgorithm) {
 *       uint8_t psk_identity<0..2^16-1>;
 *    } exchange_keys;
 * } ClientKeyExchange;
 *
 */
int
_gnutls_gen_psk_client_kx (gnutls_session_t session, gnutls_buffer_st* data)
{
  int ret, free;
  gnutls_datum_t username;
  gnutls_datum_t key;
  gnutls_psk_client_credentials_t cred;

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

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

  ret = _gnutls_find_psk_key( session, cred, &username, &key, &free);
  if (ret < 0)
    return gnutls_assert_val(ret);

  ret = _gnutls_set_psk_session_key (session, &key, NULL);
  if (ret < 0)
    {
      gnutls_assert();
      goto cleanup;
    }
  
  ret = _gnutls_buffer_append_data_prefix(data, 16, username.data, username.size);
  if (ret < 0)
    {
      gnutls_assert();
    }

cleanup:
  if (free) 
    {
      gnutls_free(username.data);
      gnutls_free(key.data);
    }
  
  return ret;
}
Пример #7
0
int _gnutls_buffer_append_mpi (gnutls_buffer_st * buf, int pfx_size, bigint_t mpi, int lz)
{
gnutls_datum_t dd;
int ret;

  if (lz)
    ret = _gnutls_mpi_dprint_lz (mpi, &dd);
  else
    ret = _gnutls_mpi_dprint (mpi, &dd);

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

  ret = _gnutls_buffer_append_data_prefix(buf, pfx_size, dd.data, dd.size);
  
  _gnutls_free_datum(&dd);
  
  return ret;
}
Пример #8
0
static int
gen_ecdhe_psk_client_kx(gnutls_session_t session, gnutls_buffer_st * data)
{
	int ret, free;
	gnutls_psk_client_credentials_t cred;
	gnutls_datum_t username, key;

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

	if (cred == NULL)
		return
		    gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);

	ret = _gnutls_find_psk_key(session, cred, &username, &key, &free);
	if (ret < 0)
		return gnutls_assert_val(ret);

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

	/* The PSK key is set in there */
	ret = _gnutls_gen_ecdh_common_client_kx_int(session, data, &key);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = data->length;

      cleanup:
	if (free) {
		_gnutls_free_datum(&username);
		_gnutls_free_datum(&key);
	}

	return ret;
}
Пример #9
0
int _gnutls13_send_certificate(gnutls_session_t session, unsigned again)
{
	int ret;
	gnutls_pcert_st *apr_cert_list = NULL;
	gnutls_privkey_t apr_pkey = NULL;
	int apr_cert_list_length = 0;
	mbuffer_st *bufel = NULL;
	gnutls_buffer_st buf;
	unsigned pos_mark, ext_pos_mark;
	unsigned i;
	struct ocsp_req_ctx_st ctx;
	gnutls_certificate_credentials_t cred;

	if (again == 0) {
		if (!session->internals.initial_negotiation_completed &&
		    session->internals.hsk_flags & HSK_PSK_SELECTED)
			return 0;

		if (session->security_parameters.entity == GNUTLS_SERVER &&
		    session->internals.resumed)
			return 0;

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

		if (session->security_parameters.entity == GNUTLS_CLIENT &&
		    !(session->internals.hsk_flags & HSK_CRT_ASKED)) {
			return 0;
		}

		ret = _gnutls_get_selected_cert(session, &apr_cert_list,
						&apr_cert_list_length, &apr_pkey);
		if (ret < 0)
			return gnutls_assert_val(ret);

		ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
		if (ret < 0)
			return gnutls_assert_val(ret);

		if (session->security_parameters.entity == GNUTLS_CLIENT) {
			ret = _gnutls_buffer_append_data_prefix(&buf, 8,
								session->internals.post_handshake_cr_context.data,
								session->internals.post_handshake_cr_context.size);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

		} else {
			ret = _gnutls_buffer_append_prefix(&buf, 8, 0);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}
		}

		/* mark total size */
		pos_mark = buf.length;
		ret = _gnutls_buffer_append_prefix(&buf, 24, 0);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		for (i=0;i<(unsigned)apr_cert_list_length;i++) {
			ret = _gnutls_buffer_append_data_prefix(&buf, 24,
								apr_cert_list[i].cert.data,
								apr_cert_list[i].cert.size);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

#ifdef ENABLE_OCSP
			if ((session->internals.selected_ocsp_length > 0 ||
			     session->internals.selected_ocsp_func) &&
			    _gnutls_hello_ext_is_present(session, GNUTLS_EXTENSION_STATUS_REQUEST)) {
				/* append status response if available */
				ret = _gnutls_extv_append_init(&buf);
				if (ret < 0) {
					gnutls_assert();
					goto cleanup;
				}
				ext_pos_mark = ret;

				ctx.pcert = &apr_cert_list[i];
				ctx.cert_index = i;
				ctx.session = session;
				ctx.cred = cred;
				ret = _gnutls_extv_append(&buf, STATUS_REQUEST_TLS_ID,
							  &ctx, append_status_request);
				if (ret < 0) {
					gnutls_assert();
					goto cleanup;
				}

				ret = _gnutls_extv_append_final(&buf, ext_pos_mark, 0);
				if (ret < 0) {
					gnutls_assert();
					goto cleanup;
				}
			} else
#endif
			{
				ret = _gnutls_buffer_append_prefix(&buf, 16, 0);
				if (ret < 0) {
					gnutls_assert();
					goto cleanup;
				}
			}
		}

		_gnutls_write_uint24(buf.length-pos_mark-3, &buf.data[pos_mark]);

		bufel = _gnutls_buffer_to_mbuffer(&buf);
	}

	return _gnutls_send_handshake(session, bufel, GNUTLS_HANDSHAKE_CERTIFICATE_PKT);

 cleanup:
	_gnutls_buffer_clear(&buf);
	return ret;
}
Пример #10
0
static
int append_status_request(void *_ctx, gnutls_buffer_st *buf)
{
	struct ocsp_req_ctx_st *ctx = _ctx;
	gnutls_session_t session = ctx->session;
	int ret;
	gnutls_datum_t resp;
	unsigned free_resp = 0;

	assert(session->internals.selected_ocsp_func != NULL ||
	       session->internals.selected_ocsp_length != 0);

	/* The global ocsp callback function can only be used to return
	 * a single certificate request */
	if (session->internals.selected_ocsp_length == 1 && ctx->cert_index != 0)
		return 0;

	if (session->internals.selected_ocsp_length > 0) {
		if (ctx->cert_index < session->internals.selected_ocsp_length) {
			if ((session->internals.selected_ocsp[ctx->cert_index].exptime != 0 &&
			    gnutls_time(0) >= session->internals.selected_ocsp[ctx->cert_index].exptime) ||
			    session->internals.selected_ocsp[ctx->cert_index].response.data == NULL) {
				return 0;
			}

			resp.data = session->internals.selected_ocsp[ctx->cert_index].response.data;
			resp.size = session->internals.selected_ocsp[ctx->cert_index].response.size;
			ret = 0;
		} else {
			return 0;
		}
	} else if (session->internals.selected_ocsp_func) {
		if (ctx->cert_index == 0) {
			ret = session->internals.selected_ocsp_func(session, session->internals.selected_ocsp_func_ptr, &resp);
			free_resp = 1;
		} else {
			return 0;
		}
	} else
		return 0;

	if (ret == GNUTLS_E_NO_CERTIFICATE_STATUS || resp.data == 0) {
		return 0;
	} else if (ret < 0) {
		return gnutls_assert_val(ret);
	}

	ret = _gnutls_buffer_append_data(buf, "\x01", 1);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = _gnutls_buffer_append_data_prefix(buf, 24, resp.data, resp.size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	ret = 0;
 cleanup:
	if (free_resp)
		gnutls_free(resp.data);
	return ret;
}
Пример #11
0
     static int _proxyinfo_send_params (gnutls_session_t session, gnutls_buffer_st* extdata)
     {
//printf("Send params\n");
  uint16_t len;
  unsigned i;
  int total_size = 0, ret;
  ProxyInfo_ext_st *priv;
  extension_priv_data_t epriv;

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


  /* this function sends the client extension data (dnsname)
   */
  if (session->security_parameters.entity == GNUTLS_CLIENT)
    {
      priv = epriv.ptr;

      if (priv->server_names_size == 0)
        return 0;

      /* uint16_t
       */
      total_size = 2;
      total_size+=2; //2 byte for 16 bit integer proxy_count
      total_size+=(sizeof(gnutls_ProxyInfo_ext)/2)*((priv->proxy_cnt)+1);
      for (i = 0; i < priv->server_names_size; i++)
        {
          /* count the total size
           */
          len = priv->server_names[i].name_length;

          /* uint8_t + uint16_t + size
           */
          total_size += 1 + 2 + len;
        }

      /* UINT16: write total size of all names
       */

      ret = _gnutls_buffer_append_prefix(extdata, 16, total_size - 2);
      ret = _gnutls_buffer_append_prefix(extdata, 16, priv->proxy_cnt);
      int count=priv->proxy_cnt;
      for(int proxy_id=0;proxy_id<count+1;proxy_id++){
      ret = _gnutls_buffer_append_prefix(extdata, 16, priv->proxy_info[proxy_id].cipher_algo);
      ret = _gnutls_buffer_append_prefix(extdata, 16, priv->proxy_info[proxy_id].kx_algo);
      ret = _gnutls_buffer_append_prefix(extdata, 16, priv->proxy_info[proxy_id].mac_algo);
      ret = _gnutls_buffer_append_prefix(extdata, 16, priv->proxy_info[proxy_id].ip_addr);
      ret = _gnutls_buffer_append_prefix(extdata, 16, priv->proxy_info[proxy_id].mac_addr);
      }
              
      if (ret < 0)
        return gnutls_assert_val(ret);

      for (i = 0; i < priv->server_names_size; i++)
        {

          switch (priv->server_names[i].type)
            {
            case GNUTLS_NAME_DNS:
              len = priv->server_names[i].name_length;
              if (len == 0)
                break;

              /* UINT8: type of this extension
               * UINT16: size of the first name
               * LEN: the actual server name.
               */
              ret = _gnutls_buffer_append_prefix(extdata, 8, 0);
              if (ret < 0)
                return gnutls_assert_val(ret);

              ret = _gnutls_buffer_append_data_prefix(extdata, 16, priv->server_names[i].name, len);
              if (ret < 0)
                return gnutls_assert_val(ret);

              break;
            default:
              gnutls_assert ();
              return GNUTLS_E_INTERNAL_ERROR;
            }
        }
    }

  return total_size;
     }
Пример #12
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;
}
Пример #13
0
static int
gen_srp_cert_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
{
	ssize_t ret;
	gnutls_datum_t signature, ddata;
	gnutls_certificate_credentials_t cred;
	gnutls_pcert_st *apr_cert_list;
	gnutls_privkey_t apr_pkey;
	int apr_cert_list_length;
	gnutls_sign_algorithm_t sign_algo;
	const version_entry_st *ver = get_version(session);

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

	ret = _gnutls_gen_srp_server_kx(session, data);

	if (ret < 0)
		return ret;

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

	cred = (gnutls_certificate_credentials_t)
	    _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE);
	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_handshake_sign_data(session, &apr_cert_list[0],
					 apr_pkey, &ddata, &signature,
					 &sign_algo)) < 0) {
		gnutls_assert();
		return ret;
	}

	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();
		goto cleanup;
	}

	ret = data->length;

      cleanup:
	_gnutls_free_datum(&signature);
	return ret;
}
Пример #14
0
static int
_gnutls_alpn_send_params (gnutls_session_t session,
                          gnutls_buffer_st* extdata)
{
  unsigned i;
  int total_size = 0, ret;
  alpn_ext_st *priv;
  extension_priv_data_t epriv;

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

  priv = epriv.ptr;

  if (priv->size == 0)
    return 0;

  if (session->security_parameters.entity == GNUTLS_SERVER)
    {
      if (priv->selected_protocol_size == 0)
        return 0;

      ret = _gnutls_buffer_append_prefix(extdata, 16, priv->selected_protocol_size+1);
      if (ret < 0)
        return gnutls_assert_val(ret);

      total_size += 2;

      ret = _gnutls_buffer_append_data_prefix(extdata, 8, priv->selected_protocol, priv->selected_protocol_size);
      if (ret < 0)
        return gnutls_assert_val(ret);

      total_size += 1+priv->selected_protocol_size;
    }
  else
    {
      int t = 0;
      for (i=0;i<priv->size;i++)
        t += priv->protocol_size[i] + 1;

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

      total_size += 2;

      for (i=0;i<priv->size;i++)
        {
          ret = _gnutls_buffer_append_data_prefix(extdata, 8, priv->protocols[i], priv->protocol_size[i]);
          if (ret < 0)
            return gnutls_assert_val(ret);

          total_size += 1+priv->protocol_size[i];
        }
    }

  return total_size;
}
Пример #15
0
Файл: dhe.c Проект: intgr/gnutls
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;

}
Пример #16
0
static int _gnutls_server_cert_type_send_params(gnutls_session_t session,
						gnutls_buffer_st* data)
{
	int ret;
	uint8_t cert_type; // Holds an IANA cert type ID
	uint8_t i = 0, num_cert_types = 0;
	priority_st* cert_priorities;
	gnutls_datum_t tmp_cert_types; // For type conversion
	uint8_t cert_types[GNUTLS_CRT_MAX]; // The list with supported cert types. Inv: 0 <= cert type Id < 256

	/* Only activate this extension if we have cert credentials set
	 * and alternative cert types are allowed */
	if (!are_alternative_cert_types_allowed(session) ||
		(_gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE) == NULL))
		return 0;

	if (!IS_SERVER(session)) {	// Client mode
		// For brevity
		cert_priorities =
				&session->internals.priorities->server_ctype;

		/* Retrieve server certificate type priorities if any. If no
		 * priorities are set then the default server certificate type
		 * initialization values apply. This default is currently set to
		 * X.509 in which case we don't enable this extension.
		 */
		if (cert_priorities->num_priorities > 0) {	// Priorities are explicitly set
			/* If the certificate priority is explicitly set to only
			 * X.509 (default) then, according to spec we don't send
			 * this extension. We check this here to avoid further work in
			 * this routine. We also check it below after pruning supported
			 * types.
			 */
			if (cert_priorities->num_priorities == 1 &&
					cert_priorities->priorities[0] == DEFAULT_CERT_TYPE) {
				_gnutls_handshake_log
						("EXT[%p]: Server certificate type was set to default cert type (%s). "
						 "We therefore do not send this extension.\n",
						 session,
						 gnutls_certificate_type_get_name(DEFAULT_CERT_TYPE));

				// Explicitly set but default ctype, so don't send anything
				return 0;
			}

			/* We are only allowed to send certificate types that we support.
			 * Therefore we check this here and prune our original list.
			 * This check might seem redundant now because we don't check for
			 * credentials (they are not needed for a client) and only check the
			 * priorities over which we already iterate. In the future,
			 * additional checks might be necessary and they can be easily
			 * added in the ..type_supported() routine without modifying the
			 * structure of the code here.
			 */
			for (i = 0; i < cert_priorities->num_priorities; i++) {
				if (_gnutls_session_cert_type_supported
						(session, cert_priorities->priorities[i],
						 false, GNUTLS_CTYPE_SERVER) == 0) {
					/* Check whether we are allowed to store another cert type
					 * in our buffer. In other words, prevent a possible buffer
					 * overflow. This situation can occur when a user sets
					 * duplicate cert types in the priority strings. */
					if (num_cert_types >= GNUTLS_CRT_MAX)
						return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);

					// Convert to IANA representation
					ret = cert_type2IANA(cert_priorities->priorities[i]);

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

					cert_type = ret; // For readability

					// Add this cert type to our list with supported types
					cert_types[num_cert_types] = cert_type;
					num_cert_types++;

					_gnutls_handshake_log
							("EXT[%p]: Server certificate type %s (%d) was queued.\n",
							 session,
							 gnutls_certificate_type_get_name(cert_priorities->priorities[i]),
							 cert_type);
				}
			}

			/* Check whether there are any supported certificate types left
			 * after the previous pruning step. If not, we do not send this
			 * extension. Also, if the only supported type is the default type
			 * we do not send this extension (according to RFC7250).
			 */
			if (num_cert_types == 0) {	// For now, this should not occur since we only check priorities while pruning.
				_gnutls_handshake_log
						("EXT[%p]: Server certificate types were set but none of them is supported. "
						 "We do not send this extension.\n",
						 session);

				return 0;
			} else if (num_cert_types == 1 &&
					 IANA2cert_type(cert_types[0]) == DEFAULT_CERT_TYPE) {
				_gnutls_handshake_log
						("EXT[%p]: The only supported server certificate type is (%s) which is the default. "
						 "We therefore do not send this extension.\n",
						 session,
						 gnutls_certificate_type_get_name(DEFAULT_CERT_TYPE));

				return 0;
			}

			/* We have data to send and store a copy internally. We convert
			 * our list with supported cert types to a datum_t in order to
			 * be able to make the ..._set_datum call.
			 */
			tmp_cert_types.data = cert_types;
			tmp_cert_types.size = num_cert_types;

			_gnutls_hello_ext_set_datum(session,
								 GNUTLS_EXTENSION_SERVER_CERT_TYPE,
								 &tmp_cert_types);

			/* Serialize the certificate types into a sequence of octets
			 * uint8: length of sequence of cert types (1 octet)
			 * uint8: cert types (0 <= #octets <= 255)
			 */
			ret = _gnutls_buffer_append_data_prefix(data, 8,
								cert_types,
								num_cert_types);

			// Check for errors and cleanup in case of error
			if (ret < 0) {
				return gnutls_assert_val(ret);
			} else {
				// Number of bytes we are sending
				return num_cert_types + 1;
			}
		}
	} else {	// Server mode
		// Retrieve negotiated server certificate type and send it
		ret = cert_type2IANA(get_certificate_type(
					session, GNUTLS_CTYPE_SERVER));

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

		cert_type = ret; // For readability

		ret = gnutls_buffer_append_data(data, &cert_type, 1);

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

		return 1;	// sent one byte
	}

	// In all other cases don't enable this extension
	return 0;
}
Пример #17
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;
}
Пример #18
0
/* Generate client key exchange message
 *
 *
 * struct {
 *    select (KeyExchangeAlgorithm) {
 *       uint8_t psk_identity<0..2^16-1>;
 *       EncryptedPreMasterSecret;
 *    } exchange_keys;
 * } ClientKeyExchange;
 */
static int
_gnutls_gen_rsa_psk_client_kx(gnutls_session_t session,
			      gnutls_buffer_st * data)
{
	cert_auth_info_t auth = session->key.auth_info;
	gnutls_datum_t sdata;	/* data to send */
	gnutls_pk_params_st params;
	gnutls_psk_client_credentials_t cred;
	gnutls_datum_t username, key;
	int ret, free;
	unsigned init_pos;

	if (auth == NULL) {
		/* this shouldn't have happened. The proc_certificate
		 * function should have detected that.
		 */
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	gnutls_datum_t premaster_secret;
	premaster_secret.size = GNUTLS_MASTER_SIZE;
	premaster_secret.data =
	    gnutls_malloc(premaster_secret.size);

	if (premaster_secret.data == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	/* Generate random */
	ret = gnutls_rnd(GNUTLS_RND_RANDOM, premaster_secret.data,
			  premaster_secret.size);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	/* Set version */
	if (session->internals.rsa_pms_version[0] == 0) {
		premaster_secret.data[0] =
		    _gnutls_get_adv_version_major(session);
		premaster_secret.data[1] =
		    _gnutls_get_adv_version_minor(session);
	} else {		/* use the version provided */
		premaster_secret.data[0] =
		    session->internals.rsa_pms_version[0];
		premaster_secret.data[1] =
		    session->internals.rsa_pms_version[1];
	}

	/* move RSA parameters to key (session).
	 */
	if ((ret = _gnutls_get_public_rsa_params(session, &params)) < 0) {
		gnutls_assert();
		return ret;
	}

	/* Encrypt premaster secret */
	if ((ret =
	     _gnutls_pk_encrypt(GNUTLS_PK_RSA, &sdata, &premaster_secret,
				&params)) < 0) {
		gnutls_assert();
		return ret;
	}

	gnutls_pk_params_release(&params);

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

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

	ret = _gnutls_find_psk_key(session, cred, &username, &key, &free);
	if (ret < 0)
		return gnutls_assert_val(ret);

	/* Here we set the PSK key */
	ret = set_rsa_psk_session_key(session, &key, &premaster_secret);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* Create message for client key exchange
	 *
	 * struct {
	 *   uint8_t psk_identity<0..2^16-1>;
	 *   EncryptedPreMasterSecret;
	 * }
	 */

	init_pos = data->length;

	/* Write psk_identity and EncryptedPreMasterSecret into data stream
	 */
	ret =
	    _gnutls_buffer_append_data_prefix(data, 16,
					      username.data,
					      username.size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

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

	ret = data->length - init_pos;

      cleanup:
	_gnutls_free_datum(&sdata);
	_gnutls_free_temp_key_datum(&premaster_secret);
	if (free) {
		_gnutls_free_temp_key_datum(&key);
		gnutls_free(username.data);
	}

	return ret;
}
Пример #19
0
/* return RSA(random) using the peers public key 
 */
int
_gnutls_gen_rsa_client_kx(gnutls_session_t session,
			  gnutls_buffer_st * data)
{
	cert_auth_info_t auth = session->key.auth_info;
	gnutls_datum_t sdata;	/* data to send */
	gnutls_pk_params_st params;
	int ret;

	if (auth == NULL) {
		/* this shouldn't have happened. The proc_certificate
		 * function should have detected that.
		 */
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	session->key.key.size = GNUTLS_MASTER_SIZE;
	session->key.key.data = gnutls_malloc(session->key.key.size);

	if (session->key.key.data == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}

	ret = _gnutls_rnd(GNUTLS_RND_RANDOM, session->key.key.data,
			  session->key.key.size);
	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	if (session->internals.rsa_pms_version[0] == 0) {
		session->key.key.data[0] =
		    _gnutls_get_adv_version_major(session);
		session->key.key.data[1] =
		    _gnutls_get_adv_version_minor(session);
	} else {		/* use the version provided */
		session->key.key.data[0] =
		    session->internals.rsa_pms_version[0];
		session->key.key.data[1] =
		    session->internals.rsa_pms_version[1];
	}

	/* move RSA parameters to key (session).
	 */
	if ((ret = _gnutls_get_public_rsa_params(session, &params)) < 0) {
		gnutls_assert();
		return ret;
	}

	ret =
	    _gnutls_pk_encrypt(GNUTLS_PK_RSA, &sdata, &session->key.key,
			       &params);

	gnutls_pk_params_release(&params);

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


	if (get_num_version(session) == GNUTLS_SSL3) {
		/* SSL 3.0 */
		_gnutls_buffer_replace_data(data, &sdata);

		return data->length;
	} else {		/* TLS 1 */
		ret =
		    _gnutls_buffer_append_data_prefix(data, 16, sdata.data,
						      sdata.size);

		_gnutls_free_datum(&sdata);
		return ret;
	}

}
Пример #20
0
static int
_gnutls_srtp_send_params(gnutls_session_t session,
			 gnutls_buffer_st * extdata)
{
	unsigned i;
	int total_size = 0, ret;
	srtp_ext_st *priv;
	extension_priv_data_t epriv;

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

	priv = epriv;

	if (priv->profiles_size == 0)
		return 0;

	if (session->security_parameters.entity == GNUTLS_SERVER) {
		/* Don't send anything if no matching profile was found */
		if (priv->selected_profile == 0)
			return 0;

		ret = _gnutls_buffer_append_prefix(extdata, 16, 2);
		if (ret < 0)
			return gnutls_assert_val(ret);
		ret =
		    _gnutls_buffer_append_prefix(extdata, 16,
						 priv->selected_profile);
		if (ret < 0)
			return gnutls_assert_val(ret);
		total_size = 4;
	} else {
		ret =
		    _gnutls_buffer_append_prefix(extdata, 16,
						 2 * priv->profiles_size);
		if (ret < 0)
			return gnutls_assert_val(ret);

		for (i = 0; i < priv->profiles_size; i++) {
			ret =
			    _gnutls_buffer_append_prefix(extdata, 16,
							 priv->
							 profiles[i]);
			if (ret < 0)
				return gnutls_assert_val(ret);
		}
		total_size = 2 + 2 * priv->profiles_size;
	}

	/* use_mki */
	ret =
	    _gnutls_buffer_append_data_prefix(extdata, 8, priv->mki,
					      priv->mki_size);
	if (ret < 0)
		return gnutls_assert_val(ret);
	total_size += 1 + priv->mki_size;

	return total_size;
}
Пример #21
0
int _gnutls13_send_session_ticket(gnutls_session_t session, unsigned nr, unsigned again)
{
	int ret = 0;
	mbuffer_st *bufel = NULL;
	gnutls_buffer_st buf;
	tls13_ticket_st ticket;
	unsigned i;

	/* Client does not send a NewSessionTicket */
	if (unlikely(session->security_parameters.entity == GNUTLS_CLIENT))
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	/* Session resumption has not been enabled */
	if (session->internals.flags & GNUTLS_NO_TICKETS)
		return gnutls_assert_val(0);

	/* If we received the psk_key_exchange_modes extension which
	 * does not have overlap with the server configuration, don't
	 * send a session ticket */
	if (session->internals.hsk_flags & HSK_PSK_KE_MODE_INVALID)
		return gnutls_assert_val(0);

	if (again == 0) {
		for (i=0;i<nr;i++) {
			unsigned init_pos;

			memset(&ticket, 0, sizeof(tls13_ticket_st));
			bufel = NULL;

			ret = _gnutls_buffer_init_handshake_mbuffer(&buf);
			if (ret < 0)
				return gnutls_assert_val(ret);

			ret = generate_session_ticket(session, &ticket);
			if (ret < 0) {
				if (ret == GNUTLS_E_INT_RET_0) {
					ret = gnutls_assert_val(0);
					goto cleanup;
				}
				gnutls_assert();
				goto cleanup;
			}

			ret = _gnutls_buffer_append_prefix(&buf, 32, ticket.lifetime);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			ret = _gnutls_buffer_append_prefix(&buf, 32, ticket.age_add);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			/* append ticket_nonce */
			ret = _gnutls_buffer_append_data_prefix(&buf, 8, ticket.nonce, ticket.nonce_size);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			/* append ticket */
			ret = _gnutls_buffer_append_data_prefix(&buf, 16, ticket.ticket.data, ticket.ticket.size);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			_gnutls_free_datum(&ticket.ticket);

			/* append extensions */
			ret = _gnutls_extv_append_init(&buf);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}
			init_pos = ret;

			ret = _gnutls_extv_append(&buf, ext_mod_early_data.tls_id, session,
						  (extv_append_func)append_nst_extension);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			ret = _gnutls_extv_append_final(&buf, init_pos, 0);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			bufel = _gnutls_buffer_to_mbuffer(&buf);

			ret = _gnutls_send_handshake2(session, bufel,
						      GNUTLS_HANDSHAKE_NEW_SESSION_TICKET, 1);
			if (ret < 0) {
				gnutls_assert();
				goto cleanup;
			}

			session->internals.hsk_flags |= HSK_TLS13_TICKET_SENT;
		}
	}

	ret = _gnutls_handshake_io_write_flush(session);

	return ret;

cleanup:
	_gnutls_free_datum(&ticket.ticket);
	_mbuffer_xfree(&bufel);
	_gnutls_buffer_clear(&buf);

	return ret;
}
Пример #22
0
/* returns data_size or a negative number on failure
 */
static int
_gnutls_server_name_send_params(gnutls_session_t session,
				gnutls_buffer_st * extdata)
{
	uint16_t len;
	unsigned i;
	int total_size = 0, ret;
	server_name_ext_st *priv;
	extension_priv_data_t epriv;

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


	/* this function sends the client extension data (dnsname)
	 */
	if (session->security_parameters.entity == GNUTLS_CLIENT) {
		priv = epriv;

		if (priv->server_names_size == 0)
			return 0;

		/* uint16_t
		 */
		total_size = 2;
		for (i = 0; i < priv->server_names_size; i++) {
			/* count the total size
			 */
			len = priv->server_names[i].name_length;

			/* uint8_t + uint16_t + size
			 */
			total_size += 1 + 2 + len;
		}

		/* UINT16: write total size of all names
		 */
		ret =
		    _gnutls_buffer_append_prefix(extdata, 16,
						 total_size - 2);
		if (ret < 0)
			return gnutls_assert_val(ret);

		for (i = 0; i < priv->server_names_size; i++) {

			switch (priv->server_names[i].type) {
			case GNUTLS_NAME_DNS:
				len = priv->server_names[i].name_length;
				if (len == 0)
					break;

				/* UINT8: type of this extension
				 * UINT16: size of the first name
				 * LEN: the actual server name.
				 */
				ret =
				    _gnutls_buffer_append_prefix(extdata,
								 8, 0);
				if (ret < 0)
					return gnutls_assert_val(ret);

				ret =
				    _gnutls_buffer_append_data_prefix
				    (extdata, 16,
				     priv->server_names[i].name, len);
				if (ret < 0)
					return gnutls_assert_val(ret);

				break;
			default:
				gnutls_assert();
				return GNUTLS_E_INTERNAL_ERROR;
			}
		}
	}

	return total_size;
}
Пример #23
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;
}