summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2005-11-07 22:24:48 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2005-11-07 22:24:48 +0000
commitad4ed44c65e753e6d3a00104c049dd81826ccbf3 (patch)
treec7511d77a37287b567c2f31f3e5dfa9af956d635 /lib
parent31168918162ee35315f025a9d8aeec67a81c7a7c (diff)
downloadgnutls-ad4ed44c65e753e6d3a00104c049dd81826ccbf3.tar.gz
This is the initial commit in the 1.3 branch. Ported from the PSK branch:
* PSK ciphersuites have been added. * The session resumption data are now system independent.
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am13
-rw-r--r--lib/auth_psk.c168
-rw-r--r--lib/auth_psk.h56
-rw-r--r--lib/auth_psk_passwd.c363
-rw-r--r--lib/auth_psk_passwd.h37
-rw-r--r--lib/auth_srp.h2
-rw-r--r--lib/auth_srp_sb64.c4
-rw-r--r--lib/ext_srp.c4
-rw-r--r--lib/gnutls_algorithms.c28
-rw-r--r--lib/gnutls_compress_int.c9
-rw-r--r--lib/gnutls_db.c19
-rw-r--r--lib/gnutls_helper.c38
-rw-r--r--lib/gnutls_helper.h1
-rw-r--r--lib/gnutls_int.h3
-rw-r--r--lib/gnutls_psk.c700
-rw-r--r--lib/gnutls_session.c51
-rw-r--r--lib/gnutls_session_pack.c1137
-rw-r--r--lib/gnutls_session_pack.h1
-rw-r--r--lib/gnutls_srp.c18
-rw-r--r--lib/gnutls_str.c33
-rw-r--r--lib/gnutls_str.h2
-rw-r--r--lib/libgnutls.vers2
22 files changed, 2362 insertions, 327 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 65798b63ba..3f08ceba41 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -54,6 +54,8 @@ lib_LTLIBRARIES = libgnutls.la
SRP_COBJECTS = ext_srp.c gnutls_srp.c auth_srp.c auth_srp_passwd.c \
auth_srp_sb64.c auth_srp_rsa.c
+PSK_COBJECTS = auth_psk.c auth_psk_passwd.c gnutls_psk.c
+
COBJECTS = gnutls_record.c gnutls_compress.c debug.c gnutls_cipher.c \
gnutls_buffers.c gnutls_handshake.c gnutls_num.c \
gnutls_errors.c gnutls_algorithms.c gnutls_dh.c gnutls_kx.c \
@@ -67,7 +69,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c gnutls_cipher.c \
gnutls_ui.c gnutls_sig.c auth_dhe.c gnutls_dh_primes.c \
ext_max_record.c gnutls_alert.c gnutls_str.c gnutls_state.c \
gnutls_x509.c ext_cert_type.c gnutls_rsa_export.c \
- auth_rsa_export.c ext_server_name.c auth_dh_common.c
+ auth_rsa_export.c ext_server_name.c auth_dh_common.c gnutls_helper.c
HFILES = debug.h gnutls_compress.h defines.h gnutls_cipher.h \
gnutls_buffers.h gnutls_errors.h gnutls_int.h \
@@ -82,12 +84,13 @@ HFILES = debug.h gnutls_compress.h defines.h gnutls_cipher.h \
gnutls_mem.h io_debug.h ext_max_record.h gnutls_session_pack.h \
gnutls_str.h gnutls_state.h gnutls_x509.h ext_cert_type.h \
gnutls_rsa_export.h ext_server_name.h auth_dh_common.h \
- ext_srp.h gnutls_srp.h auth_srp.h auth_srp_passwd.h
+ ext_srp.h gnutls_srp.h auth_srp.h auth_srp_passwd.h \
+ gnutls_helper.h auth_psk_passwd.h
# Separate so we can create the documentation
libgnutls_la_SOURCES = $(HFILES) $(COBJECTS) $(SRP_COBJECTS) \
- gnutls.asn pkix.asn libgnutls.vers
+ $(PSK_COBJECTS) gnutls.asn pkix.asn libgnutls.vers
libgnutls_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
@@ -110,9 +113,9 @@ pkix_asn1_tab.c: pkix.asn
gnutls_asn1_tab.c: gnutls.asn
-asn1Parser gnutls.asn gnutls_asn1_tab.c
-gnutls-api.texi: $(COBJECTS) $(SRP_COBJECTS)
+gnutls-api.texi: $(COBJECTS) $(SRP_COBJECTS) $(PSK_COBJECTS)
@echo "" > gnutls-api.texi
- @for i in $(COBJECTS) $(SRP_COBJECTS); do \
+ @for i in $(COBJECTS) $(SRP_COBJECTS) $(PSK_COBJECTS); do \
echo -n "Creating documentation for file $$i... " && \
../doc/scripts/gdoc -texinfo $$i >> gnutls-api.texi && \
echo "ok"; \
diff --git a/lib/auth_psk.c b/lib/auth_psk.c
new file mode 100644
index 0000000000..261d282db2
--- /dev/null
+++ b/lib/auth_psk.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavroyanopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+
+#ifdef ENABLE_PSK
+
+#include "gnutls_errors.h"
+#include "gnutls_auth.h"
+#include "gnutls_auth_int.h"
+#include "psk.h"
+#include "debug.h"
+#include "gnutls_num.h"
+#include "auth_psk.h"
+#include <gnutls_str.h>
+#include <gnutls_datum.h>
+
+int _gnutls_gen_psk_client_kx(gnutls_session_t, opaque **);
+
+int _gnutls_proc_psk_client_kx(gnutls_session_t, opaque *, size_t);
+
+const mod_auth_st srp_auth_struct = {
+ "PSK",
+ NULL,
+ NULL,
+ NULL,
+ _gnutls_gen_psk_client_kx,
+ NULL,
+ NULL,
+
+ NULL,
+ NULL, /* certificate */
+ NULL,
+ _gnutls_proc_psk_client_kx,
+ NULL,
+ NULL
+};
+
+
+
+/* Generates the PSK client key exchange
+ *
+ *
+ * struct {
+ * select (KeyExchangeAlgorithm) {
+ * opaque psk_identity<0..2^16-1>;
+ * } exchange_keys;
+ * } ClientKeyExchange;
+ *
+ */
+int _gnutls_gen_psk_client_kx(gnutls_session_t session, opaque ** data)
+{
+ int ret;
+ gnutls_datum *username;
+ gnutls_psk_client_credentials_t cred;
+ gnutls_datum * psk;
+
+ cred = (gnutls_srp_client_credentials_t)
+ _gnutls_get_cred(session->key, GNUTLS_CRD_PSK, NULL);
+
+ if (cred == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ if (session->internals.psk_username == NULL) {
+ username = &cred->username;
+ psk = &cred->psk_key;
+ } else {
+ username = &session->internals.psk_username;
+ psk = &session->internals.psk_key;
+ }
+
+ if (username == NULL || psk == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ ret = _gnutls_set_datum( session->key.key, psk->data, psk->size);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ (*data) = gnutls_malloc( 2 + username.size);
+ if ((*data) == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ _gnutls_write_datum16( *data, username);
+
+ return (username.size + 2);
+}
+
+
+/* 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 username;
+ gnutls_psk_client_credentials_t cred;
+ gnutls_datum * psk;
+
+ cred = (gnutls_srp_client_credentials_t)
+ _gnutls_get_cred(session->key, GNUTLS_CRD_PSK, NULL);
+
+ if (cred == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+
+ DECR_LEN(data_size, 2);
+ username.size = _gnutls_read_uint16(&data[0]);
+
+ DECR_LEN(data_size, username.size);
+
+ username.data = &data[2];
+
+ if (session->internals.psk_passwd_file != NULL) {
+ psk = _gnutls_find_psk( session->internals.psk_passwd_file, &username);
+ } else {
+ psk = _callback_psk( session, &username);
+ }
+
+ if (psk == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ /* set the session key
+ */
+ ret = _gnutls_set_datum( session->key.key, psk->data, psk->size);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ return 0;
+}
+
+
+#endif /* ENABLE_PSK */
diff --git a/lib/auth_psk.h b/lib/auth_psk.h
new file mode 100644
index 0000000000..59b49abc1e
--- /dev/null
+++ b/lib/auth_psk.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavroyanopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifndef AUTH_PSK_H
+# define AUTH_PSK_H
+
+#include <gnutls_auth.h>
+
+typedef struct gnutls_psk_client_credentials_st {
+ gnutls_datum username;
+ gnutls_datum key;
+ gnutls_psk_client_credentials_function *get_function;
+} psk_client_credentials_st;
+
+typedef struct gnutls_psk_server_credentials_st {
+ char *password_file;
+ /* callback function, instead of reading the
+ * password files.
+ */
+ gnutls_psk_server_credentials_function *pwd_callback;
+} psk_server_cred_st;
+
+/* these structures should not use allocated data */
+typedef struct psk_server_auth_info_st {
+ char username[MAX_SRP_USERNAME+1];
+} *psk_server_auth_info_t;
+
+
+#ifdef ENABLE_PSK
+
+typedef struct psk_server_auth_info_st psk_server_auth_info_st;
+
+#endif /* ENABLE_PSK */
+
+#endif
diff --git a/lib/auth_psk_passwd.c b/lib/auth_psk_passwd.c
new file mode 100644
index 0000000000..14cfa09f0c
--- /dev/null
+++ b/lib/auth_psk_passwd.c
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavroyanopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+/* Functions for operating in an SRP passwd file are included here */
+
+#include <gnutls_int.h>
+
+#ifdef ENABLE_PSK
+
+#include "x509_b64.h"
+#include "gnutls_errors.h"
+#include <auth_psk_passwd.h>
+#include "auth_psk.h"
+#include "gnutls_auth_int.h"
+#include "gnutls_psk.h"
+#include "gnutls_random.h"
+#include "gnutls_dh.h"
+#include "debug.h"
+#include <gnutls_str.h>
+#include <gnutls_datum.h>
+#include <gnutls_num.h>
+
+static int _randomize_pwd_entry(PSK_PWD_ENTRY * entry);
+
+/* this function parses tpasswd.conf file. Format is:
+ * string(username):base64(v)
+ */
+static int pwd_put_values(PSK_PWD_ENTRY * entry, char *str)
+{
+ char *p;
+ int len, ret;
+ opaque *verifier;
+ size_t verifier_size;
+ int indx;
+
+
+ p = strchr(str, ':'); /* we have index */
+ if (p == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_PSK_PWD_PARSING_ERROR;
+ }
+
+ *p = '\0';
+ p++;
+
+ /* username
+ */
+ len = strlen(p);
+ entry->username = gnutls_strdup( str);
+
+ /* read the key
+ */
+ len = strlen(p);
+ if (p[len - 1] == '\n' || p[len - 1] == ' ')
+ len--;
+
+ entry->key.size = len;
+
+
+ /* now go for key */
+
+
+ return indx;
+}
+
+
+ int ret;
+
+ p = strrchr(str, ':'); /* we have g */
+ if (p == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_SRP_PWD_PARSING_ERROR;
+ }
+
+ *p = '\0';
+ p++;
+
+ /* read the generator */
+ len = strlen(p);
+ if (p[len - 1] == '\n' || p[len - 1] == ' ')
+ len--;
+ ret = _gnutls_sbase64_decode(p, len, &tmp);
+
+ if (ret < 0) {
+ gnutls_assert();
+ return GNUTLS_E_SRP_PWD_PARSING_ERROR;
+ }
+
+ entry->g.data = tmp;
+ entry->g.size = ret;
+
+ /* now go for n - modulo */
+ p = strrchr(str, ':'); /* we have n */
+ if (p == NULL) {
+ _gnutls_free_datum(&entry->g);
+ gnutls_assert();
+ return GNUTLS_E_SRP_PWD_PARSING_ERROR;
+ }
+
+ *p = '\0';
+ p++;
+
+ len = strlen(p);
+ ret = _gnutls_sbase64_decode(p, len, &tmp);
+
+ if (ret < 0) {
+ gnutls_assert();
+ _gnutls_free_datum(&entry->g);
+ return GNUTLS_E_SRP_PWD_PARSING_ERROR;
+ }
+
+ entry->n.data = tmp;
+ entry->n.size = ret;
+
+ return 0;
+}
+
+
+/* this function opens the tpasswd.conf file and reads the g and n
+ * values. They are put in the entry.
+ */
+static int pwd_read_conf(const char *pconf_file, SRP_PWD_ENTRY * entry,
+ int idx)
+{
+ FILE *fd;
+ char line[2 * 1024];
+ uint i, len;
+ char indexstr[10];
+
+ sprintf(indexstr, "%d", idx); /* Flawfinder: ignore */
+
+ fd = fopen(pconf_file, "r");
+ if (fd == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_FILE_ERROR;
+ }
+
+ len = strlen(indexstr);
+ while (fgets(line, sizeof(line), fd) != NULL) {
+ /* move to first ':' */
+ i = 0;
+ while ((line[i] != ':') && (line[i] != '\0') && (i < sizeof(line))) {
+ i++;
+ }
+ if (strncmp(indexstr, line, MAX(i, len)) == 0) {
+ if ((idx = pwd_put_values2(entry, line)) >= 0)
+ return 0;
+ else {
+ return GNUTLS_E_SRP_PWD_ERROR;
+ }
+ }
+ }
+ return GNUTLS_E_SRP_PWD_ERROR;
+
+}
+
+int _gnutls_srp_pwd_read_entry(gnutls_session_t state, char *username,
+ SRP_PWD_ENTRY ** _entry)
+{
+ gnutls_srp_server_credentials_t cred;
+ FILE *fd;
+ char line[2 * 1024];
+ uint i, len;
+ int ret;
+ int idx, last_idx;
+ SRP_PWD_ENTRY *entry;
+
+ *_entry = gnutls_calloc(1, sizeof(SRP_PWD_ENTRY));
+ if (*_entry == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ entry = *_entry;
+
+ cred = (gnutls_srp_server_credentials_t)
+ _gnutls_get_cred(state->key, GNUTLS_CRD_SRP, NULL);
+ if (cred == NULL) {
+ gnutls_assert();
+ _gnutls_srp_entry_free(entry);
+ return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
+ }
+
+ /* if the callback which sends the parameters is
+ * set, use it.
+ */
+ if (cred->pwd_callback != NULL) {
+ ret = cred->pwd_callback(state, username, &entry->salt,
+ &entry->v, &entry->g, &entry->n);
+
+ if (ret == 1) { /* the user does not exist */
+ if (entry->g.size != 0 && entry->n.size != 0) {
+ ret = _randomize_pwd_entry(entry);
+ if (ret < 0) {
+ _gnutls_srp_entry_free(entry);
+ return ret;
+ }
+ return 0;
+ } else {
+ gnutls_assert();
+ ret = -1; /* error in the callback */
+ }
+ }
+
+ if (ret < 0) {
+ gnutls_assert();
+ _gnutls_srp_entry_free(entry);
+ return GNUTLS_E_SRP_PWD_ERROR;
+ }
+
+ return 0;
+ }
+
+ /* The callback was not set. Proceed.
+ */
+
+ if (cred->password_file == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_SRP_PWD_ERROR;
+ }
+
+ /* Open the selected password file.
+ */
+ fd = fopen(cred->password_file, "r");
+ if (fd == NULL) {
+ gnutls_assert();
+ _gnutls_srp_entry_free(entry);
+ return GNUTLS_E_SRP_PWD_ERROR;
+ }
+
+ last_idx = 1; /* a default value */
+
+ len = strlen(username);
+ while (fgets(line, sizeof(line), fd) != NULL) {
+ /* move to first ':' */
+ i = 0;
+ while ((line[i] != ':') && (line[i] != '\0') && (i < sizeof(line))) {
+ i++;
+ }
+
+ if (strncmp(username, line, MAX(i, len)) == 0) {
+ if ((idx = pwd_put_values(entry, line)) >= 0) {
+ /* Keep the last index in memory, so we can retrieve fake parameters (g,n)
+ * when the user does not exist.
+ */
+ last_idx = idx;
+ if (pwd_read_conf(cred->password_conf_file, entry, idx)
+ == 0) {
+ return 0;
+ } else {
+ gnutls_assert();
+ _gnutls_srp_entry_free(entry);
+ return GNUTLS_E_SRP_PWD_ERROR;
+ }
+ } else {
+ gnutls_assert();
+ _gnutls_srp_entry_free(entry);
+ return GNUTLS_E_SRP_PWD_ERROR;
+ }
+ }
+ }
+
+ /* user was not found. Fake him. Actually read the g,n values from
+ * the last index found and randomize the entry.
+ */
+ if (pwd_read_conf(cred->password_conf_file, entry, last_idx) == 0) {
+ ret = _randomize_pwd_entry(entry);
+ if (ret < 0) {
+ gnutls_assert();
+ _gnutls_srp_entry_free(entry);
+ return ret;
+ }
+
+ return 0;
+ }
+
+ gnutls_assert();
+ _gnutls_srp_entry_free(entry);
+ return GNUTLS_E_SRP_PWD_ERROR;
+
+}
+
+/* Randomizes the given password entry. It actually sets the verifier
+ * and the salt. Returns 0 on success.
+ */
+static int _randomize_pwd_entry(SRP_PWD_ENTRY * entry)
+{
+ unsigned char rnd;
+
+ if (entry->g.size == 0 || entry->n.size == 0) {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ _gnutls_get_random(&rnd, 1, GNUTLS_WEAK_RANDOM);
+ entry->salt.size = (rnd % 10) + 9;
+
+ entry->v.data = gnutls_malloc(20);
+ entry->v.size = 20;
+ if (entry->v.data == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ _gnutls_get_random(entry->v.data, 20, GNUTLS_WEAK_RANDOM);
+
+ entry->salt.data = gnutls_malloc(entry->salt.size);
+ if (entry->salt.data == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ if (_gnutls_get_random
+ (entry->salt.data, entry->salt.size, GNUTLS_WEAK_RANDOM) < 0) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ return 0;
+}
+
+/* Free all the entry parameters, except if g and n are
+ * the static ones defined in extra.h
+ */
+void _gnutls_srp_entry_free(SRP_PWD_ENTRY * entry)
+{
+ _gnutls_free_datum(&entry->v);
+ _gnutls_free_datum(&entry->salt);
+
+ if (entry->g.data != gnutls_srp_1024_group_generator.data)
+ _gnutls_free_datum(&entry->g);
+
+ if (entry->n.data != gnutls_srp_1024_group_prime.data &&
+ entry->n.data != gnutls_srp_1536_group_prime.data &&
+ entry->n.data != gnutls_srp_2048_group_prime.data)
+ _gnutls_free_datum(&entry->n);
+
+ gnutls_free(entry->username);
+ gnutls_free(entry);
+}
+
+
+#endif /* ENABLE SRP */
diff --git a/lib/auth_psk_passwd.h b/lib/auth_psk_passwd.h
new file mode 100644
index 0000000000..7cdfddd7b0
--- /dev/null
+++ b/lib/auth_psk_passwd.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavroyanopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#ifdef ENABLE_PSK
+
+typedef struct {
+ char *username;
+ gnutls_datum_t key;
+} PSK_PWD_ENTRY;
+
+/* this is locally allocated. It should be freed using the provided function */
+int _gnutls_psk_pwd_read_entry(gnutls_session_t state, char *username,
+ PSK_PWD_ENTRY **);
+void _gnutls_psk_entry_free(SRP_PSK_ENTRY * entry);
+
+#endif /* ENABLE_SRP */
diff --git a/lib/auth_srp.h b/lib/auth_srp.h
index 4037150188..b23a7369c1 100644
--- a/lib/auth_srp.h
+++ b/lib/auth_srp.h
@@ -44,7 +44,7 @@ typedef struct gnutls_srp_server_credentials_st {
/* these structures should not use allocated data */
typedef struct srp_server_auth_info_st {
- char username[MAX_SRP_USERNAME];
+ char username[MAX_SRP_USERNAME+1];
} *srp_server_auth_info_t;
extern const gnutls_datum_t gnutls_srp_1024_group_prime;
diff --git a/lib/auth_srp_sb64.c b/lib/auth_srp_sb64.c
index b2982101f1..db48cac9c3 100644
--- a/lib/auth_srp_sb64.c
+++ b/lib/auth_srp_sb64.c
@@ -300,7 +300,7 @@ int _gnutls_sbase64_decode(uint8 * data, size_t idata_size,
*
**/
int gnutls_srp_base64_encode(const gnutls_datum_t * data, char *result,
- int *result_size)
+ size_t *result_size)
{
opaque *ret;
int size;
@@ -370,7 +370,7 @@ int gnutls_srp_base64_encode_alloc(const gnutls_datum_t * data,
* or 0 on success.
**/
int gnutls_srp_base64_decode(const gnutls_datum_t * b64_data, char *result,
- int *result_size)
+ size_t *result_size)
{
opaque *ret;
int size;
diff --git a/lib/ext_srp.c b/lib/ext_srp.c
index baff841c34..d6333ffd8d 100644
--- a/lib/ext_srp.c
+++ b/lib/ext_srp.c
@@ -52,9 +52,7 @@ int _gnutls_srp_recv_params(gnutls_session_t session, const opaque * data,
len = data[0];
DECR_LEN(data_size, len);
- if (sizeof
- (session->security_parameters.extensions.srp_username) <=
- len) {
+ if (MAX_SRP_USERNAME < len) {
gnutls_assert();
return GNUTLS_E_ILLEGAL_SRP_USERNAME;
}
diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c
index 7554ab58f0..66b36791bd 100644
--- a/lib/gnutls_algorithms.c
+++ b/lib/gnutls_algorithms.c
@@ -45,6 +45,7 @@ static const gnutls_cred_map cred_mappings[] = {
{GNUTLS_KX_RSA_EXPORT, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
{GNUTLS_KX_DHE_DSS, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
{GNUTLS_KX_DHE_RSA, GNUTLS_CRD_CERTIFICATE, GNUTLS_CRD_CERTIFICATE},
+ {GNUTLS_KX_PSK, GNUTLS_CRD_PSK, GNUTLS_CRD_PSK},
{GNUTLS_KX_SRP, GNUTLS_CRD_SRP, GNUTLS_CRD_SRP},
{GNUTLS_KX_SRP_RSA, GNUTLS_CRD_SRP, GNUTLS_CRD_CERTIFICATE},
{GNUTLS_KX_SRP_DSS, GNUTLS_CRD_SRP, GNUTLS_CRD_CERTIFICATE},
@@ -222,6 +223,7 @@ extern mod_auth_st dhe_rsa_auth_struct;
extern mod_auth_st dhe_dss_auth_struct;
extern mod_auth_st anon_auth_struct;
extern mod_auth_st srp_auth_struct;
+extern mod_auth_st psk_auth_struct;
extern mod_auth_st srp_rsa_auth_struct;
extern mod_auth_st srp_dss_auth_struct;
@@ -243,6 +245,9 @@ gnutls_kx_algo_entry _gnutls_kx_algorithms[MAX_KX_ALGOS] = {
{"SRP RSA", GNUTLS_KX_SRP_RSA, &srp_rsa_auth_struct, 0, 0},
{"SRP", GNUTLS_KX_SRP, &srp_auth_struct, 0, 0},
#endif
+#ifdef ENABLE_PSK
+ {"PSK", GNUTLS_KX_PSK, &psk_auth_struct, 0, 0},
+#endif
/* other algorithms are appended here by gnutls-extra
* initialization function.
*/
@@ -289,6 +294,14 @@ typedef struct {
#define GNUTLS_ANON_DH_AES_128_CBC_SHA1 { 0x00, 0x34 }
#define GNUTLS_ANON_DH_AES_256_CBC_SHA1 { 0x00, 0x3A }
+/* PSK (not in TLS 1.0)
+ * draft-ietf-tls-psk:
+ */
+#define GNUTLS_PSK_SHA_ARCFOUR_SHA1 { 0x00, 0x8A }
+#define GNUTLS_PSK_SHA_3DES_EDE_CBC_SHA1 { 0x00, 0x8B }
+#define GNUTLS_PSK_SHA_AES_128_CBC_SHA1 { 0x00, 0x8C }
+#define GNUTLS_PSK_SHA_AES_256_CBC_SHA1 { 0x00, 0x8D }
+
/* SRP (not in TLS 1.0)
* draft-ietf-tls-srp-02:
*/
@@ -373,6 +386,21 @@ static const gnutls_cipher_suite_entry cs_algorithms[] = {
GNUTLS_CIPHER_SUITE_ENTRY(GNUTLS_ANON_DH_AES_256_CBC_SHA1,
GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_ANON_DH,
GNUTLS_MAC_SHA1, GNUTLS_SSL3),
+
+ /* PSK */
+ GNUTLS_CIPHER_SUITE_ENTRY(GNUTLS_PSK_SHA_ARCFOUR_SHA1,
+ GNUTLS_CIPHER_ARCFOUR, GNUTLS_KX_PSK,
+ GNUTLS_MAC_SHA1, GNUTLS_TLS1),
+ GNUTLS_CIPHER_SUITE_ENTRY(GNUTLS_PSK_SHA_3DES_EDE_CBC_SHA1,
+ GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_PSK,
+ GNUTLS_MAC_SHA1, GNUTLS_TLS1),
+ GNUTLS_CIPHER_SUITE_ENTRY(GNUTLS_PSK_SHA_AES_128_CBC_SHA1,
+ GNUTLS_CIPHER_AES_128_CBC, GNUTLS_KX_PSK,
+ GNUTLS_MAC_SHA1, GNUTLS_TLS1),
+ GNUTLS_CIPHER_SUITE_ENTRY(GNUTLS_PSK_SHA_AES_256_CBC_SHA1,
+ GNUTLS_CIPHER_AES_256_CBC, GNUTLS_KX_PSK,
+ GNUTLS_MAC_SHA1, GNUTLS_TLS1),
+
/* SRP */
GNUTLS_CIPHER_SUITE_ENTRY(GNUTLS_SRP_SHA_3DES_EDE_CBC_SHA1,
GNUTLS_CIPHER_3DES_CBC, GNUTLS_KX_SRP,
diff --git a/lib/gnutls_compress_int.c b/lib/gnutls_compress_int.c
index f06e09bc1a..5a45e3e58f 100644
--- a/lib/gnutls_compress_int.c
+++ b/lib/gnutls_compress_int.c
@@ -162,6 +162,10 @@ int _gnutls_compress(comp_hd_t handle, const opaque * plain,
/* NULL compression is not handled here
*/
+ if (handle == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
switch (handle->algo) {
#ifdef USE_LZO
@@ -262,6 +266,11 @@ int _gnutls_decompress(comp_hd_t handle, opaque * compressed,
/* NULL compression is not handled here
*/
+ if (handle == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
switch (handle->algo) {
#ifdef USE_LZO
case GNUTLS_COMP_LZO:{
diff --git a/lib/gnutls_db.c b/lib/gnutls_db.c
index df3a98155e..29af963bf3 100644
--- a/lib/gnutls_db.c
+++ b/lib/gnutls_db.c
@@ -32,6 +32,7 @@
#include <gnutls_db.h>
#include "debug.h"
#include <gnutls_session_pack.h>
+#include <gnutls_datum.h>
/**
* gnutls_db_set_retrieve_function - Sets the function that will be used to get data
@@ -185,31 +186,15 @@ int _gnutls_server_register_current_session(gnutls_session_t session)
return GNUTLS_E_INVALID_SESSION;
}
-/* allocate space for data */
- ret = _gnutls_session_size(session);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
- content.size = ret;
-
- content.data = gnutls_malloc(content.size);
- if (content.data == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
-
/* copy data */
ret = _gnutls_session_pack(session, &content);
if (ret < 0) {
- gnutls_free(content.data);
gnutls_assert();
return ret;
}
ret = _gnutls_store_session(session, key, content);
-
- gnutls_free(content.data);
+ _gnutls_free_datum( &content);
return ret;
}
diff --git a/lib/gnutls_helper.c b/lib/gnutls_helper.c
new file mode 100644
index 0000000000..bdab26c870
--- /dev/null
+++ b/lib/gnutls_helper.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavroyanopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+
+int _gnutls_file_exists(const char *file)
+{
+ FILE *fd;
+
+ fd = fopen(file, "r");
+ if (fd == NULL)
+ return -1;
+
+ fclose(fd);
+ return 0;
+}
+
diff --git a/lib/gnutls_helper.h b/lib/gnutls_helper.h
new file mode 100644
index 0000000000..ef1156c11f
--- /dev/null
+++ b/lib/gnutls_helper.h
@@ -0,0 +1 @@
+int _gnutls_file_exists(const char *file);
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 937c642389..1733b7d6d1 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -244,7 +244,7 @@ typedef struct {
server_name_st server_names[MAX_SERVER_NAME_EXTENSIONS];
/* limit server_name extensions */
uint server_names_size;
- opaque srp_username[MAX_SRP_USERNAME];
+ opaque srp_username[MAX_SRP_USERNAME+1];
} tls_ext_st;
/* auth_info_t structures now MAY contain malloced
@@ -272,6 +272,7 @@ typedef struct {
* there is a time in handshake where the peer has
* null cipher and we don't
*/
+ /* FIXME: remove the read and write stuff... keep only one version */
gnutls_cipher_algorithm_t read_bulk_cipher_algorithm;
gnutls_mac_algorithm_t read_mac_algorithm;
gnutls_compression_method_t read_compression_algorithm;
diff --git a/lib/gnutls_psk.c b/lib/gnutls_psk.c
new file mode 100644
index 0000000000..629c860016
--- /dev/null
+++ b/lib/gnutls_psk.c
@@ -0,0 +1,700 @@
+/*
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation
+ *
+ * Author: Nikos Mavroyanopoulos
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <auth_srp.h>
+#include <gnutls_state.h>
+
+#ifdef ENABLE_SRP
+
+#include <gnutls_srp.h>
+#include <auth_srp_passwd.h>
+#include <gnutls_mpi.h>
+#include <gnutls_num.h>
+#include "debug.h"
+
+
+/* Here functions for SRP (like g^x mod n) are defined
+ */
+
+int _gnutls_srp_gx(opaque * text, size_t textsize, opaque ** result,
+ mpi_t g, mpi_t prime, gnutls_alloc_function galloc_func)
+{
+ mpi_t x, e;
+ size_t result_size;
+
+ if (_gnutls_mpi_scan_nz(&x, text, &textsize)) {
+ gnutls_assert();
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ e = _gnutls_mpi_alloc_like(prime);
+ if (e == NULL) {
+ gnutls_assert();
+ _gnutls_mpi_release(&x);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ /* e = g^x mod prime (n) */
+ _gnutls_mpi_powm(e, g, x, prime);
+ _gnutls_mpi_release(&x);
+
+ _gnutls_mpi_print(NULL, &result_size, e);
+ if (result != NULL) {
+ *result = galloc_func(result_size);
+ if ((*result) == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ _gnutls_mpi_print(*result, &result_size, e);
+ }
+
+ _gnutls_mpi_release(&e);
+
+ return result_size;
+
+}
+
+
+/****************
+ * Choose a random value b and calculate B = (k* v + g^b) % N.
+ * where k == SHA1(N|g)
+ * Return: B and if ret_b is not NULL b.
+ */
+mpi_t _gnutls_calc_srp_B(mpi_t * ret_b, mpi_t g, mpi_t n, mpi_t v)
+{
+ mpi_t tmpB = NULL, tmpV = NULL;
+ mpi_t b = NULL, B = NULL, k = NULL;
+ int bits;
+
+
+ /* calculate: B = (k*v + g^b) % N
+ */
+ bits = _gnutls_mpi_get_nbits(n);
+ b = _gnutls_mpi_snew(bits);
+ if (b == NULL) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ tmpV = _gnutls_mpi_alloc_like(n);
+
+ if (tmpV == NULL) {
+ gnutls_assert();
+ goto error;
+ }
+
+ _gnutls_mpi_randomize(b, bits, GCRY_STRONG_RANDOM);
+
+ tmpB = _gnutls_mpi_snew(bits);
+ if (tmpB == NULL) {
+ gnutls_assert();
+ goto error;
+ }
+
+ B = _gnutls_mpi_snew(bits);
+ if (B == NULL) {
+ gnutls_assert();
+ goto error;
+ }
+
+ k = _gnutls_calc_srp_u(n, g, n);
+ if (k == NULL) {
+ gnutls_assert();
+ goto error;
+ }
+
+ _gnutls_mpi_mulm(tmpV, k, v, n);
+ _gnutls_mpi_powm(tmpB, g, b, n);
+
+ _gnutls_mpi_addm(B, tmpV, tmpB, n);
+
+ _gnutls_mpi_release(&k);
+ _gnutls_mpi_release(&tmpB);
+ _gnutls_mpi_release(&tmpV);
+
+ if (ret_b)
+ *ret_b = b;
+ else
+ _gnutls_mpi_release(&b);
+
+ return B;
+
+ error:
+ _gnutls_mpi_release(&b);
+ _gnutls_mpi_release(&B);
+ _gnutls_mpi_release(&k);
+ _gnutls_mpi_release(&tmpB);
+ _gnutls_mpi_release(&tmpV);
+ return NULL;
+
+}
+
+/* This calculates the SHA1(A | B)
+ * A and B will be left-padded with zeros to fill n_size.
+ */
+mpi_t _gnutls_calc_srp_u(mpi_t A, mpi_t B, mpi_t n)
+{
+ size_t b_size, a_size;
+ opaque *holder, hd[MAX_HASH_SIZE];
+ size_t holder_size, hash_size, n_size;
+ GNUTLS_HASH_HANDLE td;
+ int ret;
+ mpi_t res;
+
+ /* get the size of n in bytes */
+ _gnutls_mpi_print(NULL, &n_size, n);
+
+ _gnutls_mpi_print(NULL, &a_size, A);
+ _gnutls_mpi_print(NULL, &b_size, B);
+
+ if (a_size > n_size || b_size > n_size) {
+ gnutls_assert();
+ return NULL; /* internal error */
+ }
+
+ holder_size = n_size + n_size;
+
+ holder = gnutls_calloc(1, holder_size);
+ if (holder == NULL)
+ return NULL;
+
+ _gnutls_mpi_print(&holder[n_size - a_size], &a_size, A);
+ _gnutls_mpi_print(&holder[n_size + n_size - b_size], &b_size, B);
+
+ td = _gnutls_hash_init(GNUTLS_MAC_SHA1);
+ if (td == NULL) {
+ gnutls_free(holder);
+ gnutls_assert();
+ return NULL;
+ }
+ _gnutls_hash(td, holder, holder_size);
+ _gnutls_hash_deinit(td, hd);
+
+ /* convert the bytes of hd to integer
+ */
+ hash_size = 20; /* SHA */
+ ret = _gnutls_mpi_scan_nz(&res, hd, &hash_size);
+ gnutls_free(holder);
+
+ if (ret < 0) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ return res;
+}
+
+/* S = (A * v^u) ^ b % N
+ * this is our shared key (server premaster secret)
+ */
+mpi_t _gnutls_calc_srp_S1(mpi_t A, mpi_t b, mpi_t u, mpi_t v, mpi_t n)
+{
+ mpi_t tmp1 = NULL, tmp2 = NULL;
+ mpi_t S = NULL;
+
+ S = _gnutls_mpi_alloc_like(n);
+ if (S == NULL)
+ return NULL;
+
+ tmp1 = _gnutls_mpi_alloc_like(n);
+ tmp2 = _gnutls_mpi_alloc_like(n);
+
+ if (tmp1 == NULL || tmp2 == NULL)
+ goto freeall;
+
+ _gnutls_mpi_powm(tmp1, v, u, n);
+ _gnutls_mpi_mulm(tmp2, A, tmp1, n);
+ _gnutls_mpi_powm(S, tmp2, b, n);
+
+ _gnutls_mpi_release(&tmp1);
+ _gnutls_mpi_release(&tmp2);
+
+ return S;
+
+ freeall:
+ _gnutls_mpi_release(&tmp1);
+ _gnutls_mpi_release(&tmp2);
+ return NULL;
+}
+
+/* A = g^a % N
+ * returns A and a (which is random)
+ */
+mpi_t _gnutls_calc_srp_A(mpi_t * a, mpi_t g, mpi_t n)
+{
+ mpi_t tmpa;
+ mpi_t A;
+ int bits;
+
+ bits = _gnutls_mpi_get_nbits(n);
+ tmpa = _gnutls_mpi_snew(bits);
+ if (tmpa == NULL) {
+ gnutls_assert();
+ return NULL;
+ }
+
+ _gnutls_mpi_randomize(tmpa, bits, GCRY_STRONG_RANDOM);
+
+ A = _gnutls_mpi_snew(bits);
+ if (A == NULL) {
+ gnutls_assert();
+ _gnutls_mpi_release(&tmpa);
+ return NULL;
+ }
+ _gnutls_mpi_powm(A, g, tmpa, n);
+
+ if (a != NULL)
+ *a = tmpa;
+ else
+ _gnutls_mpi_release(&tmpa);
+
+ return A;
+}
+
+/* generate x = SHA(s | SHA(U | ":" | p))
+ * The output is exactly 20 bytes
+ */
+int _gnutls_calc_srp_sha(const char *username, const char *password,
+ opaque * salt, int salt_size, size_t * size,
+ void *digest)
+{
+ GNUTLS_HASH_HANDLE td;
+ opaque res[MAX_HASH_SIZE];
+
+ *size = 20;
+
+ td = _gnutls_hash_init(GNUTLS_MAC_SHA1);
+ if (td == NULL) {
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ _gnutls_hash(td, username, strlen(username));
+ _gnutls_hash(td, ":", 1);
+ _gnutls_hash(td, password, strlen(password));
+
+ _gnutls_hash_deinit(td, res);
+
+ td = _gnutls_hash_init(GNUTLS_MAC_SHA1);
+ if (td == NULL) {
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ _gnutls_hash(td, salt, salt_size);
+ _gnutls_hash(td, res, 20); /* 20 bytes is the output of sha1 */
+
+ _gnutls_hash_deinit(td, digest);
+
+ return 0;
+}
+
+int _gnutls_calc_srp_x(char *username, char *password, opaque * salt,
+ size_t salt_size, size_t * size, void *digest)
+{
+
+ return _gnutls_calc_srp_sha(username, password, salt,
+ salt_size, size, digest);
+}
+
+
+/* S = (B - k*g^x) ^ (a + u * x) % N
+ * this is our shared key (client premaster secret)
+ */
+mpi_t _gnutls_calc_srp_S2(mpi_t B, mpi_t g, mpi_t x,
+ mpi_t a, mpi_t u, mpi_t n)
+{
+ mpi_t S = NULL, tmp1 = NULL, tmp2 = NULL;
+ mpi_t tmp4 = NULL, tmp3 = NULL, k = NULL;
+
+ S = _gnutls_mpi_alloc_like(n);
+ if (S == NULL)
+ return NULL;
+
+ tmp1 = _gnutls_mpi_alloc_like(n);
+ tmp2 = _gnutls_mpi_alloc_like(n);
+ tmp3 = _gnutls_mpi_alloc_like(n);
+ if (tmp1 == NULL || tmp2 == NULL || tmp3 == NULL) {
+ goto freeall;
+ }
+
+ k = _gnutls_calc_srp_u(n, g, n);
+ if (k == NULL) {
+ gnutls_assert();
+ goto freeall;
+ }
+
+ _gnutls_mpi_powm(tmp1, g, x, n); /* g^x */
+ _gnutls_mpi_mulm(tmp3, tmp1, k, n); /* k*g^x mod n */
+ _gnutls_mpi_subm(tmp2, B, tmp3, n);
+
+ tmp4 = _gnutls_mpi_alloc_like(n);
+ if (tmp4 == NULL)
+ goto freeall;
+
+ _gnutls_mpi_mul(tmp1, u, x);
+ _gnutls_mpi_add(tmp4, a, tmp1);
+ _gnutls_mpi_powm(S, tmp2, tmp4, n);
+
+ _gnutls_mpi_release(&tmp1);
+ _gnutls_mpi_release(&tmp2);
+ _gnutls_mpi_release(&tmp3);
+ _gnutls_mpi_release(&tmp4);
+ _gnutls_mpi_release(&k);
+
+ return S;
+
+ freeall:
+ _gnutls_mpi_release(&k);
+ _gnutls_mpi_release(&tmp1);
+ _gnutls_mpi_release(&tmp2);
+ _gnutls_mpi_release(&tmp3);
+ _gnutls_mpi_release(&tmp4);
+ _gnutls_mpi_release(&S);
+ return NULL;
+}
+
+/**
+ * gnutls_srp_free_client_credentials - Used to free an allocated gnutls_srp_client_credentials_t structure
+ * @sc: is an #gnutls_srp_client_credentials_t structure.
+ *
+ * This structure is complex enough to manipulate directly thus
+ * this helper function is provided in order to free (deallocate) it.
+ *
+ **/
+void gnutls_srp_free_client_credentials(gnutls_srp_client_credentials_t sc)
+{
+ gnutls_free(sc->username);
+ gnutls_free(sc->password);
+ gnutls_free(sc);
+}
+
+/**
+ * gnutls_srp_allocate_client_credentials - Used to allocate an gnutls_srp_server_credentials_t structure
+ * @sc: is a pointer to an #gnutls_srp_server_credentials_t structure.
+ *
+ * This structure is complex enough to manipulate directly thus
+ * this helper function is provided in order to allocate it.
+ *
+ * Returns 0 on success.
+ **/
+int gnutls_srp_allocate_client_credentials(gnutls_srp_client_credentials_t
+ * sc)
+{
+ *sc = gnutls_calloc(1, sizeof(srp_client_credentials_st));
+
+ if (*sc == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ return 0;
+}
+
+/**
+ * gnutls_srp_set_client_credentials - Used to set the username/password, in a gnutls_srp_client_credentials_t structure
+ * @res: is an #gnutls_srp_client_credentials_t structure.
+ * @username: is the user's userid
+ * @password: is the user's password
+ *
+ * This function sets the username and password, in a gnutls_srp_client_credentials_t structure.
+ * Those will be used in SRP authentication. @username and @password should be ASCII
+ * strings or UTF-8 strings prepared using the "SASLprep" profile of "stringprep".
+ *
+ * Returns 0 on success.
+ **/
+int gnutls_srp_set_client_credentials(gnutls_srp_client_credentials_t res,
+ char *username, char *password)
+{
+
+ if (username == NULL || password == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ res->username = gnutls_strdup(username);
+ if (res->username == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ res->password = gnutls_strdup(password);
+ if (res->password == NULL) {
+ gnutls_free(res->username);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ return 0;
+}
+
+/**
+ * gnutls_srp_free_server_credentials - Used to free an allocated gnutls_srp_server_credentials_t structure
+ * @sc: is an #gnutls_srp_server_credentials_t structure.
+ *
+ * This structure is complex enough to manipulate directly thus
+ * this helper function is provided in order to free (deallocate) it.
+ *
+ **/
+void gnutls_srp_free_server_credentials(gnutls_srp_server_credentials_t sc)
+{
+ gnutls_free(sc->password_file);
+ gnutls_free(sc->password_conf_file);
+
+ gnutls_free(sc);
+}
+
+/**
+ * gnutls_srp_allocate_server_credentials - Used to allocate an gnutls_srp_server_credentials_t structure
+ * @sc: is a pointer to an #gnutls_srp_server_credentials_t structure.
+ *
+ * This structure is complex enough to manipulate directly thus
+ * this helper function is provided in order to allocate it.
+ *
+ * Returns 0 on success.
+ **/
+int gnutls_srp_allocate_server_credentials(gnutls_srp_server_credentials_t
+ * sc)
+{
+ *sc = gnutls_calloc(1, sizeof(srp_server_cred_st));
+
+ if (*sc == NULL)
+ return GNUTLS_E_MEMORY_ERROR;
+
+ return 0;
+}
+
+inline static int file_exists(const char *file)
+{
+ FILE *fd;
+
+ fd = fopen(file, "r");
+ if (fd == NULL)
+ return -1;
+
+ fclose(fd);
+ return 0;
+}
+
+/**
+ * gnutls_srp_set_server_credentials_file - Used to set the password files, in a gnutls_srp_server_credentials_t structure
+ * @res: is an #gnutls_srp_server_credentials_t structure.
+ * @password_file: is the SRP password file (tpasswd)
+ * @password_conf_file: is the SRP password conf file (tpasswd.conf)
+ *
+ * This function sets the password files, in a gnutls_srp_server_credentials_t structure.
+ * Those password files hold usernames and verifiers and will be used for SRP authentication.
+ *
+ * Returns 0 on success.
+ *
+ **/
+int gnutls_srp_set_server_credentials_file(gnutls_srp_server_credentials_t
+ res, const char *password_file,
+ const char *password_conf_file)
+{
+
+ if (password_file == NULL || password_conf_file == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* Check if the files can be opened */
+ if (file_exists(password_file) != 0) {
+ gnutls_assert();
+ return GNUTLS_E_FILE_ERROR;
+ }
+
+ if (file_exists(password_conf_file) != 0) {
+ gnutls_assert();
+ return GNUTLS_E_FILE_ERROR;
+ }
+
+ res->password_file = gnutls_strdup(password_file);
+ if (res->password_file == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ res->password_conf_file = gnutls_strdup(password_conf_file);
+ if (res->password_conf_file == NULL) {
+ gnutls_assert();
+ gnutls_free(res->password_file);
+ res->password_file = NULL;
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ return 0;
+}
+
+
+/**
+ * gnutls_srp_set_server_credentials_function - Used to set a callback to retrieve the user's SRP credentials
+ * @cred: is a #gnutls_srp_server_credentials_t structure.
+ * @func: is the callback function
+ *
+ * This function can be used to set a callback to retrieve the user's SRP credentials.
+ * The callback's function form is:
+ * int (*callback)(gnutls_session_t, const char* username,
+ * gnutls_datum_t* salt, gnutls_datum_t *verifier, gnutls_datum_t* g,
+ * gnutls_datum_t* n);
+ *
+ * @username contains the actual username.
+ * The @salt, @verifier, @generator and @prime must be filled
+ * in using the gnutls_malloc(). For convenience @prime and @generator
+ * may also be one of the static parameters defined in extra.h.
+ *
+ * In case the callback returned a negative number then gnutls will
+ * assume that the username does not exist.
+ *
+ * In order to prevent attackers from guessing valid usernames,
+ * if a user does not exist, g and n values should be filled in
+ * using a random user's parameters. In that case the callback must
+ * return the special value (1).
+ *
+ * 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_srp_set_server_credentials_function(gnutls_srp_server_credentials_t
+ cred,
+ gnutls_srp_server_credentials_function
+ * func)
+{
+ cred->pwd_callback = func;
+}
+
+/**
+ * gnutls_srp_set_client_credentials_function - Used to set a callback to retrieve the username and password
+ * @cred: is a #gnutls_srp_server_credentials_t structure.
+ * @func: is the callback function
+ *
+ * This function can be used to set a callback to retrieve the username and
+ * password for client SRP authentication.
+ * The callback's function form is:
+ * int (*callback)(gnutls_session_t, unsigned int times, char** username,
+ * char** password);
+ *
+ * The @username and @password must be allocated using gnutls_malloc().
+ * @times will be 0 the first time called, and 1 the second.
+ * @username and @password should be ASCII strings or UTF-8 strings
+ * prepared using the "SASLprep" profile of "stringprep".
+ *
+ * The callback function will be called once or twice per handshake.
+ * The first time called, is before the ciphersuite is negotiated.
+ * At that time if the callback returns a negative error code,
+ * the callback will be called again if SRP has been
+ * negotiated. This uses a special TLS-SRP idiom in order to avoid
+ * asking the user for SRP password and username if the server does
+ * not support SRP.
+ *
+ * The callback should not return a negative error code the second
+ * time called, since the handshake procedure will be aborted.
+ *
+ * The callback function should return 0 on success.
+ * -1 indicates an error.
+ *
+ **/
+void
+gnutls_srp_set_client_credentials_function(gnutls_srp_client_credentials_t
+ cred,
+ gnutls_srp_client_credentials_function
+ * func)
+{
+ cred->get_function = func;
+}
+
+
+/**
+ * gnutls_srp_server_get_username - This function returns the username of the peer
+ * @session: is a gnutls session
+ *
+ * This function will return the username of the peer. This should only be
+ * called in case of SRP authentication and in case of a server.
+ * Returns NULL in case of an error.
+ *
+ **/
+const char *gnutls_srp_server_get_username(gnutls_session_t session)
+{
+ srp_server_auth_info_t info;
+
+ CHECK_AUTH(GNUTLS_CRD_SRP, NULL);
+
+ info = _gnutls_get_auth_info(session);
+ if (info == NULL)
+ return NULL;
+ return info->username;
+}
+
+/**
+ * gnutls_srp_verifier - Used to calculate an SRP verifier
+ * @username: is the user's name
+ * @password: is the user's password
+ * @salt: should be some randomly generated bytes
+ * @generator: is the generator of the group
+ * @prime: is the group's prime
+ * @res: where the verifier will be stored.
+ *
+ * This function will create an SRP verifier, as specified in RFC2945.
+ * The @prime and @generator should be one of the static parameters defined
+ * in gnutls/extra.h or may be generated using the GCRYPT functions
+ * gcry_prime_generate() and gcry_prime_group_generator().
+ * The verifier will be allocated with @malloc and will be stored in @res using
+ * binary format.
+ *
+ **/
+int gnutls_srp_verifier(const char *username, const char *password,
+ const gnutls_datum_t * salt,
+ const gnutls_datum_t * generator,
+ const gnutls_datum_t * prime, gnutls_datum_t * res)
+{
+ mpi_t _n, _g;
+ int ret;
+ size_t digest_size = 20, size;
+ opaque digest[20];
+
+ ret = _gnutls_calc_srp_sha(username, password, salt->data,
+ salt->size, &digest_size, digest);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ size = prime->size;
+ if (_gnutls_mpi_scan_nz(&_n, prime->data, &size)) {
+ gnutls_assert();
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ size = generator->size;
+ if (_gnutls_mpi_scan_nz(&_g, generator->data, &size)) {
+ gnutls_assert();
+ return GNUTLS_E_MPI_SCAN_FAILED;
+ }
+
+ ret = _gnutls_srp_gx(digest, 20, &res->data, _g, _n, malloc);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+ res->size = ret;
+
+ return 0;
+}
+
+#endif /* ENABLE_SRP */
diff --git a/lib/gnutls_session.c b/lib/gnutls_session.c
index a349cf4450..cf0d37a14d 100644
--- a/lib/gnutls_session.c
+++ b/lib/gnutls_session.c
@@ -26,8 +26,6 @@
#include "debug.h"
#include <gnutls_session_pack.h>
-#define SESSION_SIZE _gnutls_session_size( session)
-
/**
* gnutls_session_get_data - Returns all session parameters.
* @session: is a #gnutls_session_t structure.
@@ -48,17 +46,8 @@ int gnutls_session_get_data(gnutls_session_t session,
gnutls_datum_t psession;
int ret;
- if (*session_data_size < SESSION_SIZE || session_data == NULL) {
- *session_data_size = SESSION_SIZE;
- session_data = NULL; /* return with the new session_data_size value */
- }
-
if (session->internals.resumable == RESUME_FALSE)
return GNUTLS_E_INVALID_SESSION;
- /* just return the session size */
- if (session_data == NULL) {
- return 0;
- }
psession.data = session_data;
@@ -69,6 +58,46 @@ int gnutls_session_get_data(gnutls_session_t session,
}
*session_data_size = psession.size;
+ if (psession.size > *session_data_size)
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+
+ if (session_data != NULL)
+ memcpy(session_data, psession.data, psession.size);
+
+ return 0;
+}
+
+/**
+ * gnutls_session_get_data2 - Returns all session parameters.
+ * @session: is a #gnutls_session_t structure.
+ * @session_data: is a pointer to a datum that will hold the session.
+ *
+ * Returns all session parameters, in order to support resuming.
+ * The client should call this, and keep the returned session, if he wants to
+ * resume that current version later by calling gnutls_session_set_data()
+ * This function must be called after a successful handshake. The returned
+ * datum must be freed with gnutls_free().
+ *
+ * Resuming sessions is really useful and speedups connections after a succesful one.
+ **/
+int gnutls_session_get_data2(gnutls_session_t session, gnutls_datum * data)
+{
+
+ int ret;
+
+ if (data == NULL) {
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ if (session->internals.resumable == RESUME_FALSE)
+ return GNUTLS_E_INVALID_SESSION;
+
+ ret = _gnutls_session_pack(session, data);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
return 0;
}
diff --git a/lib/gnutls_session_pack.c b/lib/gnutls_session_pack.c
index 4f937febe6..93753d2301 100644
--- a/lib/gnutls_session_pack.c
+++ b/lib/gnutls_session_pack.c
@@ -30,6 +30,9 @@
#ifdef ENABLE_SRP
# include <auth_srp.h>
#endif
+#ifdef ENABLE_SRP
+# include <auth_psk.h>
+#endif
#include <auth_anon.h>
#include <auth_cert.h>
#include <gnutls_errors.h>
@@ -39,23 +42,45 @@
#include <gnutls_num.h>
#define PACK_HEADER_SIZE 1
-static int _gnutls_pack_certificate_auth_info(cert_auth_info_t info,
- gnutls_datum_t *
- packed_session);
-static int _gnutls_unpack_certificate_auth_info(cert_auth_info_t info,
- const gnutls_datum_t *
- packed_session);
-static int _gnutls_pack_certificate_auth_info_size(cert_auth_info_t info);
+#define MAX_SEC_PARAMS 7+MAX_SRP_USERNAME+MAX_SERVER_NAME_EXTENSIONS*(3+MAX_SERVER_NAME_SIZE)+165
+static int pack_certificate_auth_info(gnutls_session_t,
+ gnutls_datum_t * packed_session);
+static int unpack_certificate_auth_info(gnutls_session_t,
+ const gnutls_datum_t *
+ packed_session);
+
+static int unpack_srp_auth_info(gnutls_session_t session,
+ const gnutls_datum * packed_session);
+static int pack_srp_auth_info(gnutls_session_t session,
+ gnutls_datum * packed_session);
+
+static int unpack_psk_auth_info(gnutls_session_t session,
+ const gnutls_datum * packed_session);
+static int pack_psk_auth_info(gnutls_session_t session,
+ gnutls_datum * packed_session);
+
+static int unpack_anon_auth_info(gnutls_session_t session,
+ const gnutls_datum * packed_session);
+static int pack_anon_auth_info(gnutls_session_t session,
+ gnutls_datum * packed_session);
+
+static int unpack_security_parameters(gnutls_session_t session,
+ const gnutls_datum * packed_session);
+static int pack_security_parameters(gnutls_session_t session,
+ gnutls_datum * packed_session);
/* Since auth_info structures contain malloced data, this function
* is required in order to pack these structures in a vector in
* order to store them to the DB.
+ *
+ * packed_session will contain the session data.
+ *
+ * The data will be in a platform independent format.
*/
int _gnutls_session_pack(gnutls_session_t session,
gnutls_datum_t * packed_session)
{
- uint32 pack_size;
int ret;
if (packed_session == NULL) {
@@ -66,66 +91,37 @@ int _gnutls_session_pack(gnutls_session_t session,
switch (gnutls_auth_get_type(session)) {
#ifdef ENABLE_SRP
- case GNUTLS_CRD_SRP:{
- srp_server_auth_info_t info = _gnutls_get_auth_info(session);
-
-
- if (info == NULL && session->key->auth_info_size != 0) {
- gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- pack_size = session->key->auth_info_size;
- packed_session->size =
- PACK_HEADER_SIZE + pack_size + sizeof(uint32);
-
- packed_session->data[0] = GNUTLS_CRD_SRP;
- _gnutls_write_uint32(pack_size,
- &packed_session->data[PACK_HEADER_SIZE]);
-
- if (session->key->auth_info_size > 0)
- memcpy(&packed_session->
- data[PACK_HEADER_SIZE + sizeof(uint32)],
- info, session->key->auth_info_size);
-
+ case GNUTLS_CRD_SRP:
+ ret = pack_srp_auth_info(session, packed_session);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
}
-
break;
#endif
- case GNUTLS_CRD_ANON:{
- anon_auth_info_t info = _gnutls_get_auth_info(session);
- if (info == NULL && session->key->auth_info_size != 0) {
- gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- packed_session->size =
- PACK_HEADER_SIZE + session->key->auth_info_size +
- sizeof(uint32);
-
- packed_session->data[0] = GNUTLS_CRD_ANON;
- _gnutls_write_uint32(session->key->auth_info_size,
- &packed_session->data[PACK_HEADER_SIZE]);
-
- if (session->key->auth_info_size > 0)
- memcpy(&packed_session->
- data[PACK_HEADER_SIZE + sizeof(uint32)],
- info, session->key->auth_info_size);
-
+#ifdef ENABLE_SRP
+ case GNUTLS_CRD_PSK:
+ ret = pack_psk_auth_info(session, packed_session);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
}
break;
- case GNUTLS_CRD_CERTIFICATE:{
- cert_auth_info_t info = _gnutls_get_auth_info(session);
- if (info == NULL && session->key->auth_info_size != 0) {
- gnutls_assert();
- return GNUTLS_E_INVALID_REQUEST;
- }
-
- ret = _gnutls_pack_certificate_auth_info(info, packed_session);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
+#endif
+#ifdef ENABLE_ANON
+ case GNUTLS_CRD_ANON:
+ ret = pack_anon_auth_info(session, packed_session);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+ break;
+#endif
+ case GNUTLS_CRD_CERTIFICATE:
+ ret = pack_certificate_auth_info(session, packed_session);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
}
break;
default:
@@ -134,312 +130,911 @@ int _gnutls_session_pack(gnutls_session_t session,
}
/* Auth_info structures copied. Now copy security_parameters_st.
+ * packed_session must have allocated space for the security parameters.
*/
- packed_session->size +=
- sizeof(security_parameters_st) + sizeof(uint32);
-
- _gnutls_write_uint32(sizeof(security_parameters_st),
- &packed_session->data[packed_session->size -
- sizeof
- (security_parameters_st) -
- sizeof(uint32)]);
- memcpy(&packed_session->
- data[packed_session->size - sizeof(security_parameters_st)],
- &session->security_parameters, sizeof(security_parameters_st));
+ ret = pack_security_parameters(session, packed_session);
+ if (ret < 0) {
+ gnutls_assert();
+ _gnutls_free_datum( packed_session);
+ return ret;
+ }
return 0;
}
-/* Returns the size needed to hold the current session.
+
+/* Load session data from a buffer.
*/
-uint _gnutls_session_size(gnutls_session_t session)
+int _gnutls_session_unpack(gnutls_session_t session,
+ const gnutls_datum_t * packed_session)
{
- uint32 pack_size;
+ int ret;
+
+ if (packed_session == NULL || packed_session->size == 0) {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
- pack_size = PACK_HEADER_SIZE + sizeof(uint32);
+ if (session->key->auth_info != NULL) {
+ _gnutls_free_auth_info(session);
+ }
- switch (gnutls_auth_get_type(session)) {
+ switch (packed_session->data[0]) {
+#ifdef ENABLE_SRP
case GNUTLS_CRD_SRP:
+ ret = unpack_srp_auth_info(session, packed_session);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+ break;
+#endif
+#ifdef ENABLE_PSK
+ case GNUTLS_CRD_PSK:
+ ret = unpack_psk_auth_info(session, packed_session);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+ break;
+#endif
+#ifdef ENABLE_ANON
case GNUTLS_CRD_ANON:
- pack_size += session->key->auth_info_size;
+ ret = unpack_anon_auth_info(session, packed_session);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
break;
- case GNUTLS_CRD_CERTIFICATE:{
- cert_auth_info_t info = _gnutls_get_auth_info(session);
-
- pack_size += _gnutls_pack_certificate_auth_info_size(info);
+#endif
+ case GNUTLS_CRD_CERTIFICATE:
+ ret = unpack_certificate_auth_info(session, packed_session);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
}
break;
+ default:
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+
}
/* Auth_info structures copied. Now copy security_parameters_st.
+ * packed_session must have allocated space for the security parameters.
*/
- pack_size += sizeof(security_parameters_st) + sizeof(uint32);
+ ret = unpack_security_parameters(session, packed_session);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
- return pack_size;
+ return 0;
}
-/* Load session data from a buffer.
+
+/* Format:
+ * 1 byte the credentials type
+ * 4 bytes the size of the whole structure
+ * DH stuff
+ * 2 bytes the size of secret key in bits
+ * 4 bytes the size of the prime
+ * x bytes the prime
+ * 4 bytes the size of the generator
+ * x bytes the generator
+ * 4 bytes the size of the public key
+ * x bytes the public key
+ * RSA stuff
+ * 4 bytes the size of the modulus
+ * x bytes the modulus
+ * 4 bytes the size of the exponent
+ * x bytes the exponent
+ * CERTIFICATES
+ * 4 bytes the length of the certificate list
+ * 4 bytes the size of first certificate
+ * x bytes the certificate
+ * and so on...
*/
-int _gnutls_session_unpack(gnutls_session_t session,
- const gnutls_datum_t * packed_session)
+static
+int pack_certificate_auth_info(gnutls_session_t session,
+ gnutls_datum_t * packed_session)
{
- uint32 pack_size;
- int ret;
- time_t timestamp = time(0);
- security_parameters_st sp;
+ unsigned int pos, i;
+ int cert_size, pack_size;
+ cert_auth_info_t info = _gnutls_get_auth_info(session);
- if (packed_session == NULL || packed_session->size == 0) {
+
+ if (info == NULL && session->key->auth_info_size != 0) {
gnutls_assert();
- return GNUTLS_E_INTERNAL_ERROR;
+ return GNUTLS_E_INVALID_REQUEST;
}
- if (session->key->auth_info != NULL) {
- _gnutls_free_auth_info(session);
+ if (info) {
+ for (i = 0; i < info->ncerts; i++)
+ cert_size += info->raw_certificate_list[i].size;
+
+ pack_size = 2 + 4 * 3 + 4 * 2 + info->dh.prime.size +
+ info->dh.generator.size + info->dh.public_key.size +
+ info->rsa_export.modulus.size +
+ info->rsa_export.exponent.size + cert_size;
+ } else
+ pack_size = 0;
+
+ packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof(uint32);
+
+ /* calculate the size and allocate the data.
+ */
+ packed_session->data = gnutls_malloc(packed_session->size + MAX_SEC_PARAMS);
+
+ if (packed_session->data == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
}
- switch (packed_session->data[0]) {
-#ifdef ENABLE_SRP
- case GNUTLS_CRD_SRP:{
+ packed_session->data[0] = GNUTLS_CRD_CERTIFICATE;
+ _gnutls_write_uint32(pack_size,
+ &packed_session->data[PACK_HEADER_SIZE]);
+ pos += pack_size + PACK_HEADER_SIZE;
+
- pack_size =
- _gnutls_read_uint32(&packed_session->
- data[PACK_HEADER_SIZE]);
+ if (pack_size > 0) {
- if (pack_size == 0)
- break;
- if (pack_size != sizeof(srp_server_auth_info_st)) {
- gnutls_assert();
- return GNUTLS_E_DB_ERROR;
- }
+ _gnutls_write_uint16(info->dh.secret_bits,
+ &packed_session->data[pos]);
+ pos += 2;
- session->key->auth_info = gnutls_malloc(pack_size);
+ _gnutls_write_datum32(&packed_session->data[pos], info->dh.prime);
+ pos += 4 + info->dh.prime.size;
+ _gnutls_write_datum32(&packed_session->data[pos],
+ info->dh.generator);
+ pos += 4 + info->dh.generator.size;
+ _gnutls_write_datum32(&packed_session->data[pos],
+ info->dh.public_key);
+ pos += 4 + info->dh.public_key.size;
- if (session->key->auth_info == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
- session->key->auth_info_size = sizeof(srp_server_auth_info_st);
+ _gnutls_write_datum32(&packed_session->data[pos],
+ info->rsa_export.modulus);
+ pos += 4 + info->rsa_export.modulus.size;
+ _gnutls_write_datum32(&packed_session->data[pos],
+ info->rsa_export.exponent);
+ pos += 4 + info->rsa_export.exponent.size;
+ _gnutls_write_uint32(info->ncerts, &packed_session->data[pos]);
+ pos += 4;
- memcpy(session->key->auth_info,
- &packed_session->data[PACK_HEADER_SIZE +
- sizeof(uint32)], pack_size);
+ for (i = 0; i < info->ncerts; i++) {
+ _gnutls_write_uint32(info->raw_certificate_list[i].size,
+ &packed_session->data[pos]);
+ pos += sizeof(uint32);
+
+ memcpy(&packed_session->data[pos],
+ info->raw_certificate_list[i].data,
+ info->raw_certificate_list[i].size);
+ pos += info->raw_certificate_list[i].size;
}
- break;
-#endif
- case GNUTLS_CRD_ANON:{
- anon_auth_info_t info;
+ }
- pack_size =
- _gnutls_read_uint32(&packed_session->
- data[PACK_HEADER_SIZE]);
+ return 0;
+}
- if (pack_size == 0)
- break;
- if (pack_size != sizeof(anon_client_auth_info_st)) {
- gnutls_assert();
- return GNUTLS_E_DB_ERROR;
- }
+/* Upack certificate info.
+ */
+static int unpack_certificate_auth_info(gnutls_session_t session,
+ const gnutls_datum_t *
+ packed_session)
+{
+ int pos, size, ret;
+ unsigned int i, j;
+ size_t pack_size;
+ cert_auth_info_t info;
- session->key->auth_info = gnutls_malloc(pack_size);
+ if (packed_session->data[0] != GNUTLS_CRD_CERTIFICATE) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
- if (session->key->auth_info == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
- session->key->auth_info_size = pack_size;
+ pack_size =
+ _gnutls_read_uint32(&packed_session->data[PACK_HEADER_SIZE]);
+ pos += PACK_HEADER_SIZE + 4;
- memcpy(session->key->auth_info,
- &packed_session->data[PACK_HEADER_SIZE +
- sizeof(uint32)], pack_size);
+ if (pack_size == 0)
+ return 0; /* nothing to be done */
- /* Delete the DH parameters. (this might need to be moved to a function)
- */
- info = session->key->auth_info;
- memset(&info->dh, 0, sizeof(dh_info_st));
- }
- break;
- case GNUTLS_CRD_CERTIFICATE:{
- pack_size =
- _gnutls_read_uint32(&packed_session->
- data[PACK_HEADER_SIZE]);
-
- if (pack_size == 0) {
- session->key->auth_info = NULL;
- session->key->auth_info_size = 0;
- break;
- }
- if (pack_size < sizeof(cert_auth_info_st)) {
- gnutls_assert();
- return GNUTLS_E_DB_ERROR;
- }
-
- session->key->auth_info =
- gnutls_malloc(sizeof(cert_auth_info_st));
-
- if (session->key->auth_info == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
- session->key->auth_info_size = sizeof(cert_auth_info_st);
-
- ret =
- _gnutls_unpack_certificate_auth_info(session->
- key->
- auth_info,
- packed_session);
- if (ret < 0) {
- gnutls_assert();
- return ret;
- }
+ /* a simple check for integrity */
+ if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
- }
- break;
- default:
+ /* client and server have the same auth_info here
+ */
+ ret =
+ _gnutls_auth_info_set(session, GNUTLS_CRD_CERTIFICATE,
+ sizeof(cert_auth_info_st), 1);
+ if (ret < 0) {
gnutls_assert();
- return GNUTLS_E_INTERNAL_ERROR;
+ return ret;
+ }
+ info = _gnutls_get_auth_info(session);
+ if (info == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
}
- session->key->auth_info_type = packed_session->data[0];
+ info->dh.secret_bits = _gnutls_read_uint16(&packed_session->data[pos]);
+ pos += 2;
- /* Auth_info structures copied. Now copy security_parameters_st.
- */
+ size = _gnutls_read_uint32(&packed_session->data[pos]);
+ pos += 4;
ret =
- _gnutls_read_uint32(&packed_session->
- data[PACK_HEADER_SIZE + sizeof(uint32) +
- pack_size]);
+ _gnutls_set_datum(&info->dh.prime, &packed_session->data[pos],
+ size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+ pos += size;
- if (ret != sizeof(security_parameters_st)) {
+ size = _gnutls_read_uint32(&packed_session->data[pos]);
+ pos += 4;
+ ret =
+ _gnutls_set_datum(&info->dh.generator, &packed_session->data[pos],
+ size);
+ if (ret < 0) {
gnutls_assert();
- return GNUTLS_E_DB_ERROR;
+ goto error;
}
- memcpy(&sp, &packed_session->data[PACK_HEADER_SIZE +
- 2 * sizeof(uint32) + pack_size],
- sizeof(security_parameters_st));
+ pos += size;
- if (timestamp - sp.timestamp <= session->internals.expire_time
- && sp.timestamp <= timestamp) {
+ size = _gnutls_read_uint32(&packed_session->data[pos]);
+ pos += 4;
+ ret =
+ _gnutls_set_datum(&info->dh.public_key, &packed_session->data[pos],
+ size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+ pos += size;
- memcpy(&session->internals.resumed_security_parameters, &sp,
- sizeof(security_parameters_st));
- } else {
- _gnutls_free_auth_info(session);
+ size = _gnutls_read_uint32(&packed_session->data[pos]);
+ pos += 4;
+ ret =
+ _gnutls_set_datum(&info->rsa_export.modulus,
+ &packed_session->data[pos], size);
+ if (ret < 0) {
gnutls_assert();
- return GNUTLS_E_EXPIRED;
+ goto error;
+ }
+ pos += size;
+
+ size = _gnutls_read_uint32(&packed_session->data[pos]);
+ pos += 4;
+ ret =
+ _gnutls_set_datum(&info->rsa_export.exponent,
+ &packed_session->data[pos], size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+ pos += size;
+
+ info->ncerts = _gnutls_read_uint32(&packed_session->data[pos]);
+ pos += 4;
+
+ for (i = 0; i < info->ncerts; i++) {
+ size = _gnutls_read_uint32(&packed_session->data[pos]);
+ pos += sizeof(uint32);
+
+ ret =
+ _gnutls_set_datum(&info->raw_certificate_list[i],
+ &packed_session->data[pos], size);
+ pos += size;
+
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
}
return 0;
+
+ error:
+ _gnutls_free_datum(&info->dh.prime);
+ _gnutls_free_datum(&info->dh.generator);
+ _gnutls_free_datum(&info->dh.public_key);
+
+ _gnutls_free_datum(&info->rsa_export.modulus);
+ _gnutls_free_datum(&info->rsa_export.exponent);
+
+ for (j = 0; j < i; j++)
+ _gnutls_free_datum(&info->raw_certificate_list[j]);
+
+ gnutls_free(info->raw_certificate_list);
+
+ return ret;
+
}
-int _gnutls_pack_certificate_auth_info(cert_auth_info_t info,
- gnutls_datum_t * packed_session)
+#ifdef ENABLE_SRP
+/* Packs the SRP session authentication data.
+ */
+
+/* Format:
+ * 1 byte the credentials type
+ * 4 bytes the size of the SRP username (x)
+ * x bytes the SRP username
+ */
+static int pack_srp_auth_info(gnutls_session_t session,
+ gnutls_datum * packed_session)
{
- unsigned int pos, i;
- int info_size;
+ srp_server_auth_info_t info = _gnutls_get_auth_info(session);
+ int pack_size;
- packed_session->size = _gnutls_pack_certificate_auth_info_size(info);
+ if (info == NULL && session->key->auth_info_size != 0) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
- if (info == NULL)
- info_size = 0;
+ if (info && info->username)
+ pack_size = strlen(info->username) + 1; /* include the terminating null */
else
- info_size = sizeof(cert_auth_info_st);
+ pack_size = 0;
- packed_session->data[0] = GNUTLS_CRD_CERTIFICATE;
- _gnutls_write_uint32(packed_session->size - PACK_HEADER_SIZE -
- sizeof(uint32),
+ packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof(uint32);
+
+ /* calculate the size and allocate the data.
+ */
+ packed_session->data = gnutls_malloc(packed_session->size + MAX_SEC_PARAMS);
+
+ if (packed_session->data == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ packed_session->data[0] = GNUTLS_CRD_SRP;
+ _gnutls_write_uint32(pack_size,
&packed_session->data[PACK_HEADER_SIZE]);
- if (info != NULL) {
+ if (pack_size > 0)
memcpy(&packed_session->data[PACK_HEADER_SIZE + sizeof(uint32)],
- info, sizeof(cert_auth_info_st));
+ info->username, pack_size + 1);
+
+ return 0;
+}
+
+
+static int unpack_srp_auth_info(gnutls_session_t session,
+ const gnutls_datum * packed_session)
+{
+ size_t username_size;
+ int ret;
+ srp_server_auth_info_t info;
+
+ if (packed_session->data[0] != GNUTLS_CRD_SRP) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
}
- pos = PACK_HEADER_SIZE + sizeof(uint32) + info_size;
+ username_size =
+ _gnutls_read_uint32(&packed_session->data[PACK_HEADER_SIZE]);
- if (info != NULL) {
- for (i = 0; i < info->ncerts; i++) {
- _gnutls_write_uint32(info->raw_certificate_list[i].size,
- &packed_session->data[pos]);
- pos += sizeof(uint32);
+ if (username_size == 0)
+ return 0; /* nothing to be done */
- memcpy(&packed_session->data[pos],
- info->raw_certificate_list[i].data,
- info->raw_certificate_list[i].size);
- pos += info->raw_certificate_list[i].size;
- }
+ /* a simple check for integrity */
+ if (username_size + 4 + PACK_HEADER_SIZE > packed_session->size) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ ret =
+ _gnutls_auth_info_set(session, GNUTLS_CRD_SRP,
+ sizeof(srp_server_auth_info_st), 1);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ info = _gnutls_get_auth_info(session);
+ if (info == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
}
+ memcpy(info->username,
+ &packed_session->data[PACK_HEADER_SIZE + sizeof(uint32)],
+ username_size);
+
return 0;
}
+#endif
+
+
+#ifdef ENABLE_ANON
+/* Packs the ANON session authentication data.
+ */
-static int _gnutls_pack_certificate_auth_info_size(cert_auth_info_t info)
+/* Format:
+ * 1 byte the credentials type
+ * 4 bytes the size of the whole structure
+ * 2 bytes the size of secret key in bits
+ * 4 bytes the size of the prime
+ * x bytes the prime
+ * 4 bytes the size of the generator
+ * x bytes the generator
+ * 4 bytes the size of the public key
+ * x bytes the public key
+ */
+static int pack_anon_auth_info(gnutls_session_t session,
+ gnutls_datum * packed_session)
{
- uint32 pack_size = sizeof(cert_auth_info_st);
- unsigned int i;
+ anon_auth_info_t info = _gnutls_get_auth_info(session);
+ int pos;
+ size_t pack_size;
- if (info == NULL)
- return sizeof(uint32) + PACK_HEADER_SIZE;
+ if (info == NULL && session->key->auth_info_size != 0) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ if (info)
+ pack_size = 2 + 4 * 3 + info->dh.prime.size +
+ info->dh.generator.size + info->dh.public_key.size;
+ else
+ pack_size = 0;
+
+ packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof(uint32);
+
+ /* calculate the size and allocate the data.
+ */
+ packed_session->data = gnutls_malloc(packed_session->size + MAX_SEC_PARAMS);
+
+ if (packed_session->data == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ packed_session->data[0] = GNUTLS_CRD_ANON;
+ _gnutls_write_uint32(pack_size,
+ &packed_session->data[PACK_HEADER_SIZE]);
+ pos += pack_size + PACK_HEADER_SIZE;
+
+ if (pack_size > 0) {
+ _gnutls_write_uint16(info->dh.secret_bits,
+ &packed_session->data[pos]);
+ pos += 2;
+
+ _gnutls_write_datum32(&packed_session->data[pos], info->dh.prime);
+ pos += 4 + info->dh.prime.size;
+ _gnutls_write_datum32(&packed_session->data[pos],
+ info->dh.generator);
+ pos += 4 + info->dh.generator.size;
+ _gnutls_write_datum32(&packed_session->data[pos],
+ info->dh.public_key);
+ pos += 4 + info->dh.public_key.size;
- for (i = 0; i < info->ncerts; i++) {
- pack_size += sizeof(uint32) + info->raw_certificate_list[i].size;
}
- return pack_size + PACK_HEADER_SIZE + sizeof(uint32);
+ return 0;
}
-/* Load session data.
+
+static int unpack_anon_auth_info(gnutls_session_t session,
+ const gnutls_datum * packed_session)
+{
+ size_t pack_size;
+ int pos, size, ret;
+ anon_auth_info_t info;
+
+ if (packed_session->data[0] != GNUTLS_CRD_ANON) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ pack_size =
+ _gnutls_read_uint32(&packed_session->data[PACK_HEADER_SIZE]);
+ pos += PACK_HEADER_SIZE + 4;
+
+
+ if (pack_size == 0)
+ return 0; /* nothing to be done */
+
+ /* a simple check for integrity */
+ if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ /* client and serer have the same auth_info here
+ */
+ ret =
+ _gnutls_auth_info_set(session, GNUTLS_CRD_ANON,
+ sizeof(anon_client_auth_info_st), 1);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ info = _gnutls_get_auth_info(session);
+ if (info == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ info->dh.secret_bits = _gnutls_read_uint16(&packed_session->data[pos]);
+ pos += 2;
+
+ size = _gnutls_read_uint32(&packed_session->data[pos]);
+ pos += 4;
+ ret =
+ _gnutls_set_datum(&info->dh.prime, &packed_session->data[pos],
+ size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+ pos += size;
+
+ size = _gnutls_read_uint32(&packed_session->data[pos]);
+ pos += 4;
+ ret =
+ _gnutls_set_datum(&info->dh.generator, &packed_session->data[pos],
+ size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+ pos += size;
+
+ size = _gnutls_read_uint32(&packed_session->data[pos]);
+ pos += 4;
+ ret =
+ _gnutls_set_datum(&info->dh.public_key, &packed_session->data[pos],
+ size);
+ if (ret < 0) {
+ gnutls_assert();
+ goto error;
+ }
+ pos += size;
+
+ return 0;
+
+ error:
+ _gnutls_free_datum(&info->dh.prime);
+ _gnutls_free_datum(&info->dh.generator);
+ _gnutls_free_datum(&info->dh.public_key);
+ return ret;
+}
+#endif /* ANON */
+
+#ifdef ENABLE_PSK
+/* Packs the PSK session authentication data.
+ */
+
+/* Format:
+ * 1 byte the credentials type
+ * 4 bytes the size of the PSK username (x)
+ * x bytes the PSK username
*/
-int _gnutls_unpack_certificate_auth_info(cert_auth_info_t info,
- const gnutls_datum_t *
- packed_session)
+static int pack_psk_auth_info(gnutls_session_t session,
+ gnutls_datum * packed_session)
{
- unsigned int i, j, pos;
+ psk_server_auth_info_t info = _gnutls_get_auth_info(session);
+ int pack_size;
+
+ if (info == NULL && session->key->auth_info_size != 0) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ if (info && info->username)
+ pack_size = strlen(info->username) + 1; /* include the terminating null */
+ else
+ pack_size = 0;
+
+ packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof(uint32);
+
+ /* calculate the size and allocate the data.
+ */
+ packed_session->data = gnutls_malloc(packed_session->size + MAX_SEC_PARAMS);
+
+ if (packed_session->data == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+
+ packed_session->data[0] = GNUTLS_CRD_PSK;
+ _gnutls_write_uint32(pack_size,
+ &packed_session->data[PACK_HEADER_SIZE]);
+
+ if (pack_size > 0)
+ memcpy(&packed_session->data[PACK_HEADER_SIZE + sizeof(uint32)],
+ info->username, pack_size + 1);
+
+ return 0;
+}
+
+
+static int unpack_psk_auth_info(gnutls_session_t session,
+ const gnutls_datum * packed_session)
+{
+ size_t username_size;
int ret;
- uint32 size;
+ psk_server_auth_info_t info;
- memcpy(info,
+ if (packed_session->data[0] != GNUTLS_CRD_PSK) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ username_size =
+ _gnutls_read_uint32(&packed_session->data[PACK_HEADER_SIZE]);
+
+ if (username_size == 0)
+ return 0; /* nothing to be done */
+
+ /* a simple check for integrity */
+ if (username_size + 4 + PACK_HEADER_SIZE > packed_session->size) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ ret =
+ _gnutls_auth_info_set(session, GNUTLS_CRD_PSK,
+ sizeof(psk_server_auth_info_st), 1);
+ if (ret < 0) {
+ gnutls_assert();
+ return ret;
+ }
+
+ info = _gnutls_get_auth_info(session);
+ if (info == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_INTERNAL_ERROR;
+ }
+
+ memcpy(info->username,
&packed_session->data[PACK_HEADER_SIZE + sizeof(uint32)],
- sizeof(cert_auth_info_st));
+ username_size);
- /* Delete the dh_info_st and rsa_info_st fields.
- */
- memset(&info->dh, 0, sizeof(dh_info_st));
- memset(&info->rsa_export, 0, sizeof(rsa_info_st));
-
- pos = PACK_HEADER_SIZE + sizeof(uint32) + sizeof(cert_auth_info_st);
- if (info->ncerts > 0) {
- info->raw_certificate_list =
- gnutls_calloc(1, info->ncerts * sizeof(gnutls_datum_t));
- if (info->raw_certificate_list == NULL) {
- gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
- }
+ return 0;
+}
+#endif
- for (i = 0; i < info->ncerts; i++) {
- size = _gnutls_read_uint32(&packed_session->data[pos]);
- pos += sizeof(uint32);
- ret =
- _gnutls_set_datum(&info->raw_certificate_list[i],
- &packed_session->data[pos], size);
- pos += size;
+/* Packs the security parameters.
+ */
- if (ret < 0) {
- gnutls_assert();
- goto clear;
- }
- }
+/* Format:
+ * 4 bytes the total security data size
+ * 1 byte the entity type (client/server)
+ * 1 byte the key exchange algorithm used
+ * 1 byte the read cipher algorithm
+ * 1 byte the read mac algorithm
+ * 1 byte the read compression algorithm
+ *
+ * 1 byte the write cipher algorithm
+ * 1 byte the write mac algorithm
+ * 1 byte the write compression algorithm
+ *
+ * 1 byte the certificate type
+ * 1 byte the protocol version
+ *
+ * 2 bytes the cipher suite
+ *
+ * 48 bytes the master secret
+ *
+ * 32 bytes the client random
+ * 32 bytes the server random
+ *
+ * 1 byte the session ID size
+ * x bytes the session ID (32 bytes max)
+ *
+ * 4 bytes a timestamp
+ * -------------------
+ * MAX: 165 bytes
+ *
+ * EXTENSIONS:
+ * 2 bytes the record send size
+ * 2 bytes the record recv size
+ *
+ * 1 byte the SRP username size
+ * x bytes the SRP username (MAX_SRP_USERNAME)
+ *
+ * 2 bytes the number of server name extensions (up to MAX_SERVER_NAME_EXTENSIONS)
+ * 1 byte the first name type
+ * 2 bytes the size of the first name
+ * x bytes the first name (MAX_SERVER_NAME_SIZE)
+ * and so on...
+ *
+ * --------------------
+ * MAX: 7+MAX_SRP_USERNAME+MAX_SERVER_NAME_EXTENSIONS*(3+MAX_SERVER_NAME_SIZE)
+ */
+static int pack_security_parameters(gnutls_session_t session,
+ gnutls_datum * packed_session)
+{
+ int pos;
+ size_t len, init, i;
+
+ /* move after the auth info stuff.
+ */
+ init = _gnutls_read_uint32( &packed_session->data[PACK_HEADER_SIZE]) + 4 + PACK_HEADER_SIZE;
+
+ pos = init + 4; /* make some space to write later the size */
+
+ packed_session->data[pos++] = session->security_parameters.entity;
+ packed_session->data[pos++] = session->security_parameters.kx_algorithm;
+ packed_session->data[pos++] = session->security_parameters.read_bulk_cipher_algorithm;
+ packed_session->data[pos++] = session->security_parameters.read_mac_algorithm;
+ packed_session->data[pos++] = session->security_parameters.read_compression_algorithm;
+ packed_session->data[pos++] = session->security_parameters.write_bulk_cipher_algorithm;
+ packed_session->data[pos++] = session->security_parameters.write_mac_algorithm;
+ packed_session->data[pos++] = session->security_parameters.write_compression_algorithm;
+ packed_session->data[pos++] = session->security_parameters.current_cipher_suite.suite[0];
+ packed_session->data[pos++] = session->security_parameters.current_cipher_suite.suite[1];
+
+ packed_session->data[pos++] = session->security_parameters.cert_type;
+ packed_session->data[pos++] = session->security_parameters.version;
+
+ memcpy(&packed_session->data[pos], session->security_parameters.master_secret,
+ TLS_MASTER_SIZE);
+ pos += TLS_MASTER_SIZE;
+
+ memcpy(&packed_session->data[pos], session->security_parameters.client_random,
+ TLS_RANDOM_SIZE);
+ pos += TLS_RANDOM_SIZE;
+ memcpy(&packed_session->data[pos], session->security_parameters.server_random,
+ TLS_RANDOM_SIZE);
+ pos += TLS_RANDOM_SIZE;
+
+ packed_session->data[pos++] = session->security_parameters.session_id_size;
+ memcpy(&packed_session->data[pos], session->security_parameters.session_id,
+ session->security_parameters.session_id_size);
+ pos += session->security_parameters.session_id_size;
+
+ _gnutls_write_uint32(session->security_parameters.timestamp,
+ &packed_session->data[pos]);
+ pos += 4;
+
+ /* Extensions */
+ _gnutls_write_uint16(session->security_parameters.max_record_send_size,
+ &packed_session->data[pos]);
+ pos += 2;
+
+ _gnutls_write_uint16(session->security_parameters.max_record_recv_size,
+ &packed_session->data[pos]);
+ pos += 2;
+
+ /* SRP */
+ len = strlen((char*)session->security_parameters.extensions.srp_username);
+ packed_session->data[pos++] = len;
+ memcpy(&packed_session->data[pos], session->security_parameters.extensions.srp_username,
+ len);
+ pos += len;
+
+ _gnutls_write_uint16(session->security_parameters.extensions.server_names_size,
+ &packed_session->data[pos]);
+ pos += 2;
+
+ for(i=0;i<session->security_parameters.extensions.server_names_size;i++) {
+ packed_session->data[pos++] = session->security_parameters.extensions.server_names[i].type;
+ _gnutls_write_uint16(session->security_parameters.extensions.server_names[i].name_length,
+ &packed_session->data[pos]);
+ pos += 2;
+
+ memcpy(&packed_session->data[pos], session->security_parameters.extensions.
+ server_names[i].name, session->security_parameters.extensions.server_names[i].name_length);
+ pos += session->security_parameters.extensions.server_names[i].name_length;
}
+
+ /* write the total size */
+ _gnutls_write_uint32(pos - init - 4,
+ &packed_session->data[init]);
+ packed_session->size += pos - init;
+
return 0;
+}
- clear:
- for (j = 0; j < i; j++)
- _gnutls_free_datum(&info->raw_certificate_list[j]);
- gnutls_free(info->raw_certificate_list);
- return GNUTLS_E_MEMORY_ERROR;
+static int unpack_security_parameters(gnutls_session_t session,
+ const gnutls_datum * packed_session)
+{
+ size_t pack_size, init, i;
+ int pos, len;
+ time_t timestamp = time(0);
+
+
+ /* skip the auth info stuff */
+ init = _gnutls_read_uint32( &packed_session->data[PACK_HEADER_SIZE]) + 4 + PACK_HEADER_SIZE;
+ pos = init;
+
+ pack_size =
+ _gnutls_read_uint32(&packed_session->data[pos]);
+ pos += 4;
+
+
+ if (pack_size == 0)
+ return GNUTLS_E_INVALID_REQUEST;
+
+ /* a simple check for integrity */
+ if (pack_size > MAX_SEC_PARAMS) {
+ gnutls_assert();
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ session->internals.resumed_security_parameters.entity = packed_session->data[pos++];
+ session->internals.resumed_security_parameters.kx_algorithm = packed_session->data[pos++];
+ session->internals.resumed_security_parameters.read_bulk_cipher_algorithm = packed_session->data[pos++];
+ session->internals.resumed_security_parameters.read_mac_algorithm = packed_session->data[pos++];
+ session->internals.resumed_security_parameters.read_compression_algorithm = packed_session->data[pos++];
+ session->internals.resumed_security_parameters.write_bulk_cipher_algorithm = packed_session->data[pos++];
+ session->internals.resumed_security_parameters.write_mac_algorithm = packed_session->data[pos++];
+ session->internals.resumed_security_parameters.write_compression_algorithm = packed_session->data[pos++];
+ session->internals.resumed_security_parameters.current_cipher_suite.suite[0] = packed_session->data[pos++];
+ session->internals.resumed_security_parameters.current_cipher_suite.suite[1] = packed_session->data[pos++];
+
+ session->internals.resumed_security_parameters.cert_type = packed_session->data[pos++];
+ session->internals.resumed_security_parameters.version = packed_session->data[pos++];
+
+ memcpy(session->internals.resumed_security_parameters.master_secret,&packed_session->data[pos],
+ TLS_MASTER_SIZE);
+ pos += TLS_MASTER_SIZE;
+
+ memcpy(session->internals.resumed_security_parameters.client_random,&packed_session->data[pos],
+ TLS_RANDOM_SIZE);
+ pos += TLS_RANDOM_SIZE;
+ memcpy(session->internals.resumed_security_parameters.server_random,&packed_session->data[pos],
+ TLS_RANDOM_SIZE);
+ pos += TLS_RANDOM_SIZE;
+
+ session->internals.resumed_security_parameters.session_id_size = packed_session->data[pos++];
+ memcpy( session->internals.resumed_security_parameters.session_id,&packed_session->data[pos],
+ session->internals.resumed_security_parameters.session_id_size);
+ pos += session->internals.resumed_security_parameters.session_id_size;
+
+ session->internals.resumed_security_parameters.timestamp = _gnutls_read_uint32( &packed_session->data[pos]);
+ pos += 4;
+
+ if (timestamp - session->internals.resumed_security_parameters.timestamp > session->internals.expire_time
+ || session->internals.resumed_security_parameters.timestamp > timestamp) {
+ gnutls_assert();
+ return GNUTLS_E_EXPIRED;
+ }
+
+ /* Extensions */
+ session->internals.resumed_security_parameters.max_record_send_size = _gnutls_read_uint16(
+ &packed_session->data[pos]);
+ pos += 2;
+
+ session->internals.resumed_security_parameters.max_record_recv_size = _gnutls_read_uint16(
+ &packed_session->data[pos]);
+ pos += 2;
+
+
+ /* SRP */
+ len = packed_session->data[pos++]; /* srp username length */
+ memcpy(session->internals.resumed_security_parameters.extensions.srp_username,&packed_session->data[pos],
+ len);
+ session->internals.resumed_security_parameters.extensions.srp_username[len] = 0;
+ pos += len;
+
+ session->internals.resumed_security_parameters.extensions.server_names_size =
+ _gnutls_read_uint16(&packed_session->data[pos]);
+ pos += 2;
+ for(i=0;i<session->internals.resumed_security_parameters.extensions.server_names_size;i++) {
+ session->internals.resumed_security_parameters.extensions.server_names[i].type = packed_session->data[pos++];
+ session->internals.resumed_security_parameters.extensions.server_names[i].name_length =
+ _gnutls_read_uint16(&packed_session->data[pos]);
+ pos += 2;
+
+ memcpy(session->internals.resumed_security_parameters.extensions.
+ server_names[i].name, &packed_session->data[pos], session->internals.resumed_security_parameters.extensions.server_names[i].name_length);
+ pos += session->internals.resumed_security_parameters.extensions.server_names[i].name_length;
+ }
+ return 0;
}
diff --git a/lib/gnutls_session_pack.h b/lib/gnutls_session_pack.h
index 4265ab27a0..d3beb821fa 100644
--- a/lib/gnutls_session_pack.h
+++ b/lib/gnutls_session_pack.h
@@ -26,4 +26,3 @@ int _gnutls_session_pack(gnutls_session_t session,
gnutls_datum_t * packed_session);
int _gnutls_session_unpack(gnutls_session_t session,
const gnutls_datum_t * packed_session);
-uint _gnutls_session_size(gnutls_session_t session);
diff --git a/lib/gnutls_srp.c b/lib/gnutls_srp.c
index 629c860016..5e73b2eabc 100644
--- a/lib/gnutls_srp.c
+++ b/lib/gnutls_srp.c
@@ -33,6 +33,8 @@
#include <auth_srp_passwd.h>
#include <gnutls_mpi.h>
#include <gnutls_num.h>
+#include <gnutls_helper.h>
+
#include "debug.h"
@@ -478,18 +480,6 @@ int gnutls_srp_allocate_server_credentials(gnutls_srp_server_credentials_t
return 0;
}
-inline static int file_exists(const char *file)
-{
- FILE *fd;
-
- fd = fopen(file, "r");
- if (fd == NULL)
- return -1;
-
- fclose(fd);
- return 0;
-}
-
/**
* gnutls_srp_set_server_credentials_file - Used to set the password files, in a gnutls_srp_server_credentials_t structure
* @res: is an #gnutls_srp_server_credentials_t structure.
@@ -513,12 +503,12 @@ int gnutls_srp_set_server_credentials_file(gnutls_srp_server_credentials_t
}
/* Check if the files can be opened */
- if (file_exists(password_file) != 0) {
+ if (_gnutls_file_exists(password_file) != 0) {
gnutls_assert();
return GNUTLS_E_FILE_ERROR;
}
- if (file_exists(password_conf_file) != 0) {
+ if (_gnutls_file_exists(password_conf_file) != 0) {
gnutls_assert();
return GNUTLS_E_FILE_ERROR;
}
diff --git a/lib/gnutls_str.c b/lib/gnutls_str.c
index a4c2ebccca..8edd498c25 100644
--- a/lib/gnutls_str.c
+++ b/lib/gnutls_str.c
@@ -214,3 +214,36 @@ char *_gnutls_bin2hex(const void *_old, size_t oldlen,
return buffer;
}
+
+/* just a hex2bin function.
+ */
+int _gnutls_hex2bin(const opaque* hex_data, int hex_size, opaque * bin_data,
+ size_t * bin_size)
+{
+int i, j;
+opaque hex2_data[3];
+unsigned long val;
+
+ /* FIXME: we don't handle whitespace.
+ */
+ hex_size /= 2;
+
+ if (*bin_size < (size_t)hex_size) {
+ gnutls_assert();
+ return GNUTLS_E_SHORT_MEMORY_BUFFER;
+ }
+
+ for (i=j=0; j < hex_size;i+=2,j++) {
+ hex2_data[0] = hex_data[i];
+ hex2_data[1] = hex_data[i+1];
+ hex2_data[2] = 0;
+ val = strtoul( (char*)hex2_data, NULL, 16);
+ if (val == ULONG_MAX) {
+ gnutls_assert();
+ return GNUTLS_E_SRP_PWD_PARSING_ERROR;
+ }
+ bin_data[j] = val;
+ }
+
+ return 0;
+}
diff --git a/lib/gnutls_str.h b/lib/gnutls_str.h
index 052be7af2d..951a878bff 100644
--- a/lib/gnutls_str.h
+++ b/lib/gnutls_str.h
@@ -57,5 +57,7 @@ int _gnutls_string_append_data(gnutls_string *, const void *data,
char *_gnutls_bin2hex(const void *old, size_t oldlen, char *buffer,
size_t buffer_size);
+int _gnutls_hex2bin(const opaque* hex_data, int hex_size, opaque * bin_data,
+ size_t * bin_size);
#endif
diff --git a/lib/libgnutls.vers b/lib/libgnutls.vers
index 39bf6174b5..215511bfaf 100644
--- a/lib/libgnutls.vers
+++ b/lib/libgnutls.vers
@@ -20,7 +20,7 @@
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA 02110-1301, USA
-GNUTLS_1_2
+GNUTLS_1_3
{
global: _gnutls*; gnutls*; _E_*;
local: *;