summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/ext/pre_shared_key.c141
-rw-r--r--lib/tls13/psk_parser.c133
-rw-r--r--lib/tls13/psk_parser.h17
-rw-r--r--lib/tls13/session_ticket.c5
-rw-r--r--lib/tls13/session_ticket.h3
5 files changed, 168 insertions, 131 deletions
diff --git a/lib/ext/pre_shared_key.c b/lib/ext/pre_shared_key.c
index 3d835eef65..6ba985a829 100644
--- a/lib/ext/pre_shared_key.c
+++ b/lib/ext/pre_shared_key.c
@@ -41,7 +41,7 @@ typedef struct {
static int
compute_psk_from_ticket(const mac_entry_st *prf,
const uint8_t *rms,
- struct tls13_nst_st *ticket, gnutls_datum_t *key)
+ gnutls_datum_t *nonce, gnutls_datum_t *key)
{
int ret;
unsigned hash_size = prf->output_size;
@@ -54,7 +54,7 @@ compute_psk_from_ticket(const mac_entry_st *prf,
ret = _tls13_expand_secret2(prf,
label, strlen(label),
- ticket->ticket_nonce.data, ticket->ticket_nonce.size,
+ nonce->data, nonce->size,
rms,
hash_size,
key->data);
@@ -255,7 +255,7 @@ client_send_params(gnutls_session_t session,
rms = session->key.proto.tls13.ap_rms_original.data;
ret = compute_psk_from_ticket(prf,
rms,
- &ticket, &key);
+ &ticket.ticket_nonce, &key);
if (ret < 0) {
gnutls_assert();
goto cleanup;
@@ -362,74 +362,22 @@ server_send_params(gnutls_session_t session, gnutls_buffer_t extdata)
return 2;
}
-static int
-server_find_binder(const unsigned char **data_p, long *len_p,
- int psk_index, gnutls_datum_t *binder_recvd)
-{
- uint8_t binder_len;
- int cur_index = 0, binder_found = 0;
- const unsigned char *data = *data_p;
- long len = *len_p;
-
- while (len > 0) {
- binder_len = *data;
- if (binder_len == 0)
- return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
-
- DECR_LEN(len, 1);
- data++;
-
- if (cur_index == psk_index) {
- binder_recvd->data = gnutls_malloc(binder_len);
- if (!binder_recvd->data)
- return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
-
- binder_recvd->size = binder_len;
- memcpy(binder_recvd->data, data, binder_len);
-
- DECR_LEN(len, binder_len);
- data += binder_len;
-
- binder_found = 1;
- break;
- }
-
- DECR_LEN(len, binder_len);
- data += binder_len;
-
- binder_len = 0;
- cur_index++;
- }
-
- *len_p = len;
- *data_p = data;
-
- return (binder_found ? binder_len : gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS));
-}
-
static int server_recv_params(gnutls_session_t session,
const unsigned char *data, long len,
const gnutls_psk_server_credentials_t pskcred)
{
int ret;
- const mac_entry_st *prf;
+ const mac_entry_st *prf = NULL;
gnutls_datum_t full_client_hello;
- psk_ext_st *priv = NULL;
- uint16_t ttl_identities_len;
uint8_t binder_value[MAX_HASH_SIZE];
int psk_index = -1;
- gnutls_datum_t binder_recvd;
- gnutls_datum_t username, key;
- gnutls_datum_t ticket_data = { NULL, 0 }, rms = { NULL, 0 };
+ gnutls_datum_t username = { NULL, 0 }, key = { NULL, 0 };
+ gnutls_datum_t binder_recvd = { NULL, 0 };
+ gnutls_datum_t ticket_data = { NULL, 0 }, rms = { NULL, 0 }, nonce = { NULL, 0 };
gnutls_mac_algorithm_t kdf_id;
unsigned hash_size;
- struct psk_parser_st psk_parser;
+ struct psk_ext_parser_st psk_parser;
struct psk_st psk;
- struct ticket_st *ticket = NULL;
-
- memset(&binder_recvd, 0, sizeof(gnutls_datum_t));
- memset(&username, 0, sizeof(gnutls_datum_t));
- memset(&key, 0, sizeof(gnutls_datum_t));
if (pskcred) {
/* No credentials - this extension is not applicable */
@@ -442,51 +390,39 @@ static int server_recv_params(gnutls_session_t session,
ret = _gnutls_psk_pwd_find_entry(session, pskcred->hint, &key);
if (ret < 0)
return ret;
-
- if (pskcred->hint) {
- username.data = (unsigned char *) pskcred->hint;
- username.size = strlen(pskcred->hint);
-
- ret = _gnutls_psk_pwd_find_entry(session, pskcred->hint, &key);
- if (ret < 0)
- return ret;
- }
}
- ttl_identities_len = _gnutls_read_uint16(data);
- /* The client advertised no PSKs */
- if (ttl_identities_len == 0)
+ ret = _gnutls13_psk_ext_parser_init(&psk_parser, data, len);
+ if (ret == 0) {
+ /* The client advertised no PSKs */
return 0;
+ } else if (ret < 0) {
+ return gnutls_assert_val(ret);
+ }
- DECR_LEN(len, 2);
- data += 2;
-
- _gnutls13_psk_parser_init(&psk_parser, data, len, ttl_identities_len);
-
- while (_gnutls13_psk_parser_next(&psk_parser, &psk) >= 0) {
+ while (_gnutls13_psk_ext_parser_next_psk(&psk_parser, &psk) >= 0) {
/*
* First check if this is an out-of-band PSK.
* If it's not, try to decrypt it, as it might be a session ticket.
*/
- if (username.size == psk.identity.size &&
+ if (pskcred && username.size == psk.identity.size &&
safe_memcmp(username.data, psk.identity.data, psk.identity.size) == 0) {
psk_index = psk.selected_index;
+ prf = _gnutls_mac_to_entry(pskcred->tls13_binder_algo);
break;
}
- if (psk.identity.size < sizeof(struct ticket_st))
- break;
-
- ticket = (struct ticket_st *) psk.identity.data;
ticket_data.data = psk.identity.data;
ticket_data.size = psk.identity.size;
- if (_gnutls13_unpack_session_ticket(session, &ticket_data, &rms, &kdf_id) > 0) {
+ if (_gnutls13_unpack_session_ticket(session, &ticket_data, &rms, &nonce, &kdf_id) > 0) {
psk_index = psk.selected_index;
+ prf = _gnutls_mac_to_entry(kdf_id);
+ if (!prf)
+ return gnutls_assert_val(GNUTLS_E_INVALID_SESSION);
- key.data = ticket->encrypted_state;
- key.size = ticket->encrypted_state_len;
- gnutls_free(ticket->encrypted_state);
- ticket->encrypted_state = NULL;
+ ret = compute_psk_from_ticket(prf, rms.data, &nonce, &key);
+ if (ret < 0)
+ return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
session->internals.resumption_requested = 1;
@@ -494,25 +430,20 @@ static int server_recv_params(gnutls_session_t session,
}
}
- _gnutls13_psk_parser_deinit(&psk_parser, &data, (size_t *) &len);
-
/* No suitable PSK found */
if (psk_index < 0)
return 0;
- DECR_LEN(len, 2);
- data += 2;
-
- ret = server_find_binder(&data, &len,
- psk_index, &binder_recvd);
+ /* Find the binder for the chosen PSK */
+ ret = _gnutls13_psk_ext_parser_find_binder(&psk_parser, psk_index,
+ &binder_recvd);
if (ret < 0)
return gnutls_assert_val(ret);
- if (binder_recvd.size == 0)
- return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
- priv = gnutls_malloc(sizeof(psk_ext_st));
- if (!priv) {
- ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+ ret = _gnutls13_psk_ext_parser_deinit(&psk_parser,
+ &data, (size_t *) &len);
+ if (ret < 0) {
+ gnutls_assert();
goto cleanup;
}
@@ -523,15 +454,18 @@ static int server_recv_params(gnutls_session_t session,
}
/* Compute the binder value for this PSK */
- prf = _gnutls_mac_to_entry(pskcred->tls13_binder_algo);
+ if (!prf) {
+ ret = gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
+ goto cleanup;
+ }
hash_size = prf->output_size;
compute_psk_binder(GNUTLS_SERVER, prf, hash_size, hash_size, 0, 0, 0,
&key, &full_client_hello,
binder_value);
if (_gnutls_mac_get_algo_len(prf) != binder_recvd.size ||
safe_memcmp(binder_value, binder_recvd.data, binder_recvd.size)) {
- _gnutls_free_datum(&binder_recvd);
- return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
+ ret = gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
+ goto cleanup;
}
session->internals.hsk_flags |= HSK_PSK_SELECTED;
@@ -539,7 +473,6 @@ static int server_recv_params(gnutls_session_t session,
session->key.proto.tls13.psk = key.data;
session->key.proto.tls13.psk_size = key.size;
session->key.proto.tls13.psk_selected = 0;
- _gnutls_free_datum(&binder_recvd);
cleanup:
_gnutls_free_datum(&binder_recvd);
diff --git a/lib/tls13/psk_parser.c b/lib/tls13/psk_parser.c
index 33f86c6cc5..86186eb215 100644
--- a/lib/tls13/psk_parser.c
+++ b/lib/tls13/psk_parser.c
@@ -21,52 +21,151 @@
*/
#include "tls13/psk_parser.h"
-void _gnutls13_psk_parser_init(struct psk_parser_st *p,
- const unsigned char *data, size_t len,
- uint16_t identities_len)
+static int advance_to_end_of_object(struct psk_ext_parser_st *p)
{
- memset(p, 0, sizeof(struct psk_parser_st));
- p->identities_len = identities_len;
- p->data = (unsigned char *) data;
- p->len = len;
+ size_t adv;
+
+ /* Advance the pointer to the end of the current object */
+ if (p->obj_read < p->obj_len) {
+ adv = p->obj_len - p->obj_read;
+ DECR_LEN(p->len, adv);
+ p->data += adv;
+ }
+
+ return 0;
}
-void _gnutls13_psk_parser_deinit(struct psk_parser_st *p,
- const unsigned char **data, size_t *len)
+int _gnutls13_psk_ext_parser_init(struct psk_ext_parser_st *p,
+ const unsigned char *data, size_t len)
{
+ uint16_t identities_len;
+
+ memset(p, 0, sizeof(struct psk_ext_parser_st));
+
+ identities_len = _gnutls_read_uint16(data);
+
+ if (identities_len > 0) {
+ DECR_LEN(len, 2);
+ data += 2;
+
+ p->obj_len = identities_len;
+ p->data = (unsigned char *) data;
+ p->len = len;
+ }
+
+ return identities_len;
+}
+
+int _gnutls13_psk_ext_parser_deinit(struct psk_ext_parser_st *p,
+ const unsigned char **data, size_t *len)
+{
+ if (p->obj_len == 0)
+ goto end;
+
+ if (advance_to_end_of_object(p) < 0)
+ return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+
if (data)
*data = p->data;
if (len)
*len = p->len;
- memset(p, 0, sizeof(struct psk_parser_st));
+
+end:
+ memset(p, 0, sizeof(struct psk_ext_parser_st));
+ return 0;
}
-int _gnutls13_psk_parser_next(struct psk_parser_st *p, struct psk_st *psk)
+int _gnutls13_psk_ext_parser_next_psk(struct psk_ext_parser_st *p, struct psk_st *psk)
{
- if (p->identities_read >= p->identities_len)
- return -1;
+ if (p->obj_read >= p->obj_len)
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
/* Read a PskIdentity structure */
psk->identity.size = _gnutls_read_uint16(p->data);
if (psk->identity.size == 0)
- return -1;
+ return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
DECR_LEN(p->len, 2);
p->data += 2;
- p->identities_read += 2;
+ p->obj_read += 2;
psk->identity.data = p->data;
DECR_LEN(p->len, psk->identity.size);
p->data += psk->identity.size;
- p->identities_read += psk->identity.size;
+ p->obj_read += psk->identity.size;
psk->ob_ticket_age = _gnutls_read_uint32(p->data);
DECR_LEN(p->len, 4);
p->data += 4;
- p->identities_read += 4;
+ p->obj_read += 4;
psk->selected_index = p->next_index++;
return psk->selected_index;
}
+int _gnutls13_psk_ext_parser_find_binder(struct psk_ext_parser_st *p, int psk_index,
+ gnutls_datum_t *binder_out)
+{
+ uint16_t binders_len;
+ uint8_t binder_len;
+ int cur_index = 0, binder_found = 0;
+
+ if (p == NULL || psk_index < 0 || binder_out == NULL)
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+ if (p->obj_len == 0)
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+ /* Place the pointer at the start of the binders */
+ if (advance_to_end_of_object(p) < 0)
+ return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+
+ binders_len = _gnutls_read_uint16(p->data);
+ if (binders_len > 0) {
+ DECR_LEN(p->len, 2);
+ p->data += 2;
+
+ p->obj_len = binders_len;
+ p->obj_read = 0;
+ } else {
+ return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
+ }
+
+ /* Start traversing the binders */
+ while (p->len > 0) {
+ binder_len = *p->data;
+ if (binder_len == 0)
+ return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS);
+
+ DECR_LEN(p->len, 1);
+ p->data++;
+ p->obj_read++;
+
+ if (cur_index == psk_index) {
+ /* We found the binder with the supplied index */
+ binder_out->data = gnutls_malloc(binder_len);
+ if (!binder_out->data)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ binder_out->size = binder_len;
+ memcpy(binder_out->data, p->data, binder_len);
+
+ binder_found = 1;
+ }
+
+ DECR_LEN(p->len, binder_len);
+ p->data += binder_len;
+ p->obj_read += binder_len;
+
+ if (binder_found)
+ break;
+
+ binder_len = 0;
+ cur_index++;
+ }
+
+ return (binder_found ?
+ 0 :
+ gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE));
+}
diff --git a/lib/tls13/psk_parser.h b/lib/tls13/psk_parser.h
index cae258b3a4..de908ead98 100644
--- a/lib/tls13/psk_parser.h
+++ b/lib/tls13/psk_parser.h
@@ -24,11 +24,11 @@
#define PSK_PARSER_H
#include "gnutls_int.h"
-struct psk_parser_st {
+struct psk_ext_parser_st {
unsigned char *data;
ssize_t len;
- uint16_t identities_len;
- uint16_t identities_read;
+ uint16_t obj_len;
+ uint16_t obj_read;
int next_index;
};
@@ -38,12 +38,13 @@ struct psk_st {
int selected_index;
};
-void _gnutls13_psk_parser_init(struct psk_parser_st *p,
- const unsigned char *data, size_t len,
- uint16_t ttl_identities_len);
-void _gnutls13_psk_parser_deinit(struct psk_parser_st *p,
+int _gnutls13_psk_ext_parser_init(struct psk_ext_parser_st *p,
+ const unsigned char *data, size_t len);
+int _gnutls13_psk_ext_parser_deinit(struct psk_ext_parser_st *p,
const unsigned char **data, size_t *len);
-int _gnutls13_psk_parser_next(struct psk_parser_st *p, struct psk_st *psk);
+int _gnutls13_psk_ext_parser_next_psk(struct psk_ext_parser_st *p, struct psk_st *psk);
+int _gnutls13_psk_ext_parser_find_binder(struct psk_ext_parser_st *p, int psk_index,
+ gnutls_datum_t *binder_out);
#endif
diff --git a/lib/tls13/session_ticket.c b/lib/tls13/session_ticket.c
index 7aa75fa10c..da07828bd5 100644
--- a/lib/tls13/session_ticket.c
+++ b/lib/tls13/session_ticket.c
@@ -489,7 +489,8 @@ cleanup:
*/
int _gnutls13_unpack_session_ticket(gnutls_session_t session,
gnutls_datum_t *data,
- gnutls_datum_t *rms, gnutls_mac_algorithm_t *kdf_id)
+ gnutls_datum_t *rms, gnutls_datum_t *nonce,
+ gnutls_mac_algorithm_t *kdf_id)
{
int ret;
const unsigned char *p = data->data;
@@ -563,6 +564,8 @@ int _gnutls13_unpack_session_ticket(gnutls_session_t session,
rms->data = ticket_data.rms;
rms->size = ticket_data.rms_len;
+ nonce->data = ticket_data.ticket_nonce;
+ nonce->size = ticket_data.ticket_nonce_len;
*kdf_id = ticket_data.kdf_id;
return decrypted.size;
diff --git a/lib/tls13/session_ticket.h b/lib/tls13/session_ticket.h
index 79be097b9d..48d0a3c70a 100644
--- a/lib/tls13/session_ticket.h
+++ b/lib/tls13/session_ticket.h
@@ -35,7 +35,8 @@ int _gnutls13_recv_session_ticket(gnutls_session_t session,
int _gnutls13_unpack_session_ticket(gnutls_session_t session,
gnutls_datum_t *data,
- gnutls_datum_t *rms, gnutls_mac_algorithm_t *kdf_id);
+ gnutls_datum_t *rms, gnutls_datum_t *nonce,
+ gnutls_mac_algorithm_t *kdf_id);
int _gnutls13_session_ticket_set(gnutls_session_t session,
struct tls13_nst_st *ticket,