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; }
/* returns data_size or a negative number on failure */ static int _gnutls_supported_ecc_send_params(gnutls_session_t session, gnutls_buffer_st * extdata) { unsigned len, i; int ret; uint16_t p; /* this extension is only being sent on client side */ if (session->security_parameters.entity == GNUTLS_CLIENT) { if (session->internals.priorities.supported_ecc. algorithms > 0) { len = session->internals.priorities.supported_ecc. algorithms; /* this is a vector! */ ret = _gnutls_buffer_append_prefix(extdata, 16, len * 2); if (ret < 0) return gnutls_assert_val(ret); for (i = 0; i < len; i++) { p = _gnutls_ecc_curve_get_tls_id(session-> internals. priorities.supported_ecc. priority [i]); ret = _gnutls_buffer_append_prefix(extdata, 16, p); if (ret < 0) return gnutls_assert_val(ret); } return (len + 1) * 2; } } return 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; }
static int gen_dhe_psk_server_kx(gnutls_session_t session, gnutls_buffer_st * data) { bigint_t g, p; const bigint_t *mpis; int ret; gnutls_dh_params_t dh_params; gnutls_psk_server_credentials_t cred; cred = (gnutls_psk_server_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_PSK, NULL); if (cred == NULL) { gnutls_assert(); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } dh_params = _gnutls_get_dh_params(cred->dh_params, cred->params_func, session); mpis = _gnutls_dh_params_to_mpi(dh_params); if (mpis == NULL) { gnutls_assert(); return GNUTLS_E_NO_TEMPORARY_DH_PARAMS; } p = mpis[0]; g = mpis[1]; if ((ret = _gnutls_auth_info_set(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1)) < 0) { gnutls_assert(); return ret; } _gnutls_dh_set_group(session, g, p); ret = _gnutls_buffer_append_prefix(data, 16, 0); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_dh_common_print_server_kx(session, g, p, dh_params->q_bits, data); if (ret < 0) gnutls_assert(); return ret; }
static int server_send_params(gnutls_session_t session, gnutls_buffer_t extdata) { int ret; if (!(session->internals.hsk_flags & HSK_PSK_SELECTED)) return 0; ret = _gnutls_buffer_append_prefix(extdata, 16, session->key.binders[0].idx); if (ret < 0) return gnutls_assert_val(ret); return 2; }
static int append_nst_extension(void *ctx, gnutls_buffer_st *buf) { gnutls_session_t session = ctx; int ret; if (!(session->internals.flags & GNUTLS_ENABLE_EARLY_DATA)) return 0; ret = _gnutls_buffer_append_prefix(buf, 32, session->security_parameters. max_early_data_size); if (ret < 0) gnutls_assert(); return ret; }
int _gnutls_buffer_append_data_prefix (gnutls_buffer_st * buf, int pfx_size, const void *data, size_t data_size) { int ret = 0, ret1; ret1 = _gnutls_buffer_append_prefix (buf, pfx_size, data_size); if (ret1 < 0) return gnutls_assert_val(ret1); if (data_size > 0) { ret = _gnutls_buffer_append_data (buf, data, data_size); if (ret < 0) return gnutls_assert_val(ret); } return ret + ret1; }
static int gen_ecdhe_psk_server_kx(gnutls_session_t session, gnutls_buffer_st * data) { int ret; if ((ret = _gnutls_auth_info_set(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1)) < 0) { gnutls_assert(); return ret; } ret = _gnutls_buffer_append_prefix(data, 16, 0); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_ecdh_common_print_server_kx(session, data, _gnutls_session_ecc_curve_get (session)); if (ret < 0) gnutls_assert(); return ret; }
/* 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; }
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; }
int _gnutls_gen_extensions(gnutls_session_t session, gnutls_buffer_st * extdata, gnutls_ext_parse_type_t parse_type) { int size; int pos, size_pos, ret; size_t i, init_size = extdata->length; pos = extdata->length; /* we will store length later on */ ret = _gnutls_buffer_append_prefix(extdata, 16, 0); if (ret < 0) return gnutls_assert_val(ret); for (i = 0; i < extfunc_size; i++) { extension_entry_st *p = &extfunc[i]; if (p->send_func == NULL) continue; if (parse_type != GNUTLS_EXT_ANY && p->parse_type != parse_type) continue; ret = _gnutls_buffer_append_prefix(extdata, 16, p->type); if (ret < 0) return gnutls_assert_val(ret); size_pos = extdata->length; ret = _gnutls_buffer_append_prefix(extdata, 16, 0); if (ret < 0) return gnutls_assert_val(ret); size = p->send_func(session, extdata); /* returning GNUTLS_E_INT_RET_0 means to send an empty * extension of this type. */ if (size > 0 || size == GNUTLS_E_INT_RET_0) { if (size == GNUTLS_E_INT_RET_0) size = 0; /* write the real size */ _gnutls_write_uint16(size, &extdata->data[size_pos]); /* add this extension to the extension list */ _gnutls_extension_list_add(session, p->type); _gnutls_handshake_log ("EXT[%p]: Sending extension %s (%d bytes)\n", session, p->name, size); } else if (size < 0) { gnutls_assert(); return size; } else if (size == 0) extdata->length -= 4; /* reset type and size */ } /* remove any initial data, and the size of the header */ size = extdata->length - init_size - 2; if (size > 0) _gnutls_write_uint16(size, &extdata->data[pos]); else if (size == 0) extdata->length -= 2; /* the length bytes */ return size; }
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; }
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; }
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; }
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; }
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; }
static int _gnutls_sr_send_params (gnutls_session_t session, gnutls_buffer_st* extdata) { /* The format of this extension is a one-byte length of verify data followed * by the verify data itself. Note that the length byte does not include * itself; IOW, empty verify data is represented as a length of 0. That means * the minimum extension is one byte: 0x00. */ sr_ext_st *priv; int ret, set = 0, len; extension_priv_data_t epriv; size_t init_length = extdata->length; if (session->internals.priorities.sr == SR_DISABLED) { gnutls_assert (); return 0; } ret = _gnutls_ext_get_session_data (session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, &epriv); if (ret < 0) { set = 1; } if (set != 0) { priv = gnutls_calloc (1, sizeof (*priv)); if (priv == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } epriv.ptr = priv; _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_SAFE_RENEGOTIATION, epriv); } else priv = epriv.ptr; /* Always offer the extension if we're a client */ if (priv->connection_using_safe_renegotiation || session->security_parameters.entity == GNUTLS_CLIENT) { len = priv->client_verify_data_len; if (session->security_parameters.entity == GNUTLS_SERVER) len += priv->server_verify_data_len; ret = _gnutls_buffer_append_prefix(extdata, 8, len); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_buffer_append_data(extdata, priv->client_verify_data, priv->client_verify_data_len); if (ret < 0) return gnutls_assert_val(ret); if (session->security_parameters.entity == GNUTLS_SERVER) { ret = _gnutls_buffer_append_data(extdata, priv->server_verify_data, priv->server_verify_data_len); if (ret < 0) return gnutls_assert_val(ret); } } else return 0; return extdata->length - init_length; }