TLSv1.3: Update the state machine to be closer to TLSv1.3#1932
TLSv1.3: Update the state machine to be closer to TLSv1.3#1932mattcaswell wants to merge 13 commits intoopenssl:masterfrom
Conversation
|
#1848 has been reviewed and approved, so once you do that and rebase I will begin looking at this. |
TLSv1.3 has a NewSessionTicket message, but it is *completely* different to the TLSv1.2 one and may as well have been called something else. This commit removes the old style NewSessionTicket from TLSv1.3. We will have to add the new style one back in later.
This is a major overhaul of the TLSv1.3 state machine. Currently it still
looks like TLSv1.2. This commit changes things around so that it starts
to look a bit less like TLSv1.2 and bit more like TLSv1.3.
After this commit we have:
ClientHello
+ key_share ---->
ServerHello
+key_share
{CertificateRequest*}
{Certificate*}
{CertificateStatus*}
<---- {Finished}
{Certificate*}
{CertificateVerify*}
{Finished} ---->
[ApplicationData] <---> [Application Data]
Key differences between this intermediate position and the final TLSv1.3
position are:
- No EncryptedExtensions message yet
- No server side CertificateVerify message yet
- CertificateStatus still exists as a separate message
- A number of the messages are still in the TLSv1.2 format
- Still running on the TLSv1.2 record layer
The previous commit had a dummy payload for the Finished data. This commit fills it in with a real value.
There is a set of miscellaneous processing for OCSP, CT etc at the end of the ServerDone processing. In TLS1.3 we don't have a ServerDone, so this needs to move elsewhere.
In one case we weren't always sending an unexpected message alert if we don't get what we expect.
After the client processes the server's initial flight in TLS1.3 it may respond with either an encrypted, or an unencrypted alert. We needed to teach TLSProxy about this so that it didn't issue spurious warnings.
Current s_server can only get an OCSP Response from an OCSP responder. This provides the capability to instead get the OCSP Response from a DER encoded file. This should make testing of OCSP easier.
Add various different handshake types that are possible.
89dd6b9 to
4427701
Compare
|
#1848 is now in, so I rebased. All commits in this PR are now for review. |
ssl/t1_lib.c
Outdated
| static int tls_use_ticket(SSL *s) | ||
| { | ||
| if (s->options & SSL_OP_NO_TICKET) | ||
| if (s->options & SSL_OP_NO_TICKET || SSL_IS_TLS13(s)) |
There was a problem hiding this comment.
Oups: missing parenthesis around binary & operands ...
EDIT: C operator precedence say it's ok.
There was a problem hiding this comment.
yeah, but we tend to (not styleguide requirement) use those parens, so consider it. don't care much what you do.
There was a problem hiding this comment.
I added parens for clarity.
richsalz
left a comment
There was a problem hiding this comment.
This is a first, lightly-read, review. After you respond and push I'll probably have more comments, hopefully substantive ones.
apps/s_server.c
Outdated
| } tlsextstatusctx; | ||
|
|
||
| static tlsextstatusctx tlscstatp = { NULL, NULL, NULL, 0, -1, 0 }; | ||
| static tlsextstatusctx tlscstatp = { NULL, NULL, NULL, NULL, 0, -1, 0 }; |
There was a problem hiding this comment.
consider re-ordering the fields in the structure so that the initializer can just be "-1" at the start, and everything else gets the zero default. More future-proof.
| * simplified version. It examines certificates each time and makes one OCSP | ||
| * responder query for each request. A full version would store details such as | ||
| * the OCSP certificate IDs and minimise the number of OCSP responses by caching | ||
| * them until they were considered "expired". |
There was a problem hiding this comment.
Do we ever have plans to write the better one? Can we tie this into the external session caching mechanism to at least make it not stink?
There was a problem hiding this comment.
This is just s_server, so I don't think we need a better one?
apps/s_server.c
Outdated
| done: | ||
| if (ret != SSL_TLSEXT_ERR_OK) | ||
| ERR_print_errors(bio_err); | ||
| if (aia) { |
There was a problem hiding this comment.
do you need this test? since free of NULL is okay. and if you do need it, then "aia != NULL"
There was a problem hiding this comment.
Yes, I think we need it to determine whether we should free "host", "path" and "port". Dependent on code path they may be set to something that needs freeing, or set to something that doesn't need freeing. Changed to "aia != NULL".
There was a problem hiding this comment.
I don't understand that, aren't the always allocated or NULL?
There was a problem hiding this comment.
In the case where aia is NULL, we set set host, path and port to point to srctx->host, srctx->path and srctx->port respectively. Those shouldn't be freed here.
| int rspderlen; | ||
| int ret = SSL_TLSEXT_ERR_ALERT_FATAL; | ||
|
|
||
| if (srctx->verbose) |
There was a problem hiding this comment.
these should only be in debug builds; libraries shouldn't have print statements. so ifdef it or (better imo) just remove all of them.
There was a problem hiding this comment.
Errr...this is in s_server, not in the library? It's not a debug thing. It implements the "-status_verbose" feature, and was done this way in the existing code.
apps/s_server.c
Outdated
| } | ||
| resp = d2i_OCSP_RESPONSE_bio(derbio, NULL); | ||
| BIO_free(derbio); | ||
| if (!resp) { |
There was a problem hiding this comment.
test against NULL and remove the printf.
There was a problem hiding this comment.
Test against NULL added, but kept the printf for same reason as above.
ssl/tls13_enc.c
Outdated
|
|
||
| /* | ||
| * Generates the mac for the Finished message. | ||
| * |
ssl/tls13_enc.c
Outdated
| * There isn't really a key block in TLSv1.3, but we still need this function | ||
| * for initialising the cipher and hash. | ||
| * | ||
| * Returns 1 on success or 0 on failure. |
There was a problem hiding this comment.
put this "returns" statement inline.
There was a problem hiding this comment.
Done. And other similar instances in this file.
| } | ||
| } else if (EVP_CIPHER_mode(ciph) == EVP_CIPH_CCM_MODE) { | ||
| int taglen; | ||
| if (s->s3->tmp.new_cipher->algorithm_enc |
ssl/tls13_enc.c
Outdated
| return 1; | ||
| } | ||
|
|
||
| const unsigned char client_handshake_traffic[] = |
There was a problem hiding this comment.
static? and perhaps move into the function that uses them if it's only one function.
| wholebody = payload; | ||
| if (contenttype == SSL3_RT_HANDSHAKE | ||
| && !PACKET_get_1(&wholebody, &msgtype)) | ||
| abort(); |
There was a problem hiding this comment.
you sure abort is the right thing do do, even in a test?
There was a problem hiding this comment.
It's what we do already in that test and in others. I think its ok.
The SSL_IS_TLS13() macro wasn't quite right. It would come back with true in the case where we haven't yet negotiated TLSv1.3, but it could be negotiated.
|
New commits pushed addressing all feedback so far. |
richsalz
left a comment
There was a problem hiding this comment.
assuming you address this, I approve.
| * server's initial flight. In TLS1.3 this is after the Server Finished message. | ||
| * In <=TLS1.2 this is after the ServerDone message. | ||
| * | ||
| * Returns 1 on success or 0 on failure. |
| /* TODO(size_t): convert me */ | ||
| keylen = EVP_CIPHER_key_length(ciph); | ||
|
|
||
| if (EVP_CIPHER_mode(ciph) == EVP_CIPH_GCM_MODE) |
There was a problem hiding this comment.
consider using a switch on the cipher mode, for future expansion? not a requirement.
There was a problem hiding this comment.
Not done. A later commit does some simplification in this area, so I'll leave it be.
There was a problem hiding this comment.
I should have said a later commit in a later PR
| } | ||
| #endif | ||
|
|
||
| OPENSSL_cleanse(secret, sizeof(secret)); |
There was a problem hiding this comment.
add a "ret" variable and remove the duplicate lines? it's consistent with what we do.
| ctx = SSL_CTX_new(TLS_method()); | ||
|
|
||
| /* | ||
| * This test is testing session tickets for <= TLS1.2. It isn't relevant |
There was a problem hiding this comment.
"Testing for session tickets <=- TLS1.2; not relevant for 1.3" might fit into a single line. If not, never mind.
| if (ret != SSL_TLSEXT_ERR_OK) | ||
| ERR_print_errors(bio_err); | ||
| if (aia) { | ||
| if (aia != NULL) { |
There was a problem hiding this comment.
Can you add a comment that says "if we parsed AIA, we need to free; otherwise they were copied and we don't" or something like that.,
|
All required changed made, so I've taken your plus one and pushed. Thanks. |
Checklist
Description of change
This is a major overhaul of the TLSv1.3 state machine. Currently it still
looks like TLSv1.2. This commit changes things around so that it starts
to look a bit less like TLSv1.2 and bit more like TLSv1.3.
After this PR we will have:
Key differences between the intermediate position after this PR and the final TLSv1.3
position are: