static void deinit_keys(gnutls_session_t session) { gnutls_pk_params_release(&session->key.ecdh_params); gnutls_pk_params_release(&session->key.dh_params); zrelease_temp_mpi_key(&session->key.ecdh_x); zrelease_temp_mpi_key(&session->key.ecdh_y); _gnutls_free_temp_key_datum(&session->key.ecdhx); zrelease_temp_mpi_key(&session->key.client_Y); /* SRP */ zrelease_temp_mpi_key(&session->key.srp_p); zrelease_temp_mpi_key(&session->key.srp_g); zrelease_temp_mpi_key(&session->key.srp_key); zrelease_temp_mpi_key(&session->key.u); zrelease_temp_mpi_key(&session->key.a); zrelease_temp_mpi_key(&session->key.x); zrelease_temp_mpi_key(&session->key.A); zrelease_temp_mpi_key(&session->key.B); zrelease_temp_mpi_key(&session->key.b); _gnutls_free_temp_key_datum(&session->key.key); _gnutls_free_temp_key_datum(&session->key.key); }
/* 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; }
int _gnutls_gen_dh_common_client_kx_int(gnutls_session_t session, gnutls_buffer_st * data, gnutls_datum_t * pskkey) { int ret; gnutls_pk_params_st peer_pub; gnutls_datum_t tmp_dh_key = {NULL, 0}; gnutls_pk_params_init(&peer_pub); ret = _gnutls_pk_generate_keys(GNUTLS_PK_DH, 0, &session->key.dh_params, 1); if (ret < 0) return gnutls_assert_val(ret); _gnutls_dh_set_secret_bits(session, _gnutls_mpi_get_nbits(session->key.dh_params.params[DH_X])); ret = _gnutls_buffer_append_mpi(data, 16, session->key.dh_params.params[DH_Y], 0); if (ret < 0) { gnutls_assert(); goto error; } peer_pub.params[DH_Y] = session->key.client_Y; /* calculate the key after calculating the message */ ret = _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key, &session->key.dh_params, &peer_pub); if (ret < 0) { gnutls_assert(); goto error; } if (_gnutls_cipher_suite_get_kx_algo (session->security_parameters.cipher_suite) != GNUTLS_KX_DHE_PSK) { session->key.key.data = tmp_dh_key.data; session->key.key.size = tmp_dh_key.size; } else { /* In DHE_PSK the key is set differently */ ret = _gnutls_set_psk_session_key(session, pskkey, &tmp_dh_key); _gnutls_free_temp_key_datum(&tmp_dh_key); } if (ret < 0) { gnutls_assert(); goto error; } ret = data->length; error: gnutls_pk_params_clear(&session->key.dh_params); return ret; }
/* Set the PSK premaster secret. */ int _gnutls_set_psk_session_key(gnutls_session_t session, gnutls_datum_t * ppsk /* key */ , gnutls_datum_t * dh_secret) { gnutls_datum_t pwd_psk = { NULL, 0 }; size_t dh_secret_size; uint8_t *p; int ret; if (dh_secret == NULL) dh_secret_size = ppsk->size; else dh_secret_size = dh_secret->size; /* set the session key */ session->key.key.size = 4 + dh_secret_size + ppsk->size; session->key.key.data = gnutls_malloc(session->key.key.size); if (session->key.key.data == NULL) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto error; } /* format of the premaster secret: * (uint16_t) psk_size * psk_size bytes of (0)s * (uint16_t) psk_size * the psk */ p = session->key.key.data; _gnutls_write_uint16(dh_secret_size, p); p += 2; if (dh_secret == NULL) memset(p, 0, dh_secret_size); else memcpy(p, dh_secret->data, dh_secret->size); p += dh_secret_size; _gnutls_write_uint16(ppsk->size, p); if (ppsk->data != NULL) memcpy(p + 2, ppsk->data, ppsk->size); ret = 0; error: _gnutls_free_temp_key_datum(&pwd_psk); return ret; }
static int calc_ecdh_key(gnutls_session_t session, gnutls_datum_t * psk_key, gnutls_ecc_curve_t curve) { gnutls_pk_params_st pub; int ret; gnutls_pk_params_init(&pub); pub.params[ECC_X] = session->key.ecdh_x; pub.params[ECC_Y] = session->key.ecdh_y; pub.flags = curve; if (psk_key == NULL) { ret = _gnutls_pk_derive(GNUTLS_PK_EC, &session->key.key, &session->key.ecdh_params, &pub); } else { gnutls_datum_t tmp_dh_key; ret = _gnutls_pk_derive(GNUTLS_PK_EC, &tmp_dh_key, &session->key.ecdh_params, &pub); if (ret < 0) { ret = gnutls_assert_val(ret); goto cleanup; } ret = _gnutls_set_psk_session_key(session, psk_key, &tmp_dh_key); _gnutls_free_temp_key_datum(&tmp_dh_key); } if (ret < 0) { ret = gnutls_assert_val(ret); goto cleanup; } ret = 0; cleanup: /* no longer needed */ _gnutls_mpi_release(&session->key.ecdh_x); _gnutls_mpi_release(&session->key.ecdh_y); gnutls_pk_params_release(&session->key.ecdh_params); return ret; }
/** * gnutls_deinit: * @session: is a #gnutls_session_t structure. * * This function clears all buffers associated with the @session. * This function will also remove session data from the session * database if the session was terminated abnormally. **/ void gnutls_deinit(gnutls_session_t session) { unsigned int i; if (session == NULL) return; _gnutls_rnd_refresh(); /* remove auth info firstly */ _gnutls_free_auth_info(session); _gnutls_handshake_internal_state_clear(session); _gnutls_handshake_io_buffer_clear(session); _gnutls_ext_free_session_data(session); for (i = 0; i < MAX_EPOCH_INDEX; i++) if (session->record_parameters[i] != NULL) { _gnutls_epoch_free(session, session->record_parameters[i]); session->record_parameters[i] = NULL; } _gnutls_buffer_clear(&session->internals.handshake_hash_buffer); _gnutls_buffer_clear(&session->internals.hb_remote_data); _gnutls_buffer_clear(&session->internals.hb_local_data); _gnutls_buffer_clear(&session->internals.record_presend_buffer); _mbuffer_head_clear(&session->internals.record_buffer); _mbuffer_head_clear(&session->internals.record_recv_buffer); _mbuffer_head_clear(&session->internals.record_send_buffer); gnutls_credentials_clear(session); _gnutls_selected_certs_deinit(session); gnutls_pk_params_release(&session->key.ecdh_params); gnutls_pk_params_release(&session->key.dh_params); zrelease_temp_mpi_key(&session->key.ecdh_x); zrelease_temp_mpi_key(&session->key.ecdh_y); zrelease_temp_mpi_key(&session->key.client_Y); zrelease_temp_mpi_key(&session->key.srp_p); zrelease_temp_mpi_key(&session->key.srp_g); zrelease_temp_mpi_key(&session->key.srp_key); zrelease_temp_mpi_key(&session->key.u); zrelease_temp_mpi_key(&session->key.a); zrelease_temp_mpi_key(&session->key.x); zrelease_temp_mpi_key(&session->key.A); zrelease_temp_mpi_key(&session->key.B); zrelease_temp_mpi_key(&session->key.b); /* RSA */ zrelease_temp_mpi_key(&session->key.rsa[0]); zrelease_temp_mpi_key(&session->key.rsa[1]); _gnutls_free_temp_key_datum(&session->key.key); gnutls_free(session); }
/* Process the client key exchange message */ static int _gnutls_proc_rsa_psk_client_kx(gnutls_session_t session, uint8_t * data, size_t _data_size) { gnutls_datum_t username; psk_auth_info_t info; gnutls_datum_t plaintext; gnutls_datum_t ciphertext; gnutls_datum_t pwd_psk = { NULL, 0 }; int ret, dsize; int randomize_key = 0; ssize_t data_size = _data_size; gnutls_psk_server_credentials_t cred; gnutls_datum_t premaster_secret = { NULL, 0 }; cred = (gnutls_psk_server_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_PSK); if (cred == NULL) { gnutls_assert(); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } ret = _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1); if (ret < 0) { gnutls_assert(); return ret; } /*** 1. Extract user psk_identity ***/ DECR_LEN(data_size, 2); username.size = _gnutls_read_uint16(&data[0]); DECR_LEN(data_size, username.size); username.data = &data[2]; /* copy the username to the auth info structures */ info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); if (info == NULL) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } if (username.size > MAX_USERNAME_SIZE) { gnutls_assert(); return GNUTLS_E_ILLEGAL_SRP_USERNAME; } memcpy(info->username, username.data, username.size); info->username[username.size] = 0; /* Adjust data so it points to EncryptedPreMasterSecret */ data += username.size + 2; /*** 2. Decrypt and extract EncryptedPreMasterSecret ***/ DECR_LEN(data_size, 2); ciphertext.data = &data[2]; dsize = _gnutls_read_uint16(data); if (dsize != data_size) { gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } ciphertext.size = dsize; ret = gnutls_privkey_decrypt_data(session->internals.selected_key, 0, &ciphertext, &plaintext); if (ret < 0 || plaintext.size != GNUTLS_MASTER_SIZE) { /* In case decryption fails then don't inform * the peer. Just use a random key. (in order to avoid * attack against pkcs-1 formatting). */ gnutls_assert(); _gnutls_debug_log ("auth_rsa_psk: Possible PKCS #1 format attack\n"); if (ret >= 0) { gnutls_free(plaintext.data); } randomize_key = 1; } else { /* If the secret was properly formatted, then * check the version number. */ if (_gnutls_get_adv_version_major(session) != plaintext.data[0] || (session->internals.allow_wrong_pms == 0 && _gnutls_get_adv_version_minor(session) != plaintext.data[1])) { /* No error is returned here, if the version number check * fails. We proceed normally. * That is to defend against the attack described in the paper * "Attacking RSA-based sessions in SSL/TLS" by Vlastimil Klima, * Ondej Pokorny and Tomas Rosa. */ gnutls_assert(); _gnutls_debug_log ("auth_rsa: Possible PKCS #1 version check format attack\n"); } } if (randomize_key != 0) { 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; } /* we do not need strong random numbers here. */ ret = gnutls_rnd(GNUTLS_RND_NONCE, premaster_secret.data, premaster_secret.size); if (ret < 0) { gnutls_assert(); goto cleanup; } } else { premaster_secret.data = plaintext.data; premaster_secret.size = plaintext.size; } /* This is here to avoid the version check attack * discussed above. */ premaster_secret.data[0] = _gnutls_get_adv_version_major(session); premaster_secret.data[1] = _gnutls_get_adv_version_minor(session); /* find the key of this username */ ret = _gnutls_psk_pwd_find_entry(session, info->username, &pwd_psk); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = set_rsa_psk_session_key(session, &pwd_psk, &premaster_secret); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = 0; cleanup: _gnutls_free_key_datum(&pwd_psk); _gnutls_free_temp_key_datum(&premaster_secret); return ret; }
/* 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, ¶ms)) < 0) { gnutls_assert(); return ret; } /* Encrypt premaster secret */ if ((ret = _gnutls_pk_encrypt(GNUTLS_PK_RSA, &sdata, &premaster_secret, ¶ms)) < 0) { gnutls_assert(); return ret; } gnutls_pk_params_release(¶ms); 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; }
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; }
/* here we generate the TLS Master secret. */ static int generate_normal_master(gnutls_session_t session, gnutls_datum_t * premaster, int keep_premaster) { int ret = 0; char buf[512]; _gnutls_hard_log("INT: PREMASTER SECRET[%d]: %s\n", premaster->size, _gnutls_bin2hex(premaster->data, premaster->size, buf, sizeof(buf), NULL)); _gnutls_hard_log("INT: CLIENT RANDOM[%d]: %s\n", 32, _gnutls_bin2hex(session->security_parameters. client_random, 32, buf, sizeof(buf), NULL)); _gnutls_hard_log("INT: SERVER RANDOM[%d]: %s\n", 32, _gnutls_bin2hex(session->security_parameters. server_random, 32, buf, sizeof(buf), NULL)); if (session->security_parameters.ext_master_secret == 0) { uint8_t rnd[2 * GNUTLS_RANDOM_SIZE + 1]; memcpy(rnd, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); memcpy(&rnd[GNUTLS_RANDOM_SIZE], session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); #ifdef ENABLE_SSL3 if (get_num_version(session) == GNUTLS_SSL3) { ret = _gnutls_ssl3_generate_random(premaster->data, premaster->size, rnd, 2 * GNUTLS_RANDOM_SIZE, GNUTLS_MASTER_SIZE, session->security_parameters. master_secret); } else #endif ret = _gnutls_PRF(session, premaster->data, premaster->size, MASTER_SECRET, MASTER_SECRET_SIZE, rnd, 2 * GNUTLS_RANDOM_SIZE, GNUTLS_MASTER_SIZE, session->security_parameters. master_secret); } else { gnutls_datum_t shash = {NULL, 0}; /* draft-ietf-tls-session-hash-02 */ ret = _gnutls_handshake_get_session_hash(session, &shash); if (ret < 0) return gnutls_assert_val(ret); #ifdef ENABLE_SSL3 if (get_num_version(session) == GNUTLS_SSL3) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); #endif ret = _gnutls_PRF(session, premaster->data, premaster->size, EXT_MASTER_SECRET, EXT_MASTER_SECRET_SIZE, shash.data, shash.size, GNUTLS_MASTER_SIZE, session->security_parameters. master_secret); gnutls_free(shash.data); } write_nss_key_log(session, premaster); if (!keep_premaster) _gnutls_free_temp_key_datum(premaster); if (ret < 0) return ret; _gnutls_hard_log("INT: MASTER SECRET: %s\n", _gnutls_bin2hex(session->security_parameters. master_secret, GNUTLS_MASTER_SIZE, buf, sizeof(buf), NULL)); return ret; }
int _gnutls_proc_dh_common_client_kx(gnutls_session_t session, uint8_t * data, size_t _data_size, bigint_t g, bigint_t p, gnutls_datum_t * psk_key) { uint16_t n_Y; size_t _n_Y; int ret; ssize_t data_size = _data_size; gnutls_datum_t tmp_dh_key = {NULL, 0}; gnutls_pk_params_st peer_pub; gnutls_pk_params_init(&peer_pub); DECR_LEN(data_size, 2); n_Y = _gnutls_read_uint16(&data[0]); _n_Y = n_Y; DECR_LEN(data_size, n_Y); if (data_size != 0) return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); if (_gnutls_mpi_init_scan_nz(&session->key.client_Y, &data[2], _n_Y)) { gnutls_assert(); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; /* most likely zero or illegal size */ } _gnutls_dh_set_peer_public(session, session->key.client_Y); peer_pub.params[DH_Y] = session->key.client_Y; /* calculate the key after calculating the message */ ret = _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key, &session->key.dh_params, &peer_pub); if (ret < 0) { gnutls_assert(); goto error; } if (psk_key == NULL) { session->key.key.data = tmp_dh_key.data; session->key.key.size = tmp_dh_key.size; } else { /* In DHE_PSK the key is set differently */ ret = _gnutls_set_psk_session_key(session, psk_key, &tmp_dh_key); _gnutls_free_temp_key_datum(&tmp_dh_key); } if (ret < 0) { gnutls_assert(); goto error; } ret = 0; error: _gnutls_mpi_release(&session->key.client_Y); gnutls_pk_params_clear(&session->key.dh_params); return ret; }