Skip to content

Commit

Permalink
ext/pre_shared_key: make PSK identity parsing robuster
Browse files Browse the repository at this point in the history
Previously, to determine whether a PSK identity is a ticket or a PSK
username, it relied on PskIdentity.obfuscated_ticket_age, which
"SHOULD" be 0 if the identity is a PSK username.

This patch instead checks the key name of the ticket first and then
check the constraints of the PSK username.  That way, it can
distinguish tickets and PSK usernames in a more realible manner.

Signed-off-by: Daiki Ueno <dueno@redhat.com>
  • Loading branch information
ueno committed Jun 1, 2018
1 parent 6b45592 commit fd8c1ec
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 38 deletions.
57 changes: 21 additions & 36 deletions lib/ext/pre_shared_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,6 @@ static int server_recv_params(gnutls_session_t session,
int psk_index;
gnutls_datum_t binder_recvd = { NULL, 0 };
gnutls_datum_t key = {NULL, 0};
unsigned cand_index;
psk_ext_parser_st psk_parser;
struct psk_st psk;
psk_auth_info_t info;
Expand All @@ -481,44 +480,13 @@ static int server_recv_params(gnutls_session_t session,
return gnutls_assert_val(ret);
}

psk_index = -1;

while ((ret = _gnutls13_psk_ext_parser_next_psk(&psk_parser, &psk)) >= 0) {
cand_index = ret;

/* Is this a PSK? */
if (psk.ob_ticket_age == 0) {
/* _gnutls_psk_pwd_find_entry() expects 0-terminated identities */
if (psk.identity.size > 0 && psk.identity.size <= MAX_USERNAME_SIZE) {
char identity_str[psk.identity.size + 1];

prf = pskcred->binder_algo;

memcpy(identity_str, psk.identity.data, psk.identity.size);
identity_str[psk.identity.size] = 0;

/* this fails only on configuration errors; as such we always
* return its error code in that case */
ret = _gnutls_psk_pwd_find_entry(session, identity_str, &key);
if (ret < 0)
return gnutls_assert_val(ret);

psk_index = cand_index;
resuming = 0;
break;
}
}

/* Is this a session ticket? */
while ((psk_index = _gnutls13_psk_ext_parser_next_psk(&psk_parser, &psk)) >= 0) {
/* This will unpack the session ticket if it is well
* formed and has the expected name */
if (!(session->internals.flags & GNUTLS_NO_TICKETS) &&
(ret = _gnutls13_unpack_session_ticket(session, &psk.identity, &ticket_data)) == 0) {
prf = ticket_data.prf;

if (!prf) {
tls13_ticket_deinit(&ticket_data);
continue;
}

/* Check whether ticket is stale or not */
ticket_age = psk.ob_ticket_age - ticket_data.age_add;
if (ticket_age < 0) {
Expand All @@ -539,9 +507,26 @@ static int server_recv_params(gnutls_session_t session,

tls13_ticket_deinit(&ticket_data);

psk_index = cand_index;
resuming = 1;
break;
} else if (psk.ob_ticket_age == 0 &&
psk.identity.size > 0 && psk.identity.size <= MAX_USERNAME_SIZE) {
/* _gnutls_psk_pwd_find_entry() expects 0-terminated identities */
char identity_str[psk.identity.size + 1];

This comment has been minimized.

Copy link
@gvanem

gvanem Dec 29, 2018

Could someone please make this compile without use of VLA for MSVC (it doesn't support it). Like just:

   char *identity_str = alloca (psk.identity.size + 1);

instead.

And BTW, many people think VLAs is a bad thing although not in this case.

This comment has been minimized.

Copy link
@ueno

ueno Dec 30, 2018

Author Member

I guess it wouldn't harm if we use char identity_str[MAX_USERNAME_SIZE + 1]; as it's only 129-byte long.

This comment has been minimized.

Copy link
@gvanem

gvanem Dec 30, 2018

Yes, even better.


prf = pskcred->binder_algo;

memcpy(identity_str, psk.identity.data, psk.identity.size);
identity_str[psk.identity.size] = 0;

/* this fails only on configuration errors; as such we always
* return its error code in that case */
ret = _gnutls_psk_pwd_find_entry(session, identity_str, &key);
if (ret < 0)
return gnutls_assert_val(ret);

resuming = 0;
break;
}
}

Expand Down
4 changes: 2 additions & 2 deletions lib/tls13/session_ticket.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ unpack_ticket(gnutls_session_t session, gnutls_datum_t *packed, tls13_ticket_t *
/* Check if the MAC ID we got is valid */
prf = _gnutls_mac_to_entry(kdf);
if (prf == NULL)
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);

/* Read the ticket age add and the ticket lifetime */
DECR_LEN(len, 4);
Expand All @@ -133,7 +133,7 @@ unpack_ticket(gnutls_session_t session, gnutls_datum_t *packed, tls13_ticket_t *

/* Check if the size of resumption_master_secret matches the PRF */
if (resumption_master_secret_size != prf->output_size)
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);

DECR_LEN(len, resumption_master_secret_size);
memcpy(resumption_master_secret, p, resumption_master_secret_size);
Expand Down

0 comments on commit fd8c1ec

Please sign in to comment.