static int gen_ecdhe_server_kx(gnutls_session_t session, gnutls_buffer_st * data) { int ret = 0; gnutls_certificate_credentials_t cred; 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; } ret = _gnutls_ecdh_common_print_server_kx(session, data, _gnutls_session_ecc_curve_get (session)); if (ret < 0) { gnutls_assert(); return ret; } /* Generate the signature. */ return _gnutls_gen_dhe_signature(session, data, data->data, data->length); }
/* 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); }
static int proc_dhe_client_kx (gnutls_session_t session, opaque * data, size_t _data_size) { gnutls_certificate_credentials_t cred; int ret; bigint_t p, g; const bigint_t *mpis; gnutls_dh_params_t dh_params; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, 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]; ret = _gnutls_proc_dh_common_client_kx (session, data, _data_size, g, p); return ret; }
/* just read the username from the client key exchange. */ int _gnutls_proc_psk_client_kx (gnutls_session_t session, opaque * data, size_t _data_size) { ssize_t data_size = _data_size; int ret; gnutls_datum_t username; gnutls_psk_server_credentials_t cred; psk_auth_info_t info; cred = (gnutls_psk_server_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_PSK, sizeof (psk_auth_info_st), 1)) < 0) { gnutls_assert (); return ret; } 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); 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; ret = _gnutls_set_psk_session_key (session, NULL); if (ret < 0) { gnutls_assert (); goto error; } ret = 0; error: return ret; }
/* 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; }
/*- * _gnutls_openpgp_crt_verify_peers - This function returns the peer's certificate status * @session: is a gnutls session * * This function will try to verify the peer's certificate and return its status (TRUSTED, INVALID etc.). * Returns a negative error code in case of an error, or GNUTLS_E_NO_CERTIFICATE_FOUND if no certificate was sent. * -*/ int _gnutls_openpgp_crt_verify_peers (gnutls_session_t session, unsigned int *status) { cert_auth_info_t info; gnutls_certificate_credentials_t cred; int peer_certificate_list_size, ret; CHECK_AUTH (GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST); info = _gnutls_get_auth_info (session); if (info == NULL) return GNUTLS_E_INVALID_REQUEST; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (info->raw_certificate_list == NULL || info->ncerts == 0) { gnutls_assert (); return GNUTLS_E_NO_CERTIFICATE_FOUND; } /* generate a list of gnutls_certs based on the auth info * raw certs. */ peer_certificate_list_size = info->ncerts; if (peer_certificate_list_size != 1) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } /* Verify certificate */ if (_E_gnutls_openpgp_verify_key == NULL) { gnutls_assert (); return GNUTLS_E_INIT_LIBEXTRA; } ret = _E_gnutls_openpgp_verify_key (cred, &info->raw_certificate_list[0], peer_certificate_list_size, status); if (ret < 0) { gnutls_assert (); return ret; } return 0; }
/* This function reads the RSA parameters from the private key */ static int _gnutls_get_private_rsa_params (gnutls_session_t session, bigint_t ** params, int *params_size) { int bits; gnutls_certificate_credentials_t cred; gnutls_rsa_params_t rsa_params; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (session->internals.selected_cert_list == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } bits = _gnutls_mpi_get_nbits (session->internals.selected_cert_list[0]. params[0]); if (_gnutls_cipher_suite_get_kx_algo (&session->security_parameters.current_cipher_suite) == GNUTLS_KX_RSA_EXPORT && bits > 512) { rsa_params = _gnutls_certificate_get_rsa_params (cred->rsa_params, cred->params_func, session); /* EXPORT case: */ if (rsa_params == NULL) { gnutls_assert (); return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS; } /* In the export case, we do use temporary RSA params * of 512 bits size. The params in the certificate are * used to sign this temporary stuff. */ *params_size = RSA_PRIVATE_PARAMS; *params = rsa_params->params; return 0; } /* non export cipher suites. */ *params_size = session->internals.selected_key->params_size; *params = session->internals.selected_key->params; return 0; }
/* * This returns a pointer to the linked list. Don't * free that!!! */ const void *_gnutls_get_kx_cred(gnutls_session_t session, gnutls_kx_algorithm_t algo) { int server = session->security_parameters.entity == GNUTLS_SERVER ? 1 : 0; return _gnutls_get_cred(session, _gnutls_map_kx_get_cred(algo, server)); }
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); }
/* just read the hint from the server key exchange. */ static int _gnutls_proc_psk_server_kx(gnutls_session_t session, uint8_t * data, size_t _data_size) { ssize_t data_size = _data_size; int ret; gnutls_datum_t hint; 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; } if ((ret = _gnutls_auth_info_set(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1)) < 0) { gnutls_assert(); return ret; } DECR_LENGTH_RET(data_size, 2, 0); hint.size = _gnutls_read_uint16(&data[0]); DECR_LEN(data_size, hint.size); hint.data = &data[2]; /* copy the hint 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 (hint.size > sizeof(info->hint)-1) { gnutls_assert(); return GNUTLS_E_ILLEGAL_SRP_USERNAME; } memcpy(info->hint, hint.data, hint.size); info->hint[hint.size] = 0; ret = 0; return ret; }
static int gen_psk_client_kx (gnutls_session_t session, opaque ** data) { int ret; opaque *tmp_data = NULL; int data_size, tmp_data_size; gnutls_psk_client_credentials_t cred; cred = (gnutls_psk_client_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (cred->username.data == NULL || cred->key.data == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } /* The PSK key is set in there */ ret = _gnutls_gen_dh_common_client_kx (session, &tmp_data); if (ret < 0) { gnutls_assert (); return ret; } tmp_data_size = ret; data_size = tmp_data_size + cred->username.size + 2; (*data) = gnutls_malloc (data_size); if ((*data) == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto error; } _gnutls_write_datum16 (*data, cred->username); memcpy (&(*data)[cred->username.size + 2], tmp_data, tmp_data_size); ret = data_size; error: gnutls_free (tmp_data); return ret; }
/* This function reads the RSA parameters from the private key */ static int _gnutls_get_private_rsa_params (gnutls_session_t session, gnutls_pk_params_st** params) { int ret; gnutls_certificate_credentials_t cred; gnutls_rsa_params_t rsa_params; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (session->internals.selected_cert_list == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } ret = _gnutls_pubkey_is_over_rsa_512(session->internals.selected_cert_list[0].pubkey); if (_gnutls_cipher_suite_get_kx_algo (session->security_parameters.cipher_suite) != GNUTLS_KX_RSA_EXPORT || ret < 0) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } rsa_params = _gnutls_certificate_get_rsa_params (cred->rsa_params, cred->params_func, session); /* EXPORT case: */ if (rsa_params == NULL) { gnutls_assert (); return GNUTLS_E_NO_TEMPORARY_RSA_PARAMS; } /* In the export case, we do use temporary RSA params * of 512 bits size. The params in the certificate are * used to sign this temporary stuff. */ *params = &rsa_params->params; return 0; }
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; }
/* Check if the given certificate type is supported. * This means that it is enabled by the priority functions, * and a matching certificate exists. */ int _gnutls_session_cert_type_supported (gnutls_session_t session, gnutls_certificate_type_t cert_type) { unsigned i; unsigned cert_found = 0; gnutls_certificate_credentials_t cred; if (session->security_parameters.entity == GNUTLS_SERVER) { cred = (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; if (cred->server_get_cert_callback == NULL && cred->get_cert_callback == NULL) { for (i = 0; i < cred->ncerts; i++) { if (cred->cert_list[i][0].type == cert_type) { cert_found = 1; break; } } if (cert_found == 0) /* no certificate is of that type. */ return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; } } if (session->internals.priorities.cert_type.algorithms == 0 && cert_type == DEFAULT_CERT_TYPE) return 0; for (i = 0; i < session->internals.priorities.cert_type.algorithms; i++) { if (session->internals.priorities.cert_type.priority[i] == cert_type) { return 0; /* ok */ } } return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE; }
/** * gnutls_credentials_get: * @session: is a #gnutls_session_t structure. * @type: is the type of the credentials to return * @cred: will contain the pointer to the credentials structure. * * Returns the previously provided credentials structures. * * For %GNUTLS_CRD_ANON, @cred will be * #gnutls_anon_client_credentials_t in case of a client. In case of * a server it should be #gnutls_anon_server_credentials_t. * * For %GNUTLS_CRD_SRP, @cred will be #gnutls_srp_client_credentials_t * in case of a client, and #gnutls_srp_server_credentials_t, in case * of a server. * * For %GNUTLS_CRD_CERTIFICATE, @cred will be * #gnutls_certificate_credentials_t. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. **/ int gnutls_credentials_get(gnutls_session_t session, gnutls_credentials_type_t type, void **cred) { const void *_cred; _cred = _gnutls_get_cred(session, type); if (_cred == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); if (cred) *cred = (void*)_cred; return 0; }
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; }
/** * gnutls_certificate_get_ours: * @session: is a gnutls session * * Gets the certificate as sent to the peer in the last handshake. * The certificate is in raw (DER) format. No certificate * list is being returned. Only the first certificate. * * Returns: a pointer to a #gnutls_datum_t containing our * certificate, or %NULL in case of an error or if no certificate * was used. **/ const gnutls_datum_t *gnutls_certificate_get_ours(gnutls_session_t session) { gnutls_certificate_credentials_t cred; CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, NULL); cred = (gnutls_certificate_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); if (cred == NULL || cred->certs == NULL) { gnutls_assert(); return NULL; } if (session->internals.selected_cert_list == NULL) return NULL; return &session->internals.selected_cert_list[0].cert; }
static int proc_ecdhe_client_kx(gnutls_session_t session, uint8_t * data, size_t _data_size) { gnutls_certificate_credentials_t cred; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) { gnutls_assert(); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } return _gnutls_proc_ecdh_common_client_kx(session, data, _data_size, _gnutls_session_ecc_curve_get (session), NULL); }
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; }
/* 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; }
static int gen_dhe_server_kx(gnutls_session_t session, gnutls_buffer_st * data) { int ret = 0; gnutls_certificate_credentials_t cred; unsigned sig_pos; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); if (cred == NULL) { gnutls_assert(); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if ((ret = _gnutls_auth_info_init(session, GNUTLS_CRD_CERTIFICATE, sizeof(cert_auth_info_st), 1)) < 0) { gnutls_assert(); return ret; } ret = _gnutls_figure_dh_params(session, cred->dh_params, cred->params_func, cred->dh_sec_param); if (ret < 0) { return gnutls_assert_val(ret); } sig_pos = data->length; 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[sig_pos], data->length-sig_pos); }
static int proc_anon_client_kx (gnutls_session_t session, opaque * data, size_t _data_size) { gnutls_anon_server_credentials_t cred; int bits; int ret; mpi_t p, g; gnutls_dh_params_t dh_params; const mpi_t *mpis; bits = _gnutls_dh_get_allowed_prime_bits (session); 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]; ret = _gnutls_proc_dh_common_client_kx (session, data, _data_size, g, p); return ret; }
/* Generates the PSK server key exchange * * struct { * select (KeyExchangeAlgorithm) { * // other cases for rsa, diffie_hellman, etc. * case psk: // NEW * opaque psk_identity_hint<0..2^16-1>; * }; * } ServerKeyExchange; * */ int _gnutls_gen_psk_server_kx (gnutls_session_t session, opaque ** data) { gnutls_psk_server_credentials_t cred; gnutls_datum_t hint; cred = (gnutls_psk_server_credentials_t) _gnutls_get_cred (session->key, 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 = cred->hint; hint.size = strlen (cred->hint); (*data) = gnutls_malloc (2 + hint.size); if ((*data) == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _gnutls_write_datum16 (*data, hint); return hint.size + 2; }
static int server_send(gnutls_session_t session, gnutls_buffer_st * extdata, status_request_ext_st * priv) { int ret; gnutls_certificate_credentials_t cred; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) /* no certificate authentication */ return gnutls_assert_val(0); if (cred->ocsp_func == NULL) return gnutls_assert_val(GNUTLS_E_SUCCESS); ret = cred->ocsp_func(session, cred->ocsp_func_ptr, &priv->response); if (ret == GNUTLS_E_NO_CERTIFICATE_STATUS) return 0; else if (ret < 0) return gnutls_assert_val(ret); return GNUTLS_E_INT_RET_0; }
/* * Return values for this function: * - 0 : Not applicable. * - >0 : Ok. Return size of extension data. * - GNUTLS_E_INT_RET_0 : Size of extension data is zero. * - <0 : There's been an error. * * In the client, generates the PskIdentity and PskBinderEntry messages. * * PskIdentity identities<7..2^16-1>; * PskBinderEntry binders<33..2^16-1>; * * struct { * opaque identity<1..2^16-1>; * uint32 obfuscated_ticket_age; * } PskIdentity; * * opaque PskBinderEntry<32..255>; * * The server sends the selected identity, which is a zero-based index * of the PSKs offered by the client: * * struct { * uint16 selected_identity; * } PreSharedKeyExtension; */ static int _gnutls_psk_send_params(gnutls_session_t session, gnutls_buffer_t extdata) { gnutls_psk_client_credentials_t cred = NULL; const version_entry_st *vers; if (session->security_parameters.entity == GNUTLS_CLIENT) { vers = _gnutls_version_max(session); if (!vers || !vers->tls13_sem) return 0; if (session->internals.hsk_flags & HSK_PSK_KE_MODES_SENT) { cred = (gnutls_psk_client_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_PSK); } if ((session->internals.flags & GNUTLS_NO_TICKETS) && !session->internals.priorities->have_psk) return 0; return client_send_params(session, extdata, cred); } else { vers = get_version(session); if (!vers || !vers->tls13_sem) return 0; if ((session->internals.flags & GNUTLS_NO_TICKETS) && !session->internals.priorities->have_psk) return 0; if (session->internals.hsk_flags & HSK_PSK_KE_MODES_RECEIVED) return server_send_params(session, extdata); else return 0; } }
static int _gnutls_ia_server_handshake (gnutls_session_t session) { gnutls_ia_apptype_t msg_type; ssize_t len; char buf[1024]; int ret; const struct gnutls_ia_server_credentials_st *cred = _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL); if (cred == NULL) return GNUTLS_E_INTERNAL_ERROR; do { char *avp; size_t avplen; len = gnutls_ia_recv (session, buf, sizeof (buf)); if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED || len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) { ret = gnutls_ia_verify_endphase (session, buf); if (ret < 0) return ret; } if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED) continue; else if (len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) break; if (len < 0) return len; avp = NULL; avplen = 0; ret = cred->avp_func (session, cred->avp_ptr, buf, len, &avp, &avplen); if (ret < 0) { int tmpret; tmpret = gnutls_alert_send (session, GNUTLS_AL_FATAL, GNUTLS_A_INNER_APPLICATION_FAILURE); if (tmpret < 0) gnutls_assert (); return ret; } msg_type = ret; if (msg_type != GNUTLS_IA_APPLICATION_PAYLOAD) { ret = gnutls_ia_endphase_send (session, msg_type == GNUTLS_IA_FINAL_PHASE_FINISHED); if (ret < 0) return ret; } else { len = gnutls_ia_send (session, avp, avplen); gnutls_free (avp); if (len < 0) return len; } } while (1); return 0; }
static int _gnutls_ia_client_handshake (gnutls_session_t session) { char *buf = NULL; size_t buflen = 0; char tmp[1024]; /* XXX */ ssize_t len; int ret; const struct gnutls_ia_client_credentials_st *cred = _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL); if (cred == NULL) return GNUTLS_E_INTERNAL_ERROR; while (1) { char *avp; size_t avplen; ret = cred->avp_func (session, cred->avp_ptr, buf, buflen, &avp, &avplen); if (ret) { int tmpret; tmpret = gnutls_alert_send (session, GNUTLS_AL_FATAL, GNUTLS_A_INNER_APPLICATION_FAILURE); if (tmpret < 0) gnutls_assert (); return ret; } len = gnutls_ia_send (session, avp, avplen); gnutls_free (avp); if (len < 0) return len; len = gnutls_ia_recv (session, tmp, sizeof (tmp)); if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED || len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) { ret = gnutls_ia_verify_endphase (session, tmp); if (ret < 0) return ret; ret = gnutls_ia_endphase_send (session, len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED); if (ret < 0) return ret; } if (len == GNUTLS_E_WARNING_IA_IPHF_RECEIVED) { buf = NULL; buflen = 0; continue; } else if (len == GNUTLS_E_WARNING_IA_FPHF_RECEIVED) break; if (len < 0) return len; buflen = len; buf = tmp; } return 0; }
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 data_size or a negative number on failure */ int _gnutls_inner_application_send_params (gnutls_session_t session, opaque * data, size_t data_size) { tls_ext_st *ext = &session->security_parameters.extensions; /* Set ext->gnutls_ia_enable depending on whether we have a TLS/IA credential in the session. */ if (session->security_parameters.entity == GNUTLS_CLIENT) { gnutls_ia_client_credentials_t cred = (gnutls_ia_client_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL); if (cred) ext->gnutls_ia_enable = 1; } else { gnutls_ia_server_credentials_t cred = (gnutls_ia_server_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_IA, NULL); if (cred) ext->gnutls_ia_enable = 1; } /* If we don't want gnutls_ia locally, or we are a server and the * client doesn't want it, don't advertise TLS/IA support at all, as * required. */ if (!ext->gnutls_ia_enable) return 0; if (session->security_parameters.entity == GNUTLS_SERVER && !ext->gnutls_ia_peer_enable) return 0; /* We'll advertise. Check if there's room in the hello buffer. */ if (data_size < 1) { gnutls_assert (); return GNUTLS_E_SHORT_MEMORY_BUFFER; } /* default: require new application phase */ *data = YES; if (session->security_parameters.entity == GNUTLS_CLIENT) { /* Client: value follows local setting */ if (ext->gnutls_ia_allowskip) *data = NO; } else { /* Server: value follows local setting and client's setting, but only * if we are resuming. * * XXX Can server test for resumption at this stage? * * Ai! It seems that read_client_hello only calls parse_extensions if * we're NOT resuming! That would make us automatically violate the IA * draft; if we're resuming, we must first learn what the client wants * -- IA or no IA -- and then prepare our response. Right now we'll * always skip IA on resumption, because recv_ext isn't even called * to record the peer's support for IA at all. Simon? */ if (ext->gnutls_ia_allowskip && ext->gnutls_ia_peer_allowskip && session->internals.resumed == RESUME_TRUE) *data = NO; } return 1; }
/* receive the key exchange message ( n, g, s, B) */ int _gnutls_proc_srp_server_kx (gnutls_session_t session, opaque * data, size_t _data_size) { uint8_t n_s; uint16_t n_g, n_n, n_b; size_t _n_s, _n_g, _n_n, _n_b; const uint8_t *data_n; const uint8_t *data_g; const uint8_t *data_s; const uint8_t *data_b; int i, ret; opaque hd[SRP_MAX_HASH_SIZE]; char *username, *password; ssize_t data_size = _data_size; gnutls_srp_client_credentials_t cred; cred = (gnutls_srp_client_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_SRP, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (session->internals.srp_username == NULL) { username = cred->username; password = cred->password; } else { username = session->internals.srp_username; password = session->internals.srp_password; } if (username == NULL || password == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } i = 0; /* Read N */ DECR_LEN (data_size, 2); n_n = _gnutls_read_uint16 (&data[i]); i += 2; DECR_LEN (data_size, n_n); data_n = &data[i]; i += n_n; /* Read G */ 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; /* Read salt */ DECR_LEN (data_size, 1); n_s = data[i]; i += 1; DECR_LEN (data_size, n_s); data_s = &data[i]; i += n_s; /* Read B */ DECR_LEN (data_size, 2); n_b = _gnutls_read_uint16 (&data[i]); i += 2; DECR_LEN (data_size, n_b); data_b = &data[i]; i += n_b; _n_s = n_s; _n_g = n_g; _n_n = n_n; _n_b = n_b; if (_gnutls_mpi_scan_nz (&N, data_n, &_n_n) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } if (_gnutls_mpi_scan_nz (&G, data_g, &_n_g) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } if (_gnutls_mpi_scan_nz (&B, data_b, &_n_b) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* Check if the g and n are from the SRP * draft. Otherwise check if N is a prime and G * a generator. */ if ((ret = check_g_n (data_g, _n_g, data_n, _n_n)) < 0) { _gnutls_x509_log ("Checking the SRP group parameters.\n"); if ((ret = group_check_g_n (G, N)) < 0) { gnutls_assert (); return ret; } } /* Checks if b % n == 0 */ if ((ret = check_b_mod_n (B, N)) < 0) { gnutls_assert (); return ret; } /* generate x = SHA(s | SHA(U | ":" | p)) * (or the equivalent using bcrypt) */ if ((ret = _gnutls_calc_srp_x (username, password, (opaque *) data_s, n_s, &_n_g, hd)) < 0) { gnutls_assert (); return ret; } if (_gnutls_mpi_scan_nz (&session->key->x, hd, &_n_g) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } return i; /* return the processed data * needed in auth_srp_rsa. */ }