Skip to content

Comments

TLSv1.3: Update the state machine to be closer to TLSv1.3#1932

Closed
mattcaswell wants to merge 13 commits intoopenssl:masterfrom
mattcaswell:tls1_3-use-secrets
Closed

TLSv1.3: Update the state machine to be closer to TLSv1.3#1932
mattcaswell wants to merge 13 commits intoopenssl:masterfrom
mattcaswell:tls1_3-use-secrets

Conversation

@mattcaswell
Copy link
Member

@mattcaswell mattcaswell commented Nov 15, 2016

Checklist
  • tests are added or updated
  • CLA is signed
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:

ClientHello
+ key_share          ---->
                           ServerHello
                           +key_share
                           {CertificateRequest*}
                           {Certificate*}
                           {CertificateStatus*}
                     <---- {Finished}
{Certificate*}
{CertificateVerify*}
{Finished}           ---->
[ApplicationData]    <---> [Application Data]

Key differences between the intermediate position after this PR 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 (although it is using the new TLSv1.3 secret generation)

@richsalz
Copy link
Contributor

#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.
@mattcaswell
Copy link
Member Author

#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))
Copy link
Contributor

@FdaSilvaYY FdaSilvaYY Nov 16, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oups: missing parenthesis around binary & operands ...
EDIT: C operator precedence say it's ok.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, but we tend to (not styleguide requirement) use those parens, so consider it. don't care much what you do.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added parens for clarity.

Copy link
Contributor

@richsalz richsalz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

* 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".
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just s_server, so I don't think we need a better one?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay

apps/s_server.c Outdated
done:
if (ret != SSL_TLSEXT_ERR_OK)
ERR_print_errors(bio_err);
if (aia) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you need this test? since free of NULL is okay. and if you do need it, then "aia != NULL"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand that, aren't the always allocated or NULL?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these should only be in debug builds; libraries shouldn't have print statements. so ifdef it or (better imo) just remove all of them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, forgot that. ok.

apps/s_server.c Outdated
}
resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
BIO_free(derbio);
if (!resp) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test against NULL and remove the printf.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete this "whitespace"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put this "returns" statement inline.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blank line before decl.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

ssl/tls13_enc.c Outdated
return 1;
}

const unsigned char client_handshake_traffic[] =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static? and perhaps move into the function that uses them if it's only one function.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

wholebody = payload;
if (contenttype == SSL3_RT_HANDSHAKE
&& !PACKET_get_1(&wholebody, &msgtype))
abort();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you sure abort is the right thing do do, even in a test?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
@mattcaswell
Copy link
Member Author

New commits pushed addressing all feedback so far.

Copy link
Contributor

@richsalz richsalz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahem. :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

/* TODO(size_t): convert me */
keylen = EVP_CIPHER_key_length(ciph);

if (EVP_CIPHER_mode(ciph) == EVP_CIPH_GCM_MODE)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider using a switch on the cipher mode, for future expansion? not a requirement.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not done. A later commit does some simplification in this area, so I'll leave it be.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should have said a later commit in a later PR

}
#endif

OPENSSL_cleanse(secret, sizeof(secret));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a "ret" variable and remove the duplicate lines? it's consistent with what we do.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

ctx = SSL_CTX_new(TLS_method());

/*
* This test is testing session tickets for <= TLS1.2. It isn't relevant
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Testing for session tickets <=- TLS1.2; not relevant for 1.3" might fit into a single line. If not, never mind.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

if (ret != SSL_TLSEXT_ERR_OK)
ERR_print_errors(bio_err);
if (aia) {
if (aia != NULL) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.,

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@mattcaswell mattcaswell mentioned this pull request Nov 21, 2016
2 tasks
@mattcaswell
Copy link
Member Author

All required changed made, so I've taken your plus one and pushed. Thanks.

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.

3 participants