diff options
Diffstat (limited to 'lib/auth_psk.c')
-rw-r--r-- | lib/auth_psk.c | 153 |
1 files changed, 149 insertions, 4 deletions
diff --git a/lib/auth_psk.c b/lib/auth_psk.c index e611b7a150..53cd1b45b0 100644 --- a/lib/auth_psk.c +++ b/lib/auth_psk.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005, 2007 Free Software Foundation + * Copyright (C) 2005, 2007, 2008 Free Software Foundation * * Author: Nikos Mavrogiannopoulos * @@ -36,22 +36,26 @@ #include <gnutls_str.h> #include <gnutls_datum.h> +int _gnutls_gen_psk_server_kx (gnutls_session_t session, opaque ** data); int _gnutls_gen_psk_client_kx (gnutls_session_t, opaque **); int _gnutls_proc_psk_client_kx (gnutls_session_t, opaque *, size_t); +int _gnutls_proc_psk_server_kx (gnutls_session_t session, opaque * data, + size_t _data_size); + const mod_auth_st psk_auth_struct = { "PSK", NULL, NULL, - NULL, + _gnutls_gen_psk_server_kx, _gnutls_gen_psk_client_kx, NULL, NULL, NULL, NULL, /* certificate */ - NULL, + _gnutls_proc_psk_server_kx, _gnutls_proc_psk_client_kx, NULL, NULL @@ -164,7 +168,37 @@ _gnutls_gen_psk_client_kx (gnutls_session_t session, opaque ** data) return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } - if (cred->username.data == NULL || cred->key.data == NULL) + if (cred->username.data == NULL && cred->key.data == NULL && + cred->get_function != NULL) + { + char *username; + gnutls_datum_t key; + + ret = cred->get_function (session, &username, &key); + if (ret) + { + gnutls_assert (); + return ret; + } + + ret = _gnutls_set_datum (&cred->username, username, strlen (username)); + gnutls_free (username); + if (ret < 0) + { + gnutls_assert (); + _gnutls_free_datum (&key); + return ret; + } + + ret = _gnutls_set_datum (&cred->key, key.data, key.size); + _gnutls_free_datum (&key); + if (ret < 0) + { + gnutls_assert (); + return GNUTLS_E_MEMORY_ERROR; + } + } + else if (cred->username.data == NULL || cred->key.data == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; @@ -254,4 +288,115 @@ error: } +/* 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; +} + + +/* just read the hint from the server key exchange. + */ +int +_gnutls_proc_psk_server_kx (gnutls_session_t session, opaque * data, + size_t _data_size) +{ + ssize_t data_size = _data_size; + int ret; + gnutls_datum_t hint; + 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_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); + + if (hint.size > MAX_SRP_USERNAME) + { + gnutls_assert (); + return GNUTLS_E_ILLEGAL_SRP_USERNAME; + } + + memcpy (info->hint, hint.data, hint.size); + info->hint[hint.size] = 0; + + ret = _gnutls_set_psk_session_key (session, NULL); + if (ret < 0) + { + gnutls_assert (); + goto error; + } + + ret = 0; + + error: + return ret; +} + #endif /* ENABLE_SRP */ |