summaryrefslogtreecommitdiff
path: root/lib/auth_psk.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/auth_psk.c')
-rw-r--r--lib/auth_psk.c153
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 */