Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

external PSK mode #481

Merged
merged 66 commits into from
Apr 8, 2024
Merged

external PSK mode #481

merged 66 commits into from
Apr 8, 2024

Conversation

kazuho
Copy link
Member

@kazuho kazuho commented Aug 7, 2023

Subsumes #321, sshock#1.

ToDo:

  • add end-to-end test against openssl?

kazuho and others added 30 commits July 18, 2023 10:29
Design of picotls is based on the assumption that PSK-based
handshake will not be used together with HRR.
From RFC 8446 section 4.2.11:
   For externally established PSKs, the Hash algorithm MUST be set when
   the PSK is established or default to SHA-256 if no such algorithm is
   defined.
Still default to SHA-256 for the hash, but make it configurable.

Be sure to use the same cipher suite on both the client and the server
(note technically the client only uses the hash alg of it, unless there is early data).
Server should not send early data indicator unless the client sent an
early data indicator.
Use configured cipher, or default to a SHA-256 one.

Note: here we've hard-coded PTLS_CIPHER_SUITE_AES_128_GCM_SHA256 for the default,
but any SHA256 one could be chosen (unless the client is sending early data,
but in that case both endpoints need to specify it explicitly, not rely on default).
From TLS 1.3 RFC 8446 section 4.2.10:
   The PSK used to encrypt the
   early data MUST be the first PSK listed in the client's
   "pre_shared_key" extension.

I noticed that later on in the code it only sets up the tls->pending_handshake_secret when
accept_early_data && tls->ctx->max_early_data_size != 0 && psk_index == 0,
so perhaps we don't need to do a check here, but I think it is still
good to check it in the psk handshake.
@sshock
Copy link
Contributor

sshock commented Feb 16, 2024

Hi @kazuho. I'm seeing an unexpected behavior for no matching PSK identity in a scenario where there is no key share.

In my testing earlier with mismatching PSK identity, the server would fail with a 115 UNKNOWN_PSK_IDENTITY as expected, as we fixed it here to do.

However, in my latest testing I have no key share (ptls_context_t key_exchanges is set to NULL), and now instead of failing with 115 as expected, the server sends a HelloRetryRequest.

This is happening around line 4633 in picotls.c, right after the /* try external psk handshake */ section, where it does the HelloRetryRequest:

    /* send HelloRetryRequest if enforced by config or upon key-share mismatch, unless PSK has already been selected */
    if (!is_second_flight && psk_index == SIZE_MAX &&
        (key_share.algorithm == NULL || (properties != NULL && properties->server.enforce_retry))) {

I'm not sure what the right solution is, but it seems like maybe this block of code to fail with UNKNOWN_PSK_IDENTITY needs to be moved up (to right after the /* try external psk handshake */ section)?

    /* If the server was setup to use an external PSK but failed to agree, abort the handshake. Because external PSK is a form of
     * mutual authentication, we should abort continue the handshake upon negotiation failure, at least by default. */
    if (tls->ctx->pre_shared_key.identity.base != NULL && psk_index == SIZE_MAX) {
        ret = PTLS_ALERT_UNKNOWN_PSK_IDENTITY;
        goto Exit;
    }

I'm not confident though because that is currently placed after a /* try psk handshake */ section (is this second one for handling resumption psk?), so if we moved it up would it break resumption psk?

I'm hoping you can understand the proper way to fix this 🤞, thanks!

@sshock
Copy link
Contributor

sshock commented Feb 29, 2024

Since my primary concern is security, I can live with this inconsistent behavior as long as it doesn't present a security vulnerability. That is, as long as the 2nd ClientHello attempt will fail, both with or without a key share. I just don't want a client to be able to trick a server into allowing an anonymous connection.

If you can help me confirm this, that would make me feel a lot better.

Then we can take our time thinking about the proper way to fix it, which I need your help with.

Or if you believe this behavior is correct, please explain. The RFC says Hello Retry is when "it is able to find an acceptable set of parameters but the ClientHello does not contain sufficient information to proceed with the handshake." I just don't see how "no matching PSK identity" falls into this category, but only when key share is missing.

@kazuho
Copy link
Member Author

kazuho commented Apr 5, 2024

@sshock

I'm seeing an unexpected behavior for no matching PSK identity in a scenario where there is no key share.

In my testing earlier with mismatching PSK identity, the server would fail with a 115 UNKNOWN_PSK_IDENTITY as expected, as we fixed it here to do.

However, in my latest testing I have no key share (ptls_context_t key_exchanges is set to NULL), and now instead of failing with 115 as expected, the server sends a HelloRetryRequest.

Thank you for the patience.

I've made some changes reducing differences from master so that this PR can be merged. I think I've fixed the bug alongside that. We also have tests that involve PSK + HRR.

@sshock
Copy link
Contributor

sshock commented Apr 7, 2024

I've made some changes reducing differences from master so that this PR can be merged. I think I've fixed the bug alongside that. We also have tests that involve PSK + HRR.

Thanks @kazuho ! I was able to confirm that it now fails properly with 115 on wrong psk identity, even with no key share.

@sshock
Copy link
Contributor

sshock commented Apr 7, 2024

I also noticed that cli.c now helps set the psk_hash (a522cd9), thanks!

@sshock sshock mentioned this pull request Apr 7, 2024
@kazuho kazuho merged commit 8b52beb into master Apr 8, 2024
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants