gnutls_psk_client_get_hint@GNUTLS_3_4
gnutls_psk_free_client_credentials@GNUTLS_3_4
gnutls_psk_free_server_credentials@GNUTLS_3_4
+gnutls_psk_server_get_username2@GNUTLS_3_6_13
gnutls_psk_server_get_username@GNUTLS_3_4
+gnutls_psk_set_client_credentials2@GNUTLS_3_6_13
gnutls_psk_set_client_credentials@GNUTLS_3_4
+gnutls_psk_set_client_credentials_function2@GNUTLS_3_6_13
gnutls_psk_set_client_credentials_function@GNUTLS_3_4
gnutls_psk_set_params_function@GNUTLS_3_4
gnutls_psk_set_server_credentials_file@GNUTLS_3_4
+gnutls_psk_set_server_credentials_function2@GNUTLS_3_6_13
gnutls_psk_set_server_credentials_function@GNUTLS_3_4
gnutls_psk_set_server_credentials_hint@GNUTLS_3_4
gnutls_psk_set_server_dh_params@GNUTLS_3_4
FUNCS += functions/gnutls_psk_free_server_credentials.short
FUNCS += functions/gnutls_psk_server_get_username
FUNCS += functions/gnutls_psk_server_get_username.short
+FUNCS += functions/gnutls_psk_server_get_username2
+FUNCS += functions/gnutls_psk_server_get_username2.short
FUNCS += functions/gnutls_psk_set_client_credentials
FUNCS += functions/gnutls_psk_set_client_credentials.short
+FUNCS += functions/gnutls_psk_set_client_credentials2
+FUNCS += functions/gnutls_psk_set_client_credentials2.short
FUNCS += functions/gnutls_psk_set_client_credentials_function
FUNCS += functions/gnutls_psk_set_client_credentials_function.short
+FUNCS += functions/gnutls_psk_set_client_credentials_function2
+FUNCS += functions/gnutls_psk_set_client_credentials_function2.short
FUNCS += functions/gnutls_psk_set_params_function
FUNCS += functions/gnutls_psk_set_params_function.short
FUNCS += functions/gnutls_psk_set_server_credentials_file
FUNCS += functions/gnutls_psk_set_server_credentials_file.short
FUNCS += functions/gnutls_psk_set_server_credentials_function
FUNCS += functions/gnutls_psk_set_server_credentials_function.short
+FUNCS += functions/gnutls_psk_set_server_credentials_function2
+FUNCS += functions/gnutls_psk_set_server_credentials_function2.short
FUNCS += functions/gnutls_psk_set_server_credentials_hint
FUNCS += functions/gnutls_psk_set_server_credentials_hint.short
FUNCS += functions/gnutls_psk_set_server_dh_params
APIMANS += gnutls_psk_free_client_credentials.3
APIMANS += gnutls_psk_free_server_credentials.3
APIMANS += gnutls_psk_server_get_username.3
+APIMANS += gnutls_psk_server_get_username2.3
APIMANS += gnutls_psk_set_client_credentials.3
+APIMANS += gnutls_psk_set_client_credentials2.3
APIMANS += gnutls_psk_set_client_credentials_function.3
+APIMANS += gnutls_psk_set_client_credentials_function2.3
APIMANS += gnutls_psk_set_params_function.3
APIMANS += gnutls_psk_set_server_credentials_file.3
APIMANS += gnutls_psk_set_server_credentials_function.3
+APIMANS += gnutls_psk_set_server_credentials_function2.3
APIMANS += gnutls_psk_set_server_credentials_hint.3
APIMANS += gnutls_psk_set_server_dh_params.3
APIMANS += gnutls_psk_set_server_known_dh_params.3
return GNUTLS_E_ILLEGAL_SRP_USERNAME;
}
- memcpy(info->username, username.data, username.size);
- info->username[username.size] = 0;
+ _gnutls_copy_psk_username(info, &username);
/* Adjust the data */
data += username.size + 2;
ret =
- _gnutls_psk_pwd_find_entry(session, info->username, &psk_key);
+ _gnutls_psk_pwd_find_entry(session, info->username, info->username_len, &psk_key);
if (ret < 0)
return gnutls_assert_val(ret);
return GNUTLS_E_ILLEGAL_SRP_USERNAME;
}
- memcpy(info->username, username.data, username.size);
- info->username[username.size] = 0;
+ _gnutls_copy_psk_username(info, &username);
/* Adjust the data */
data += username.size + 2;
/* should never fail. It will always return a key even if it is
* a random one */
ret =
- _gnutls_psk_pwd_find_entry(session, info->username, &psk_key);
+ _gnutls_psk_pwd_find_entry(session, info->username, info->username_len, &psk_key);
if (ret < 0)
return gnutls_assert_val(ret);
}
assert(username.data != NULL);
- memcpy(info->username, username.data, username.size);
- info->username[username.size] = 0;
+ _gnutls_copy_psk_username(info, &username);
cleanup:
return GNUTLS_E_ILLEGAL_SRP_USERNAME;
}
- memcpy(info->username, username.data, username.size);
- info->username[username.size] = 0;
+ _gnutls_copy_psk_username(info, &username);
ret =
- _gnutls_psk_pwd_find_entry(session, info->username, &psk_key);
+ _gnutls_psk_pwd_find_entry(session, info->username, info->username_len, &psk_key);
if (ret < 0)
return gnutls_assert_val(ret);
typedef struct gnutls_psk_client_credentials_st {
gnutls_datum_t username;
gnutls_datum_t key;
- gnutls_psk_client_credentials_function *get_function;
+ gnutls_psk_client_credentials_function2 *get_function;
+ gnutls_psk_client_credentials_function *get_function_legacy;
/* TLS 1.3 - The HMAC algorithm to use to compute the binder values */
const mac_entry_st *binder_algo;
} psk_client_credentials_st;
/* callback function, instead of reading the
* password files.
*/
- gnutls_psk_server_credentials_function *pwd_callback;
+ gnutls_psk_server_credentials_function2 *pwd_callback;
+ gnutls_psk_server_credentials_function *pwd_callback_legacy;
/* For DHE_PSK */
gnutls_dh_params_t dh_params;
/* these structures should not use allocated data */
typedef struct psk_auth_info_st {
char username[MAX_USERNAME_SIZE + 1];
+ uint16_t username_len;
dh_info_st dh;
char hint[MAX_USERNAME_SIZE + 1];
} *psk_auth_info_t;
typedef struct psk_auth_info_st psk_auth_info_st;
+inline static
+void _gnutls_copy_psk_username(psk_auth_info_t info, const gnutls_datum_t *username)
+{
+ assert(sizeof(info->username) > username->size);
+ memcpy(info->username, username->data, username->size);
+ info->username[username->size] = 0;
+ info->username_len = username->size;
+}
+
#ifdef ENABLE_PSK
int
gnutls_buffer_st * data);
int _gnutls_gen_psk_client_kx(gnutls_session_t, gnutls_buffer_st *);
-
#else
#define _gnutls_set_psk_session_key(x,y,z) GNUTLS_E_UNIMPLEMENTED_FEATURE
#endif /* ENABLE_PSK */
}
return 0;
+}
+
+static bool username_matches(const gnutls_datum_t *username,
+ const char *line, size_t line_size)
+{
+ int retval;
+ unsigned i;
+ gnutls_datum_t hexline, hex_username = { NULL, 0 };
+
+ /*
+ * Guard against weird behavior - we don't check 'line',
+ * as it's returned by getline(), which will never return NULL
+ * if successful.
+ */
+ if (username->data == NULL)
+ return false;
+
+ if (line_size == 0)
+ return (username->size == 0);
+
+ /* move to first ':' */
+ i = 0;
+ while ((i < line_size) && (line[i] != '\0')
+ && (line[i] != ':')) {
+ i++;
+ }
+
+ if (line[0] == '#') {
+ hexline.data = (void *) &line[1];
+ hexline.size = i - 1;
+ if ((retval = gnutls_hex_decode2(&hexline, &hex_username)) < 0)
+ return gnutls_assert_val(0);
+
+ if (hex_username.size == username->size)
+ retval = memcmp(username->data, hex_username.data, username->size);
+ else
+ retval = -1;
+
+ _gnutls_free_datum(&hex_username);
+ } else {
+ retval = strncmp((const char *) username->data, line, MAX(i, username->size));
+ }
+
+ return (retval == 0);
}
* If the user doesn't exist a random password is returned instead.
*/
int
-_gnutls_psk_pwd_find_entry(gnutls_session_t session, char *username,
+_gnutls_psk_pwd_find_entry(gnutls_session_t session,
+ const char *username, uint16_t username_len,
gnutls_datum_t * psk)
{
gnutls_psk_server_credentials_t cred;
FILE *fd;
char *line = NULL;
size_t line_size = 0;
- unsigned i, len;
int ret;
+ gnutls_datum_t username_datum = {
+ .data = (unsigned char *) username,
+ .size = username_len
+ };
cred = (gnutls_psk_server_credentials_t)
_gnutls_get_cred(session, GNUTLS_CRD_PSK);
* set, use it.
*/
if (cred->pwd_callback != NULL) {
- ret = cred->pwd_callback(session, username, psk);
+ ret = cred->pwd_callback(session, &username_datum, psk);
if (ret == 1) { /* the user does not exist */
ret = _randomize_psk(psk);
return GNUTLS_E_SRP_PWD_ERROR;
}
- len = strlen(username);
while (getline(&line, &line_size, fd) > 0) {
- /* move to first ':' */
- i = 0;
- while ((i < line_size) && (line[i] != '\0')
- && (line[i] != ':')) {
- i++;
- }
-
- if (strncmp(username, line, MAX(i, len)) == 0) {
+ if (username_matches(&username_datum, line, line_size)) {
ret = pwd_put_values(psk, line);
if (ret < 0) {
gnutls_assert();
gnutls_datum_t * username, gnutls_datum_t * key,
int *free)
{
- char *user_p;
int ret;
*free = 0;
key->data = cred->key.data;
key->size = cred->key.size;
} else if (cred->get_function != NULL) {
- ret = cred->get_function(session, &user_p, key);
+ ret = cred->get_function(session, username, key);
+
if (ret)
return gnutls_assert_val(ret);
- username->data = (uint8_t *) user_p;
- username->size = strlen(user_p);
-
*free = 1;
} else
return
#define GNUTLS_LIB_AUTH_PSK_PASSWD_H
/* this is locally allocated. It should be freed using the provided function */
-int _gnutls_psk_pwd_find_entry(gnutls_session_t, char *username,
+int _gnutls_psk_pwd_find_entry(gnutls_session_t,
+ const char *username, uint16_t username_len,
gnutls_datum_t * key);
int _gnutls_find_psk_key(gnutls_session_t session,
return GNUTLS_E_ILLEGAL_SRP_USERNAME;
}
- memcpy(info->username, username.data, username.size);
- info->username[username.size] = 0;
+ _gnutls_copy_psk_username(info, &username);
/* Adjust data so it points to EncryptedPreMasterSecret */
data += username.size + 2;
/* find the key of this username
*/
ret =
- _gnutls_psk_pwd_find_entry(session, info->username, &pwd_psk);
+ _gnutls_psk_pwd_find_entry(session, info->username, strlen(info->username), &pwd_psk);
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;
+ _gnutls_copy_psk_username(info, &username);
if ((ret = _gnutls_buffer_append_data_prefix(extdata, 16,
username.data,
} else if (pskcred &&
psk.ob_ticket_age == 0 &&
psk.identity.size > 0 && psk.identity.size <= MAX_USERNAME_SIZE) {
- /* _gnutls_psk_pwd_find_entry() expects 0-terminated identities */
- char identity_str[MAX_USERNAME_SIZE + 1];
-
prf = pskcred->binder_algo;
- memcpy(identity_str, psk.identity.data, psk.identity.size);
- identity_str[psk.identity.size] = 0;
-
/* this fails only on configuration errors; as such we always
* return its error code in that case */
- ret = _gnutls_psk_pwd_find_entry(session, identity_str, &key);
+ ret = _gnutls_psk_pwd_find_entry(session, (char *) psk.identity.data, psk.identity.size, &key);
if (ret < 0)
return gnutls_assert_val(ret);
info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
assert(info != NULL);
- memcpy(info->username, psk.identity.data, psk.identity.size);
- info->username[psk.identity.size] = 0;
+ _gnutls_copy_psk_username(info, &psk.identity);
_gnutls_handshake_log("EXT[%p]: selected PSK identity: %s (%d)\n", session, info->username, psk_index);
} else {
if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) {
cred_type = gnutls_auth_get_type(session);
if (cred_type == GNUTLS_CRD_PSK || cred_type == GNUTLS_CRD_SRP) {
const char *username = NULL;
+ size_t username_length;
if (cred_type == GNUTLS_CRD_PSK) {
psk_auth_info_t ai;
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
username = ai->username;
+ username_length = ai->username_len;
#ifdef ENABLE_SRP
} else {
srp_server_auth_info_t ai = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP);
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
username = ai->username;
+ username_length = strlen(ai->username);
#endif
}
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
if (session->internals.saved_username_set) {
- if (strcmp(session->internals.saved_username, username) != 0) {
+ if (strncmp(session->internals.saved_username, username, username_length) != 0) {
_gnutls_debug_log("Session's PSK username changed during rehandshake; aborting!\n");
return gnutls_assert_val(GNUTLS_E_SESSION_USER_ID_CHANGED);
}
} else {
- size_t len = strlen(username);
-
- memcpy(session->internals.saved_username, username, len);
- session->internals.saved_username[len] = 0;
+ memcpy(session->internals.saved_username, username, username_length);
+ session->internals.saved_username[username_length] = 0;
session->internals.saved_username_set = 1;
}
}
const char *username,
const gnutls_datum_t * key,
gnutls_psk_key_flags flags);
+int gnutls_psk_set_client_credentials2(gnutls_psk_client_credentials_t res,
+ const gnutls_datum_t *username,
+ const gnutls_datum_t *key,
+ gnutls_psk_key_flags flags);
void
gnutls_psk_free_server_credentials(gnutls_psk_server_credentials_t sc);
res, const char *hint);
const char *gnutls_psk_server_get_username(gnutls_session_t session);
+int gnutls_psk_server_get_username2(gnutls_session_t session,
+ gnutls_datum_t *out);
const char *gnutls_psk_client_get_hint(gnutls_session_t session);
typedef int gnutls_psk_server_credentials_function(gnutls_session_t,
const char *username,
gnutls_datum_t * key);
+typedef int gnutls_psk_server_credentials_function2(gnutls_session_t,
+ const gnutls_datum_t *username,
+ gnutls_datum_t *key);
void
gnutls_psk_set_server_credentials_function(gnutls_psk_server_credentials_t
cred,
gnutls_psk_server_credentials_function
* func);
+void
+gnutls_psk_set_server_credentials_function2(gnutls_psk_server_credentials_t cred,
+ gnutls_psk_server_credentials_function2 *func);
typedef int gnutls_psk_client_credentials_function(gnutls_session_t,
char **username,
gnutls_datum_t * key);
+typedef int gnutls_psk_client_credentials_function2(gnutls_session_t,
+ gnutls_datum_t *username,
+ gnutls_datum_t *key);
void
gnutls_psk_set_client_credentials_function(gnutls_psk_client_credentials_t
cred,
gnutls_psk_client_credentials_function
* func);
+void
+gnutls_psk_set_client_credentials_function2(gnutls_psk_client_credentials_t cred,
+ gnutls_psk_client_credentials_function2 *func);
int gnutls_hex_encode(const gnutls_datum_t * data, char *result,
size_t * result_size);
gnutls_pbkdf2;
gnutls_session_set_keylog_function;
gnutls_prf_hash_get;
+ gnutls_psk_server_get_username2;
+ gnutls_psk_set_server_credentials_function2;
+ gnutls_psk_set_client_credentials2;
+ gnutls_psk_set_client_credentials_function2;
} GNUTLS_3_6_12;
GNUTLS_FIPS140_3_4 {
#include "gnutls_int.h"
#include "errors.h"
+#include <str.h>
#include <auth/psk.h>
#include <state.h>
const char *username,
const gnutls_datum_t * key,
gnutls_psk_key_flags flags)
+{
+ gnutls_datum_t dat;
+
+ if (username == NULL)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+ dat.data = (unsigned char *) username;
+ dat.size = strlen(username);
+
+ return gnutls_psk_set_client_credentials2(res, &dat, key, flags);
+}
+
+/**
+ * gnutls_psk_set_client_credentials2:
+ * @res: is a #gnutls_psk_client_credentials_t type.
+ * @username: is the userid
+ * @key: is the user's key
+ * @flags: indicate the format of the key, either
+ * %GNUTLS_PSK_KEY_RAW or %GNUTLS_PSK_KEY_HEX.
+ *
+ * This function is identical to gnutls_psk_set_client_credentials(),
+ * except that it allows a non-null-terminated username to be introduced.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
+ * an error code is returned.
+ */
+int
+gnutls_psk_set_client_credentials2(gnutls_psk_client_credentials_t res,
+ const gnutls_datum_t *username,
+ const gnutls_datum_t *key,
+ gnutls_psk_key_flags flags)
{
int ret;
- if (username == NULL || key == NULL || key->data == NULL) {
+ if (username == NULL || username->data == NULL || key == NULL || key->data == NULL) {
gnutls_assert();
return GNUTLS_E_INVALID_REQUEST;
}
ret =
- _gnutls_set_datum(&res->username, username, strlen(username));
+ _gnutls_set_datum(&res->username, username->data, username->size);
if (ret < 0)
return ret;
return 0;
}
+static int call_server_callback_legacy(gnutls_session_t session,
+ const gnutls_datum_t *username,
+ gnutls_datum_t *key)
+{
+ gnutls_psk_server_credentials_t cred =
+ (gnutls_psk_server_credentials_t)
+ _gnutls_get_cred(session, GNUTLS_CRD_PSK);
+ return cred->pwd_callback_legacy(session, (const char *) username->data, key);
+}
+
/**
* gnutls_psk_set_server_credentials_function:
* @cred: is a #gnutls_psk_server_credentials_t type.
cred,
gnutls_psk_server_credentials_function
* func)
+{
+ cred->pwd_callback_legacy = func;
+ cred->pwd_callback = call_server_callback_legacy;
+}
+
+/**
+ * gnutls_psk_set_server_credentials_function2:
+ * @cred: is a #gnutls_psk_server_credentials_t type.
+ * @func: is the callback function
+ *
+ * This function can be used to set a callback to retrieve the user's PSK credentials.
+ * The callback's function form is:
+ * int (*callback)(gnutls_session_t, const gnutls_datum_t* username,
+ * gnutls_datum_t* key);
+ *
+ * This callback function has the same semantics as that of gnutls_psk_set_server_credentials_function(),
+ * but it allows non-string usernames to be used.
+ *
+ * @username contains the actual username.
+ * The @key must be filled in using the gnutls_malloc().
+ *
+ * In case the callback returned a negative number then gnutls will
+ * assume that the username does not exist.
+ *
+ * The callback function will only be called once per handshake. The
+ * callback function should return 0 on success, while -1 indicates
+ * an error.
+ **/
+void
+gnutls_psk_set_server_credentials_function2(gnutls_psk_server_credentials_t cred,
+ gnutls_psk_server_credentials_function2 func)
{
cred->pwd_callback = func;
+ cred->pwd_callback_legacy = NULL;
+}
+
+static int call_client_callback_legacy(gnutls_session_t session,
+ gnutls_datum_t *username,
+ gnutls_datum_t *key)
+{
+ int ret;
+ char *user_p;
+ gnutls_psk_client_credentials_t cred =
+ (gnutls_psk_client_credentials_t)
+ _gnutls_get_cred(session, GNUTLS_CRD_PSK);
+
+ ret = cred->get_function_legacy(session, &user_p, key);
+
+ if (ret)
+ goto end;
+
+ username->data = (uint8_t *) user_p;
+ username->size = strlen(user_p);
+
+end:
+ return ret;
}
/**
cred,
gnutls_psk_client_credentials_function
* func)
+{
+ cred->get_function = call_client_callback_legacy;
+ cred->get_function_legacy = func;
+}
+
+/**
+ * gnutls_psk_set_client_credentials_function2:
+ * @cred: is a #gnutls_psk_server_credentials_t type.
+ * @func: is the callback function
+ *
+ * This function can be used to set a callback to retrieve the username and
+ * password for client PSK authentication.
+ * The callback's function form is:
+ * int (*callback)(gnutls_session_t, gnutls_datum_t* username,
+ * gnutls_datum_t* key);
+ *
+ * This callback function has the same semantics as that of gnutls_psk_set_client_credentials_function(),
+ * but it allows non-string usernames to be used.
+ *
+ * The @username and @key->data must be allocated using gnutls_malloc().
+ * The @username should be an ASCII string or UTF-8
+ * string. In case of a UTF-8 string it is recommended to be following
+ * the PRECIS framework for usernames (rfc8265).
+ *
+ * The callback function will be called once per handshake.
+ *
+ * The callback function should return 0 on success.
+ * -1 indicates an error.
+ **/
+void
+gnutls_psk_set_client_credentials_function2(gnutls_psk_client_credentials_t cred,
+ gnutls_psk_client_credentials_function2 *func)
{
cred->get_function = func;
+ cred->get_function_legacy = NULL;
}
* This should only be called in case of PSK authentication and in
* case of a server.
*
- * Returns: the username of the peer, or %NULL in case of an error.
+ * The returned pointer should be considered constant (do not free) and valid
+ * for the lifetime of the session.
+ *
+ * This function will return %NULL if the username has embedded NULL bytes.
+ * In that case, gnutls_psk_server_get_username2() should be used to retrieve the username.
+ *
+ * Returns: the username of the peer, or %NULL in case of an error,
+ * or if the username has embedded NULLs.
**/
const char *gnutls_psk_server_get_username(gnutls_session_t session)
{
if (info == NULL)
return NULL;
- if (info->username[0] != 0)
+ if (info->username[0] != 0 && !_gnutls_has_embedded_null(info->username, info->username_len))
return info->username;
return NULL;
}
+/**
+ * gnutls_psk_server_get_username2:
+ * @session: is a gnutls session
+ * @username: a datum that will be filled in by this function
+ *
+ * Return a pointer to the username of the peer in the supplied datum. Does not
+ * need to be null-terminated.
+ *
+ * This should only be called in case of PSK authentication and in
+ * case of a server.
+ *
+ * The returned pointer should be considered constant (do not free) and valid
+ * for the lifetime of the session.
+ *
+ * Returns: %GNUTLS_E_SUCCESS, or a negative value in case of an error.
+ **/
+int gnutls_psk_server_get_username2(gnutls_session_t session, gnutls_datum_t *username)
+{
+ psk_auth_info_t info;
+
+ CHECK_AUTH_TYPE(GNUTLS_CRD_PSK, GNUTLS_E_INVALID_REQUEST);
+
+ info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
+ if (info == NULL)
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+
+ if (info->username_len > 0) {
+ username->data = (unsigned char *) info->username;
+ username->size = info->username_len;
+ return 0;
+ }
+
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
+}
+
/**
* gnutls_psk_client_get_hint:
* @session: is a gnutls session
if (info == NULL)
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
- username_len = strlen(info->username) + 1; /* include the terminating null */
+ username_len = info->username_len;
hint_len = strlen(info->hint) + 1; /* include the terminating null */
size_offset = ps->length;
return GNUTLS_E_INVALID_REQUEST;
BUFFER_POP_NUM(ps, username_size);
- if (username_size > sizeof(info->username)) {
+ if (username_size > (sizeof(info->username) - 1)) {
gnutls_assert();
return GNUTLS_E_INTERNAL_ERROR;
}
if (username_size == 0)
info->username[0] = 0;
+ /* append a null terminator and set length */
+ info->username[username_size] = 0;
+ info->username_len = username_size;
+
BUFFER_POP_NUM(ps, hint_size);
if (hint_size > sizeof(info->hint)) {
gnutls_assert();
return 1;
}
+inline static bool _gnutls_has_embedded_null(const char *str, unsigned size)
+{
+ if (strlen(str) != size)
+ return true;
+ return false;
+}
+
void _gnutls_str_cpy(char *dest, size_t dest_tot_size, const char *src);
void _gnutls_str_cat(char *dest, size_t dest_tot_size, const char *src);
#include "errors.h"
#include <system.h>
-static int has_embedded_null(const char *str, unsigned size)
-{
- if (strlen(str) != size)
- return 1;
- return 0;
-}
-
/**
* gnutls_x509_crt_check_email:
* @cert: should contain an gnutls_x509_crt_t type
if (ret == GNUTLS_SAN_RFC822NAME) {
found_rfc822name = 1;
- if (has_embedded_null(rfc822name, rfc822namesize)) {
+ if (_gnutls_has_embedded_null(rfc822name, rfc822namesize)) {
_gnutls_debug_log("certificate has %s with embedded null in rfc822name\n", rfc822name);
continue;
}
goto cleanup;
}
- if (has_embedded_null(rfc822name, rfc822namesize)) {
+ if (_gnutls_has_embedded_null(rfc822name, rfc822namesize)) {
_gnutls_debug_log("certificate has EMAIL %s with embedded null in name\n", rfc822name);
ret = 0;
goto cleanup;
return 0;
}
-static int has_embedded_null(const char *str, unsigned size)
-{
- if (strlen(str) != size)
- return 1;
- return 0;
-}
-
/**
* gnutls_x509_crt_check_ip:
* @cert: should contain an gnutls_x509_crt_t type
if (ret == GNUTLS_SAN_DNSNAME) {
found_dnsname = 1;
- if (has_embedded_null(dnsname, dnsnamesize)) {
+ if (_gnutls_has_embedded_null(dnsname, dnsnamesize)) {
_gnutls_debug_log("certificate has %s with embedded null in name\n", dnsname);
continue;
}
goto cleanup;
}
- if (has_embedded_null(dnsname, dnsnamesize)) {
+ if (_gnutls_has_embedded_null(dnsname, dnsnamesize)) {
_gnutls_debug_log("certificate has CN %s with embedded null in name\n", dnsname);
ret = 0;
goto cleanup;
endif
if HAVE_FORK
-ctests += x509self x509dn anonself pskself dhepskself \
+ctests += x509self x509dn anonself pskself pskself2 dhepskself \
setcredcrash tls12-resume-x509 tls12-resume-psk tls12-resume-anon \
tls13-resume-x509 tls13-resume-psk tls13-early-data tls13-early-data-neg \
resume-with-record-size-limit
#include "utils.h"
+static char hexchar(unsigned int val)
+{
+ if (val < 10)
+ return '0' + val;
+ if (val < 16)
+ return 'a' + val - 10;
+ abort();
+}
+
+static bool hex_encode(const void *buf, size_t bufsize, char *dest, size_t destsize)
+{
+ size_t used = 0;
+
+ if (destsize < 1)
+ return false;
+
+ while (used < bufsize) {
+ unsigned int c = ((const unsigned char *)buf)[used];
+ if (destsize < 3)
+ return false;
+ *(dest++) = hexchar(c >> 4);
+ *(dest++) = hexchar(c & 0xF);
+ used++;
+ destsize -= 2;
+ }
+ *dest = '\0';
+
+ return used + 1;
+}
+
/* A very basic TLS client, with PSK authentication.
*/
#define MAX_BUF 1024
#define MSG "Hello TLS"
-static void client(int sd, const char *prio, const char *user, const gnutls_datum_t *key,
- unsigned expect_hint, int expect_fail, int exp_kx)
+static void client(int sd, const char *prio, const gnutls_datum_t *user, const gnutls_datum_t *key,
+ unsigned expect_hint, int expect_fail, int exp_kx, unsigned binary_user)
{
int ret, ii, kx;
gnutls_session_t session;
side = "client";
gnutls_psk_allocate_client_credentials(&pskcred);
- gnutls_psk_set_client_credentials(pskcred, user, key,
- GNUTLS_PSK_KEY_HEX);
+
+ if (binary_user) {
+ gnutls_psk_set_client_credentials2(pskcred, user, key, GNUTLS_PSK_KEY_HEX);
+ } else {
+ gnutls_psk_set_client_credentials(pskcred, (const char *) user->data, key,
+ GNUTLS_PSK_KEY_HEX);
+ }
assert(gnutls_init(&session, GNUTLS_CLIENT|GNUTLS_KEY_SHARE_TOP)>=0);
#define MAX_BUF 1024
-static void server(int sd, const char *prio, const char *user, bool no_cred,
- int expect_fail, int exp_kx)
+static void server(int sd, const char *prio, const gnutls_datum_t *user, bool no_cred,
+ int expect_fail, int exp_kx, unsigned binary_user)
{
gnutls_psk_server_credentials_t server_pskcred;
int ret, kx;
gnutls_session_t session;
const char *pskid;
+ gnutls_datum_t pskid_binary;
char buffer[MAX_BUF + 1];
char *psk_file = getenv("PSK_FILE");
char *desc;
gnutls_alert_send_appropriate(session, ret);
/* We have to make sure that we do not close connection till
- * test client reads our fatal alert, otherwise it migh exit
+ * test client reads our fatal alert, otherwise it might exit
* with GNUTLS_E_PUSH_ERROR instead */
gnutls_session_force_valid(session);
while ((gnutls_record_recv_seq(session, buf, sizeof(buf), seq)) >= 0)
fail("server: expected failure but connection succeeded!\n");
if (!no_cred) {
- pskid = gnutls_psk_server_get_username(session);
- if (pskid == NULL || strcmp(pskid, user) != 0) {
- fail("server: username (%s), does not match expected (%s)\n",
- pskid, user);
+ if (binary_user) {
+ char pskid_bin[1024], userdata_bin[1024];
+
+ if (gnutls_psk_server_get_username2(session, &pskid_binary))
+ fail("server: Could not get binary pskid\n");
+
+ if (memcmp(pskid_binary.data, user->data, user->size) != 0) {
+ hex_encode(user->data, user->size, userdata_bin, sizeof(userdata_bin));
+ hex_encode(pskid_binary.data, pskid_binary.size, pskid_bin, sizeof(pskid_bin));
+ fail("server: binary username (%s) does not match expected (%s)\n",
+ pskid_bin, userdata_bin);
+ }
+ } else {
+ pskid = gnutls_psk_server_get_username(session);
+ if (pskid == NULL || strcmp(pskid, (const char *) user->data) != 0) {
+ fail("server: username (%s), does not match expected (%s)\n",
+ pskid, (const char *) user->data);
+ }
}
}
success("server: finished\n");
}
+static void print_user(const char *caption, const char *prio, const gnutls_datum_t *user, unsigned binary_user)
+{
+ char hexuser[100];
+
+ if (binary_user) {
+ hex_encode(user->data, user->size, hexuser, sizeof(hexuser));
+ success("%s %s (user:%s)\n", caption, prio, hexuser);
+ } else
+ success("%s %s (user:%s)\n", caption, prio, (const char *) user->data);
+}
+
static
-void run_test3(const char *prio, const char *sprio, const char *user, const gnutls_datum_t *key, bool no_cred,
- unsigned expect_hint, int exp_kx, int expect_fail_cli, int expect_fail_serv)
+void run_test3(const char *prio, const char *sprio, const gnutls_datum_t *user, const gnutls_datum_t *key, bool no_cred,
+ unsigned expect_hint, int exp_kx, int expect_fail_cli, int expect_fail_serv, unsigned binary_user)
{
pid_t child;
int err;
signal(SIGPIPE, SIG_IGN);
- if (expect_fail_serv || expect_fail_cli) {
- success("ntest %s (user:%s)\n", prio, user);
- } else {
- success("test %s (user:%s)\n", prio, user);
- }
+ if (expect_fail_serv || expect_fail_cli)
+ print_user("ntest", prio, user, binary_user);
+ else
+ print_user("test", prio, user, binary_user);
err = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
if (err == -1) {
close(sockets[1]);
int status;
/* parent */
- server(sockets[0], sprio?sprio:prio, user, no_cred, expect_fail_serv, exp_kx);
+ server(sockets[0], sprio?sprio:prio, user, no_cred, expect_fail_serv, exp_kx, binary_user);
wait(&status);
check_wait_status(status);
} else {
close(sockets[0]);
- client(sockets[1], prio, user, key, expect_hint, expect_fail_cli, exp_kx);
+ client(sockets[1], prio, user, key, expect_hint, expect_fail_cli, exp_kx, binary_user);
exit(0);
}
}
static
-void run_test2(const char *prio, const char *sprio, const char *user, const gnutls_datum_t *key,
- unsigned expect_hint, int exp_kx, int expect_fail_cli, int expect_fail_serv)
+void run_test2(const char *prio, const char *sprio, const gnutls_datum_t *user, const gnutls_datum_t *key,
+ unsigned expect_hint, int exp_kx, int expect_fail_cli, int expect_fail_serv, unsigned binary_user)
{
- run_test3(prio, sprio, user, key, 0, expect_hint, exp_kx, expect_fail_cli, expect_fail_serv);
+ run_test3(prio, sprio, user, key, 0, expect_hint, exp_kx, expect_fail_cli, expect_fail_serv, binary_user);
}
static
-void run_test_ok(const char *prio, const char *user, const gnutls_datum_t *key, unsigned expect_hint, int expect_fail)
+void run_test_ok(const char *prio, const gnutls_datum_t *user, const gnutls_datum_t *key, unsigned expect_hint, int expect_fail, unsigned binary_user)
{
- run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_PSK, expect_fail, expect_fail);
+ run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_PSK, expect_fail, expect_fail, binary_user);
}
static
-void run_ectest_ok(const char *prio, const char *user, const gnutls_datum_t *key, unsigned expect_hint, int expect_fail)
+void run_ectest_ok(const char *prio, const gnutls_datum_t *user, const gnutls_datum_t *key, unsigned expect_hint, int expect_fail, unsigned binary_user)
{
- run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_ECDHE_PSK, expect_fail, expect_fail);
+ run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_ECDHE_PSK, expect_fail, expect_fail, binary_user);
}
static
-void run_dhtest_ok(const char *prio, const char *user, const gnutls_datum_t *key, unsigned expect_hint, int expect_fail)
+void run_dhtest_ok(const char *prio, const gnutls_datum_t *user, const gnutls_datum_t *key, unsigned expect_hint, int expect_fail, unsigned binary_user)
{
- run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_DHE_PSK, expect_fail, expect_fail);
+ run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_DHE_PSK, expect_fail, expect_fail, binary_user);
}
void doit(void)
{
+ char hexuser[] = { 0xde, 0xad, 0xbe, 0xef },
+ nulluser1[] = { 0 },
+ nulluser2[] = { 0, 0, 0xaa, 0 };
+ const gnutls_datum_t user_jas = { (void *) "jas", strlen("jas") };
+ const gnutls_datum_t user_unknown = { (void *) "unknown", strlen("unknown") };
+ const gnutls_datum_t user_nonhex = { (void *) "non-hex", strlen("non-hex") };
+ const gnutls_datum_t user_hex = { (void *) hexuser, sizeof(hexuser) };
+ const gnutls_datum_t user_null_1 = { (void *) nulluser1, sizeof(nulluser1) };
+ const gnutls_datum_t user_null_2 = { (void *) nulluser2, sizeof(nulluser2) };
const gnutls_datum_t key = { (void *) "9e32cf7786321a828ef7668f09fb35db", 32 };
const gnutls_datum_t wrong_key = { (void *) "9e31cf7786321a828ef7668f09fb35db", 32 };
- run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", "jas", &key, 1, 0);
- run_dhtest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK", "jas", &key, 1, 0);
- run_ectest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK", "jas", &key, 1, 0);
- run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", NULL, "unknown", &key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_DECRYPTION_FAILED);
- run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", NULL, "jas", &wrong_key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_DECRYPTION_FAILED);
- run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", NULL, "non-hex", &key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_KEYFILE_ERROR);
-
- run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", "jas", &key, 1, 0);
- run_test_ok("NORMAL:-KX-ALL:+PSK", "jas", &key, 0, 0);
- run_test2("NORMAL:+PSK", NULL, "unknown", &key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
- run_test2("NORMAL:+PSK", NULL, "jas", &wrong_key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
- run_test2("NORMAL:-KX-ALL:+PSK", NULL, "non-hex", &key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_KEYFILE_ERROR);
-
- run_dhtest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-EC-ALL", "jas", &key, 0, 0);
- run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK", "jas", &key, 0, 0);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", &user_jas, &key, 1, 0, 0);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", &user_hex, &key, 1, 0, 1);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", &user_null_1, &key, 1, 0, 1);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", &user_null_2, &key, 1, 0, 1);
+ run_dhtest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK", &user_jas, &key, 1, 0, 0);
+ run_dhtest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK", &user_hex, &key, 1, 0, 1);
+ run_dhtest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK", &user_null_1, &key, 1, 0, 1);
+ run_dhtest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK", &user_null_2, &key, 1, 0, 1);
+ run_ectest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK", &user_jas, &key, 1, 0, 0);
+ run_ectest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK", &user_hex, &key, 1, 0, 1);
+ run_ectest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK", &user_null_1, &key, 1, 0, 1);
+ run_ectest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK", &user_null_2, &key, 1, 0, 1);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", NULL, &user_unknown, &key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_DECRYPTION_FAILED, 0);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", NULL, &user_jas, &wrong_key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_DECRYPTION_FAILED, 0);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", NULL, &user_nonhex, &key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_KEYFILE_ERROR, 0);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", NULL, &user_hex, &wrong_key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_DECRYPTION_FAILED, 1);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", NULL, &user_null_1, &wrong_key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_DECRYPTION_FAILED, 1);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", NULL, &user_null_2, &wrong_key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_DECRYPTION_FAILED, 1);
+
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", &user_jas, &key, 1, 0, 0);
+ run_test_ok("NORMAL:-KX-ALL:+PSK", &user_jas, &key, 0, 0, 0);
+ run_test_ok("NORMAL:-KX-ALL:+PSK", &user_hex, &key, 0, 0, 1);
+ run_test_ok("NORMAL:-KX-ALL:+PSK", &user_null_1, &key, 0, 0, 1);
+ run_test_ok("NORMAL:-KX-ALL:+PSK", &user_null_2, &key, 0, 0, 1);
+ run_test2("NORMAL:+PSK", NULL, &user_unknown, &key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER, 0);
+ run_test2("NORMAL:+PSK", NULL, &user_jas, &wrong_key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER, 0);
+ run_test2("NORMAL:+PSK", NULL, &user_hex, &wrong_key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER, 1);
+ run_test2("NORMAL:+PSK", NULL, &user_null_1, &wrong_key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER, 1);
+ run_test2("NORMAL:+PSK", NULL, &user_null_2, &wrong_key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER, 1);
+ run_test2("NORMAL:-KX-ALL:+PSK", NULL, &user_nonhex, &key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_KEYFILE_ERROR, 0);
+
+ run_dhtest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-EC-ALL", &user_jas, &key, 0, 0, 0);
+ run_dhtest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-EC-ALL", &user_hex, &key, 0, 0, 1);
+ run_dhtest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-EC-ALL", &user_null_1, &key, 0, 0, 1);
+ run_dhtest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-EC-ALL", &user_null_2, &key, 0, 0, 1);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK", &user_jas, &key, 0, 0, 0);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK", &user_hex, &key, 0, 0, 1);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK", &user_null_1, &key, 0, 0, 1);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK", &user_null_2, &key, 0, 0, 1);
/* test priorities of DHE-PSK and PSK */
- run_ectest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+DHE-PSK:+PSK:-GROUP-DH-ALL", "jas", &key, 0, 0);
- run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+PSK:+DHE-PSK:-GROUP-DH-ALL", "jas", &key, 0, 0);
+ run_ectest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+DHE-PSK:+PSK:-GROUP-DH-ALL", &user_jas, &key, 0, 0, 0);
+ run_ectest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+DHE-PSK:+PSK:-GROUP-DH-ALL", &user_hex, &key, 0, 0, 1);
+ run_ectest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+DHE-PSK:+PSK:-GROUP-DH-ALL", &user_null_1, &key, 0, 0, 1);
+ run_ectest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+DHE-PSK:+PSK:-GROUP-DH-ALL", &user_null_2, &key, 0, 0, 1);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+PSK:+DHE-PSK:-GROUP-DH-ALL", &user_jas, &key, 0, 0, 0);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+PSK:+DHE-PSK:-GROUP-DH-ALL", &user_hex, &key, 0, 0, 1);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+PSK:+DHE-PSK:-GROUP-DH-ALL", &user_null_1, &key, 0, 0, 1);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+PSK:+DHE-PSK:-GROUP-DH-ALL", &user_null_2, &key, 0, 0, 1);
run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+DHE-PSK:+PSK:-GROUP-DH-ALL",
"NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+PSK:+DHE-PSK:%SERVER_PRECEDENCE:-GROUP-DH-ALL",
- "jas", &key, 0, GNUTLS_KX_PSK, 0, 0);
+ &user_jas, &key, 0, GNUTLS_KX_PSK, 0, 0, 0);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+DHE-PSK:+PSK:-GROUP-DH-ALL",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+PSK:+DHE-PSK:%SERVER_PRECEDENCE:-GROUP-DH-ALL",
+ &user_hex, &key, 0, GNUTLS_KX_PSK, 0, 0, 1);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+DHE-PSK:+PSK:-GROUP-DH-ALL",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+PSK:+DHE-PSK:%SERVER_PRECEDENCE:-GROUP-DH-ALL",
+ &user_null_1, &key, 0, GNUTLS_KX_PSK, 0, 0, 1);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+DHE-PSK:+PSK:-GROUP-DH-ALL",
+ "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+PSK:+DHE-PSK:%SERVER_PRECEDENCE:-GROUP-DH-ALL",
+ &user_null_2, &key, 0, GNUTLS_KX_PSK, 0, 0, 1);
/* try with PRF that doesn't match binder (SHA256) */
- run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-256-GCM:+PSK:+DHE-PSK", NULL, "jas", &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_CIPHER_SUITES);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-256-GCM:+PSK:+DHE-PSK", NULL, &user_jas, &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_CIPHER_SUITES, 0);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-256-GCM:+PSK:+DHE-PSK", NULL, &user_hex, &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_CIPHER_SUITES, 1);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-256-GCM:+PSK:+DHE-PSK", NULL, &user_null_1, &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_CIPHER_SUITES, 1);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-256-GCM:+PSK:+DHE-PSK", NULL, &user_null_2, &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_CIPHER_SUITES, 1);
/* try with no groups and PSK */
- run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:-GROUP-ALL", "jas", &key, 0, 0);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:-GROUP-ALL", &user_jas, &key, 0, 0, 0);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:-GROUP-ALL", &user_hex, &key, 0, 0, 1);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:-GROUP-ALL", &user_null_1, &key, 0, 0, 1);
+ run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:-GROUP-ALL", &user_null_2, &key, 0, 0, 1);
/* try without any groups but DHE-PSK */
- run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:+PSK", "jas", &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_COMMON_KEY_SHARE);
- run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:+PSK:-GROUP-ALL", "jas", &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_COMMON_KEY_SHARE);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:+PSK", &user_jas, &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_COMMON_KEY_SHARE, 0);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:+PSK:-GROUP-ALL", &user_jas, &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_COMMON_KEY_SHARE, 0);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:+PSK", &user_hex, &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_COMMON_KEY_SHARE, 1);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:+PSK:-GROUP-ALL", &user_hex, &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_COMMON_KEY_SHARE, 1);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:+PSK", &user_null_1, &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_COMMON_KEY_SHARE, 1);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:+PSK:-GROUP-ALL", &user_null_1, &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_COMMON_KEY_SHARE, 1);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:+PSK", &user_null_2, &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_COMMON_KEY_SHARE, 1);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:+PSK:-GROUP-ALL", &user_null_2, &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_COMMON_KEY_SHARE, 1);
/* if user invalid we continue without PSK */
- run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, "non-hex", &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_KEYFILE_ERROR);
- run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, "unknown", &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
- run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, "jas", &wrong_key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, &user_nonhex, &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_KEYFILE_ERROR, 0);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, &user_unknown, &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER, 0);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, &user_jas, &wrong_key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER, 0);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, &user_hex, &wrong_key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER, 1);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, &user_null_1, &wrong_key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER, 1);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, &user_null_2, &wrong_key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER, 1);
/* try with HelloRetryRequest and PSK */
- run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL:+GROUP-FFDHE2048:+GROUP-FFDHE4096", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL:+GROUP-FFDHE4096", "jas", &key, 0, GNUTLS_KX_DHE_PSK, 0, 0);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL:+GROUP-FFDHE2048:+GROUP-FFDHE4096", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL:+GROUP-FFDHE4096", &user_jas, &key, 0, GNUTLS_KX_DHE_PSK, 0, 0, 0);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL:+GROUP-FFDHE2048:+GROUP-FFDHE4096", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL:+GROUP-FFDHE4096", &user_hex, &key, 0, GNUTLS_KX_DHE_PSK, 0, 0, 1);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL:+GROUP-FFDHE2048:+GROUP-FFDHE4096", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL:+GROUP-FFDHE4096", &user_null_1, &key, 0, GNUTLS_KX_DHE_PSK, 0, 0, 1);
+ run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL:+GROUP-FFDHE2048:+GROUP-FFDHE4096", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL:+GROUP-FFDHE4096", &user_null_2, &key, 0, GNUTLS_KX_DHE_PSK, 0, 0, 1);
/* try without server credentials */
- run_test3("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, "jas", &key, 1, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_INSUFFICIENT_CREDENTIALS);
+ run_test3("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, &user_jas, &key, 1, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_INSUFFICIENT_CREDENTIALS, 0);
+ run_test3("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, &user_hex, &key, 1, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_INSUFFICIENT_CREDENTIALS, 1);
+ run_test3("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, &user_null_1, &key, 1, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_INSUFFICIENT_CREDENTIALS, 1);
+ run_test3("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, &user_null_2, &key, 1, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_INSUFFICIENT_CREDENTIALS, 1);
}
#endif /* _WIN32 */
jas:9e32cf7786321a828ef7668f09fb35db
non-hex:9e32cf7786321a828ef7668f09fb35dbxx
+#deadbeef:9e32cf7786321a828ef7668f09fb35db
+#00:9e32cf7786321a828ef7668f09fb35db
+#0000aa00:9e32cf7786321a828ef7668f09fb35db
--- /dev/null
+/*
+ * Copyright (C) 2004-2012 Free Software Foundation, Inc.
+ * Copyright (C) 2013 Adam Sampson <ats@offog.org>
+ * Copyright (C) 2019 Free Software Foundation, Inc.
+ *
+ * Author: Simon Josefsson, Ander Juaristi
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GnuTLS; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/* Parts copied from pskself.c. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(_WIN32)
+
+/* socketpair isn't supported on Win32. */
+int main(int argc, char **argv)
+{
+ exit(77);
+}
+
+#else
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#if !defined(_WIN32)
+#include <sys/wait.h>
+#endif
+#include <unistd.h>
+#include <gnutls/gnutls.h>
+
+#include "utils.h"
+#include "extras/hex.h"
+
+/* A very basic TLS client, with PSK authentication.
+ */
+
+const char *side = "";
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "%s|<%d>| %s", side, level, str);
+}
+
+#define MAX_BUF 1024
+#define MSG "Hello TLS"
+
+static void client(int sd, const char *prio, unsigned exp_hint)
+{
+ int ret, ii;
+ gnutls_session_t session;
+ char buffer[MAX_BUF + 1];
+ gnutls_psk_client_credentials_t pskcred;
+ /* Need to enable anonymous KX specifically. */
+ const gnutls_datum_t key = { (void *) "DEADBEEF", 8 };
+ gnutls_datum_t user;
+ const char *hint;
+
+ global_init();
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ side = "client";
+
+ user.data = gnutls_malloc(4);
+ user.data[0] = 0xCA;
+ user.data[1] = 0xFE;
+ user.data[2] = 0xCA;
+ user.data[3] = 0xFE;
+ user.size = 4;
+
+ gnutls_psk_allocate_client_credentials(&pskcred);
+ ret = gnutls_psk_set_client_credentials2(pskcred, &user, &key,
+ GNUTLS_PSK_KEY_HEX);
+ if (ret < 0) {
+ fail("client: Could not set PSK\n");
+ gnutls_perror(ret);
+ goto end;
+ }
+
+ /* Initialize TLS session
+ */
+ gnutls_init(&session, GNUTLS_CLIENT);
+
+ /* Use default priorities */
+ gnutls_priority_set_direct(session, prio, NULL);
+
+ /* put the anonymous credentials to the current session
+ */
+ gnutls_credentials_set(session, GNUTLS_CRD_PSK, pskcred);
+
+ gnutls_transport_set_int(session, sd);
+
+ /* Perform the TLS handshake
+ */
+ ret = gnutls_handshake(session);
+
+ if (ret < 0) {
+ fail("client: Handshake failed\n");
+ gnutls_perror(ret);
+ goto end;
+ } else {
+ if (debug)
+ success("client: Handshake was completed\n");
+ }
+
+ /* check the hint */
+ if (exp_hint) {
+ hint = gnutls_psk_client_get_hint(session);
+ if (hint == NULL || strcmp(hint, "hint") != 0) {
+ fail("client: hint is not the expected: %s\n", gnutls_psk_client_get_hint(session));
+ goto end;
+ }
+ }
+
+ gnutls_record_send(session, MSG, strlen(MSG));
+
+ ret = gnutls_record_recv(session, buffer, MAX_BUF);
+ if (ret == 0) {
+ if (debug)
+ success
+ ("client: Peer has closed the TLS connection\n");
+ goto end;
+ } else if (ret < 0) {
+ fail("client: Error: %s\n", gnutls_strerror(ret));
+ goto end;
+ }
+
+ if (debug) {
+ printf("- Received %d bytes: ", ret);
+ for (ii = 0; ii < ret; ii++) {
+ fputc(buffer[ii], stdout);
+ }
+ fputs("\n", stdout);
+ }
+
+ gnutls_bye(session, GNUTLS_SHUT_RDWR);
+
+ end:
+
+ close(sd);
+
+ gnutls_deinit(session);
+
+ gnutls_free(user.data);
+ gnutls_psk_free_client_credentials(pskcred);
+
+ gnutls_global_deinit();
+}
+
+/* This is a sample TLS 1.0 echo server, for PSK authentication.
+ */
+
+#define MAX_BUF 1024
+
+/* These are global */
+
+static int
+pskfunc(gnutls_session_t session, const gnutls_datum_t *username,
+ gnutls_datum_t * key)
+{
+ if (debug)
+ printf("psk: Got username with length %d\n", username->size);
+
+ key->data = gnutls_malloc(4);
+ key->data[0] = 0xDE;
+ key->data[1] = 0xAD;
+ key->data[2] = 0xBE;
+ key->data[3] = 0xEF;
+ key->size = 4;
+
+ return 0;
+}
+
+
+static void server(int sd, const char *prio)
+{
+ gnutls_psk_server_credentials_t server_pskcred;
+ int ret;
+ gnutls_session_t session;
+ gnutls_datum_t psk_username;
+ char buffer[MAX_BUF + 1], expected_psk_username[] = { 0xDE, 0xAD, 0xBE, 0xEF };
+
+ /* this must be called once in the program
+ */
+ global_init();
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(4711);
+
+ side = "server";
+
+
+ gnutls_psk_allocate_server_credentials(&server_pskcred);
+ gnutls_psk_set_server_credentials_hint(server_pskcred, "hint");
+ gnutls_psk_set_server_credentials_function2(server_pskcred, pskfunc);
+
+ gnutls_init(&session, GNUTLS_SERVER);
+
+ /* avoid calling all the priority functions, since the defaults
+ * are adequate.
+ */
+ gnutls_priority_set_direct(session, prio, NULL);
+
+ gnutls_credentials_set(session, GNUTLS_CRD_PSK, server_pskcred);
+
+ gnutls_transport_set_int(session, sd);
+ ret = gnutls_handshake(session);
+ if (ret < 0) {
+ close(sd);
+ gnutls_deinit(session);
+ fail("server: Handshake has failed (%s)\n\n",
+ gnutls_strerror(ret));
+ return;
+ }
+
+ if (debug) {
+ success("server: Handshake was completed\n");
+
+ if (gnutls_psk_server_get_username(session))
+ fail("server: gnutls_psk_server_get_username() should have returned NULL\n");
+ if (gnutls_psk_server_get_username2(session, &psk_username) < 0)
+ fail("server: Could not get PSK username\n");
+
+ if (psk_username.size != 4 || memcmp(psk_username.data, expected_psk_username, 4))
+ fail("server: Unexpected PSK username\n");
+
+ success("server: PSK username length: %d\n", psk_username.size);
+ }
+
+ /* see the Getting peer's information example */
+ /* print_info(session); */
+
+ for (;;) {
+ memset(buffer, 0, MAX_BUF + 1);
+ gnutls_record_set_timeout(session, 10000);
+ ret = gnutls_record_recv(session, buffer, MAX_BUF);
+
+ if (ret == 0) {
+ if (debug)
+ success("server: Peer has closed the GnuTLS connection\n");
+ break;
+ } else if (ret < 0) {
+ fail("server: Received corrupted data(%d). Closing...\n", ret);
+ break;
+ } else if (ret > 0) {
+ /* echo data back to the client
+ */
+ gnutls_record_send(session, buffer,
+ strlen(buffer));
+ }
+ }
+ /* do not wait for the peer to close the connection.
+ */
+ gnutls_bye(session, GNUTLS_SHUT_WR);
+
+ close(sd);
+ gnutls_deinit(session);
+
+ gnutls_psk_free_server_credentials(server_pskcred);
+
+ gnutls_global_deinit();
+
+ if (debug)
+ success("server: finished\n");
+}
+
+static
+void run_test(const char *prio, unsigned exp_hint)
+{
+ pid_t child;
+ int err;
+ int sockets[2];
+
+ success("trying with %s\n", prio);
+
+ err = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
+ if (err == -1) {
+ perror("socketpair");
+ fail("socketpair failed\n");
+ return;
+ }
+
+ child = fork();
+ if (child < 0) {
+ perror("fork");
+ fail("fork");
+ return;
+ }
+
+ if (child) {
+ int status;
+ /* parent */
+ close(sockets[1]);
+ server(sockets[0], prio);
+ wait(&status);
+ check_wait_status(status);
+ } else {
+ close(sockets[0]);
+ client(sockets[1], prio, exp_hint);
+ exit(0);
+ }
+}
+
+void doit(void)
+{
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", 1);
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK", 1);
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK", 1);
+
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:+PSK", 0);
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-GROUP-ALL:+GROUP-FFDHE2048:+DHE-PSK", 0);
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-GROUP-ALL:+GROUP-SECP256R1:+ECDHE-PSK", 0);
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK", 0);
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-FFDHE2048:+DHE-PSK", 0);
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-SECP256R1:+ECDHE-PSK", 0);
+ /* the following should work once we support PSK without DH */
+ run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+PSK", 0);
+
+ run_test("NORMAL:-KX-ALL:+PSK", 0);
+ run_test("NORMAL:-KX-ALL:+ECDHE-PSK", 0);
+ run_test("NORMAL:-KX-ALL:+DHE-PSK", 0);
+}
+
+#endif /* _WIN32 */