diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2005-11-07 22:24:48 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2005-11-07 22:24:48 +0000 |
commit | ad4ed44c65e753e6d3a00104c049dd81826ccbf3 (patch) | |
tree | c7511d77a37287b567c2f31f3e5dfa9af956d635 /lib | |
parent | 31168918162ee35315f025a9d8aeec67a81c7a7c (diff) | |
download | gnutls-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.am | 13 | ||||
-rw-r--r-- | lib/auth_psk.c | 168 | ||||
-rw-r--r-- | lib/auth_psk.h | 56 | ||||
-rw-r--r-- | lib/auth_psk_passwd.c | 363 | ||||
-rw-r--r-- | lib/auth_psk_passwd.h | 37 | ||||
-rw-r--r-- | lib/auth_srp.h | 2 | ||||
-rw-r--r-- | lib/auth_srp_sb64.c | 4 | ||||
-rw-r--r-- | lib/ext_srp.c | 4 | ||||
-rw-r--r-- | lib/gnutls_algorithms.c | 28 | ||||
-rw-r--r-- | lib/gnutls_compress_int.c | 9 | ||||
-rw-r--r-- | lib/gnutls_db.c | 19 | ||||
-rw-r--r-- | lib/gnutls_helper.c | 38 | ||||
-rw-r--r-- | lib/gnutls_helper.h | 1 | ||||
-rw-r--r-- | lib/gnutls_int.h | 3 | ||||
-rw-r--r-- | lib/gnutls_psk.c | 700 | ||||
-rw-r--r-- | lib/gnutls_session.c | 51 | ||||
-rw-r--r-- | lib/gnutls_session_pack.c | 1137 | ||||
-rw-r--r-- | lib/gnutls_session_pack.h | 1 | ||||
-rw-r--r-- | lib/gnutls_srp.c | 18 | ||||
-rw-r--r-- | lib/gnutls_str.c | 33 | ||||
-rw-r--r-- | lib/gnutls_str.h | 2 | ||||
-rw-r--r-- | lib/libgnutls.vers | 2 |
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: *; |