static int gen_dhe_server_kx(gnutls_session_t session, gnutls_buffer_st * data) { bigint_t g, p; const bigint_t *mpis; int ret = 0; gnutls_certificate_credentials_t cred; gnutls_dh_params_t dh_params; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) { gnutls_assert(); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if ((ret = _gnutls_auth_info_set(session, GNUTLS_CRD_CERTIFICATE, sizeof(cert_auth_info_st), 0)) < 0) { gnutls_assert(); return ret; } dh_params = _gnutls_get_dh_params(cred->dh_params, cred->params_func, session); mpis = _gnutls_dh_params_to_mpi(dh_params); if (mpis == NULL) { gnutls_assert(); return GNUTLS_E_NO_TEMPORARY_DH_PARAMS; } p = mpis[0]; g = mpis[1]; _gnutls_dh_set_group(session, g, p); ret = _gnutls_set_dh_pk_params(session, g, p, dh_params->q_bits); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_dh_common_print_server_kx(session, data); if (ret < 0) { gnutls_assert(); return ret; } /* Generate the signature. */ return _gnutls_gen_dhe_signature(session, data, data->data, data->length); }
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 gen_anon_server_kx (gnutls_session_t session, gnutls_buffer_st* data) { bigint_t g, p; const bigint_t *mpis; int ret; gnutls_dh_params_t dh_params; gnutls_anon_server_credentials_t cred; cred = (gnutls_anon_server_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_ANON, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } dh_params = _gnutls_get_dh_params (cred->dh_params, cred->params_func, session); mpis = _gnutls_dh_params_to_mpi (dh_params); if (mpis == NULL) { gnutls_assert (); return GNUTLS_E_NO_TEMPORARY_DH_PARAMS; } p = mpis[0]; g = mpis[1]; if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_ANON, sizeof (anon_auth_info_st), 1)) < 0) { gnutls_assert (); return ret; } _gnutls_dh_set_group (session, g, p); ret = _gnutls_dh_common_print_server_kx (session, g, p, data, 0); if (ret < 0) { gnutls_assert (); } return ret; }
static int gen_dhe_server_kx (gnutls_session_t session, opaque ** data) { bigint_t g, p; const bigint_t *mpis; int ret = 0, data_size; gnutls_cert *apr_cert_list; gnutls_privkey_t apr_pkey; int apr_cert_list_length; gnutls_datum_t signature = { NULL, 0 }, ddata; gnutls_certificate_credentials_t cred; gnutls_dh_params_t dh_params; gnutls_sign_algorithm_t sign_algo; gnutls_protocol_t ver = gnutls_protocol_get_version (session); cred = (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } /* find the appropriate certificate */ if ((ret = _gnutls_get_selected_cert (session, &apr_cert_list, &apr_cert_list_length, &apr_pkey)) < 0) { gnutls_assert (); return ret; } dh_params = _gnutls_get_dh_params (cred->dh_params, cred->params_func, session); mpis = _gnutls_dh_params_to_mpi (dh_params); if (mpis == NULL) { gnutls_assert (); return GNUTLS_E_NO_TEMPORARY_DH_PARAMS; } p = mpis[0]; g = mpis[1]; if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE, sizeof (cert_auth_info_st), 0)) < 0) { gnutls_assert (); return ret; } _gnutls_dh_set_group (session, g, p); ret = _gnutls_dh_common_print_server_kx (session, g, p, data, 0); if (ret < 0) { gnutls_assert (); return ret; } data_size = ret; /* Generate the signature. */ ddata.data = *data; ddata.size = data_size; if (apr_cert_list_length > 0) { if ((ret = _gnutls_handshake_sign_data (session, &apr_cert_list[0], apr_pkey, &ddata, &signature, &sign_algo)) < 0) { gnutls_assert (); goto cleanup; } } else { gnutls_assert (); ret = data_size; /* do not put a signature - ILLEGAL! */ goto cleanup; } *data = gnutls_realloc_fast (*data, data_size + signature.size + 4); if (*data == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } if (_gnutls_version_has_selectable_sighash (ver)) { const sign_algorithm_st *aid; if (sign_algo == GNUTLS_SIGN_UNKNOWN) { ret = GNUTLS_E_UNKNOWN_ALGORITHM; goto cleanup; } aid = _gnutls_sign_to_tls_aid (sign_algo); if (aid == NULL) { gnutls_assert(); ret = GNUTLS_E_UNKNOWN_ALGORITHM; goto cleanup; } (*data)[data_size++] = aid->hash_algorithm; (*data)[data_size++] = aid->sign_algorithm; } _gnutls_write_datum16 (&(*data)[data_size], signature); data_size += signature.size + 2; _gnutls_free_datum (&signature); return data_size; cleanup: _gnutls_free_datum (&signature); gnutls_free(*data); return ret; }
/* Returns the bytes parsed */ int _gnutls_proc_dh_common_server_kx (gnutls_session_t session, uint8_t * data, size_t _data_size) { uint16_t n_Y, n_g, n_p; size_t _n_Y, _n_g, _n_p; uint8_t *data_p; uint8_t *data_g; uint8_t *data_Y; int i, bits, ret; ssize_t data_size = _data_size; i = 0; DECR_LEN (data_size, 2); n_p = _gnutls_read_uint16 (&data[i]); i += 2; DECR_LEN (data_size, n_p); data_p = &data[i]; i += n_p; DECR_LEN (data_size, 2); n_g = _gnutls_read_uint16 (&data[i]); i += 2; DECR_LEN (data_size, n_g); data_g = &data[i]; i += n_g; DECR_LEN (data_size, 2); n_Y = _gnutls_read_uint16 (&data[i]); i += 2; DECR_LEN (data_size, n_Y); data_Y = &data[i]; _n_Y = n_Y; _n_g = n_g; _n_p = n_p; if (_gnutls_mpi_scan_nz (&session->key.client_Y, data_Y, _n_Y) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } if (_gnutls_mpi_scan_nz (&session->key.client_g, data_g, _n_g) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } if (_gnutls_mpi_scan_nz (&session->key.client_p, data_p, _n_p) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } bits = _gnutls_dh_get_allowed_prime_bits (session); if (bits < 0) { gnutls_assert (); return bits; } if (_gnutls_mpi_get_nbits (session->key.client_p) < (size_t) bits) { /* the prime used by the peer is not acceptable */ gnutls_assert (); return GNUTLS_E_DH_PRIME_UNACCEPTABLE; } _gnutls_dh_set_group (session, session->key.client_g, session->key.client_p); _gnutls_dh_set_peer_public (session, session->key.client_Y); ret = n_Y + n_p + n_g + 6; return ret; }
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; }
/* Returns the bytes parsed */ int _gnutls_proc_dh_common_server_kx(gnutls_session_t session, uint8_t * data, size_t _data_size) { uint16_t n_Y, n_g, n_p; size_t _n_Y, _n_g, _n_p; uint8_t *data_p; uint8_t *data_g; uint8_t *data_Y; int i, bits, ret, p_bits; ssize_t data_size = _data_size; /* just in case we are resuming a session */ gnutls_pk_params_release(&session->key.dh_params); gnutls_pk_params_init(&session->key.dh_params); i = 0; DECR_LEN(data_size, 2); n_p = _gnutls_read_uint16(&data[i]); i += 2; DECR_LEN(data_size, n_p); data_p = &data[i]; i += n_p; DECR_LEN(data_size, 2); n_g = _gnutls_read_uint16(&data[i]); i += 2; DECR_LEN(data_size, n_g); data_g = &data[i]; i += n_g; DECR_LEN(data_size, 2); n_Y = _gnutls_read_uint16(&data[i]); i += 2; DECR_LEN(data_size, n_Y); data_Y = &data[i]; _n_Y = n_Y; _n_g = n_g; _n_p = n_p; if (_gnutls_mpi_init_scan_nz(&session->key.client_Y, data_Y, _n_Y) != 0) { gnutls_assert(); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } if (_gnutls_mpi_init_scan_nz(&session->key.dh_params.params[DH_G], data_g, _n_g) != 0) { gnutls_assert(); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } if (_gnutls_mpi_init_scan_nz(&session->key.dh_params.params[DH_P], data_p, _n_p) != 0) { gnutls_assert(); /* we release now because session->key.dh_params.params_nr is not yet set */ _gnutls_mpi_release(&session->key.dh_params.params[DH_G]); return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; } session->key.dh_params.params_nr = 3; /* include empty q */ session->key.dh_params.algo = GNUTLS_PK_DH; bits = _gnutls_dh_get_min_prime_bits(session); if (bits < 0) { gnutls_assert(); return bits; } p_bits = _gnutls_mpi_get_nbits(session->key.dh_params.params[DH_P]); if (p_bits < bits) { /* the prime used by the peer is not acceptable */ gnutls_assert(); _gnutls_debug_log ("Received a prime of %u bits, limit is %u\n", (unsigned) _gnutls_mpi_get_nbits(session->key.dh_params.params[DH_P]), (unsigned) bits); return GNUTLS_E_DH_PRIME_UNACCEPTABLE; } if (p_bits >= DEFAULT_MAX_VERIFY_BITS) { gnutls_assert(); _gnutls_debug_log ("Received a prime of %u bits, limit is %u\n", (unsigned) p_bits, (unsigned) DEFAULT_MAX_VERIFY_BITS); return GNUTLS_E_DH_PRIME_UNACCEPTABLE; } _gnutls_dh_set_group(session, session->key.dh_params.params[DH_G], session->key.dh_params.params[DH_P]); _gnutls_dh_set_peer_public(session, session->key.client_Y); ret = n_Y + n_p + n_g + 6; return ret; }