Skip to content

Comments

TLSv1.3: Record Construction#1975

Closed
mattcaswell wants to merge 10 commits intoopenssl:masterfrom
mattcaswell:tls1_3-record-construct
Closed

TLSv1.3: Record Construction#1975
mattcaswell wants to merge 10 commits intoopenssl:masterfrom
mattcaswell:tls1_3-record-construct

Conversation

@mattcaswell
Copy link
Member

@mattcaswell mattcaswell commented Nov 21, 2016

Checklist
  • tests are added or updated
  • CLA is signed
Description of change

This modifies the record layer to use TLSv1.3 record construction. I also updated various parts of the record layer to use PACKET/WPACKET.

@mattcaswell mattcaswell force-pushed the tls1_3-record-construct branch from 55ba47e to c010aba Compare November 23, 2016 16:04
@mattcaswell
Copy link
Member Author

I rebased this now that #1932 has gone in. It still depends on #1947 so please only look at the last 6 commits.

@mattcaswell mattcaswell force-pushed the tls1_3-record-construct branch from 54b5778 to f8ea452 Compare December 1, 2016 10:21
@mattcaswell
Copy link
Member Author

I rebased this again. All previous PRs this depended on have now been merged into master, so please review all commits.

ssl/packet.c Outdated
}
*allocbytes = GETBUF(pkt) + pkt->curr;
if (allocbytes != NULL)
*allocbytes = GETBUF(pkt) + pkt->curr;
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't this call the new get_curr routine you just added?

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

#endif
outbuf[0] = SSL3_BUFFER_get_buf(wb) + align;
SSL3_BUFFER_set_offset(wb, align);
if (!WPACKET_init_static_len(&pkt[0], SSL3_BUFFER_get_buf(wb),
Copy link
Contributor

Choose a reason for hiding this comment

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

I dislike &foo[0] constructs as a parameter, since foo is the same thing by definition

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 they are the same, but in my mind it makes it a lot clearer that you are referring to a single entity and not the array as a whole. Especially when you mix it in scenarios where on other lines we refer to a single entity which is not at index 0. I dislike the inconsistency.

Copy link
Contributor

Choose a reason for hiding this comment

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

ok

wb = &s->rlayer.wbuf[0];
outbuf[0] = SSL3_BUFFER_get_buf(wb) + SSL3_BUFFER_get_offset(wb)
+ prefix_len;
if (!WPACKET_init_static_len(&pkt[0], SSL3_BUFFER_get_buf(wb),
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe break after the pkt param, so that the get_buf/get_len calls could appear on the same line.

Copy link
Member Author

Choose a reason for hiding this comment

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

They still will not fit on the same line.

+ prefix_len;
if (!WPACKET_init_static_len(&pkt[0], SSL3_BUFFER_get_buf(wb),
SSL3_BUFFER_get_len(wb), 0)
|| !WPACKET_allocate_bytes(&pkt[0], SSL3_BUFFER_get_offset(wb)
Copy link
Contributor

Choose a reason for hiding this comment

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

linebreak after the comma so that the expression can fit on a single line.

Copy link
Member Author

Choose a reason for hiding this comment

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

Still does not fit.

} else {
for (j = 0; j < numpipes; j++) {
wb = &s->rlayer.wbuf[j];
#if defined(SSL3_ALIGN_PAYLOAD) && SSL3_ALIGN_PAYLOAD!=0
Copy link
Contributor

Choose a reason for hiding this comment

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

space around the !=

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 in existing code...but ok, done.

/* field where we are to write out packet length */
plen[j] = outbuf[j];
outbuf[j] += 2;
maxcomplen = pipelens[j] + (s->compress != NULL
Copy link
Contributor

Choose a reason for hiding this comment

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

break after the plus to keep the ternary subexpression together.

Copy link
Member Author

Choose a reason for hiding this comment

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

Still doesn't fit

Copy link
Contributor

@richsalz richsalz Dec 2, 2016

Choose a reason for hiding this comment

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

maxcomplen = pipelens[j]
                    + (s->compress != NULL
                            ? SSL3_RT_MAX_COMPRESSED_OVERHEAD : 0);

Or

maxcomplen = pipelens[j];
if (s->compress != NULL)
   maxcomplen += SSL3_RT_MAX_COMPRESSED_OVERHEAD;

Copy link
Contributor

Choose a reason for hiding this comment

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

My comment isn't getting formatted properly. In the first example line the + under the =, and then see how much fits.

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 implemented the second variant.

#endif
outbuf[j] = SSL3_BUFFER_get_buf(wb) + align;
SSL3_BUFFER_set_offset(wb, align);
if (!WPACKET_init_static_len(&pkt[j], SSL3_BUFFER_get_buf(wb),
Copy link
Contributor

Choose a reason for hiding this comment

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

as above, try to keep the getbuf/buflen params together.

Copy link
Member Author

Choose a reason for hiding this comment

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

As above, still does not fit.

} else if (mode == EVP_CIPH_CCM_MODE) {
eivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
else
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe init eivlen to zero so you can avoid this statement and the one at 783

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

}
SSL3_RECORD_add_length(&wr[j], 1);
/*
* TODO(TLS1.3): Padding goes here. Do we need an API to add this?
Copy link
Contributor

Choose a reason for hiding this comment

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

yes we need an API or a callback. which one to do requires some thought.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok. For a later PR.

if (SSL_IS_TLS13(s) && s->enc_read_ctx != NULL) {
size_t end;

if (rr[j].length == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

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

introduce a local pointer value to replace all these rr[j] instances.

Copy link
Contributor

Choose a reason for hiding this comment

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

and not just in this if block, that is.

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

Updated commits addressing feedback so far pushed.

@richsalz
Copy link
Contributor

richsalz commented Dec 2, 2016

As for the "still does not fit" I understand, but perhaps you can reformat the lines so that the subexpressions are better self-contained.

@richsalz
Copy link
Contributor

richsalz commented Dec 2, 2016

BTW, if you say that you cannot do the reformatting then +1

@mattcaswell
Copy link
Member Author

I have had another look at the sub-expressions, but I can't come up with a better way of formatting them that is more sane than what I currently have.

+ prefix_len;
if (!WPACKET_init_static_len(&pkt[0], SSL3_BUFFER_get_buf(wb),
SSL3_BUFFER_get_len(wb), 0)
|| !WPACKET_allocate_bytes(&pkt[0], SSL3_BUFFER_get_offset(wb)
Copy link
Contributor

Choose a reason for hiding this comment

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

So I was suggesting that maybe this is better:

    if (!WPACKET_init_static_len(&pkt[0],
                                            SSL3_BUFFER_get_buf(wb),
                                            SSL3_BUFFER_get_len(wb), 0)

Or this

    if (!WPACKET_init_static_len(&pkt[0],
                                            SSL3_BUFFER_get_buf(wb), SSL3_BUFFER_get_len(wb),
                                            0)

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, I did the first version.

/* field where we are to write out packet length */
plen[j] = outbuf[j];
outbuf[j] += 2;
maxcomplen = pipelens[j] + (s->compress != NULL
Copy link
Contributor

Choose a reason for hiding this comment

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

My comment isn't getting formatted properly. In the first example line the + under the =, and then see how much fits.

size_t origlen;

/* Allocate bytes for the encryption overhead */
if (!WPACKET_get_length(&pkt[j], &origlen)
Copy link
Contributor

Choose a reason for hiding this comment

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

I think all these pkt[j] and wr[j] should become pointers.

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

@richsalz
Copy link
Contributor

richsalz commented Dec 2, 2016

upon re-reading, I'm holding back by plus-one; the formatting isn't the issue, it's the pkt/wr[j] stuff.

…pointer

Improves the readability of the code, and reduces the liklihood of errors.
Also made a few minor style changes.
@mattcaswell
Copy link
Member Author

New commit pushed addressing the feedback.

@richsalz
Copy link
Contributor

richsalz commented Dec 5, 2016

+1

@mattcaswell
Copy link
Member Author

Pushed. Thanks.

@mattcaswell mattcaswell closed this Dec 5, 2016
* TODO(TLS1.3): Make sure we prevent compression!!!
*/
if (!ssl3_do_compress(s, thiswr)
|| !WPACKET_allocate_bytes(thispkt, thiswr->length, NULL)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

How does the (compressed) data get to the WPACKET in the compression case?
It looks to me like ssl3_do_compress is keeping it within the SSL3_RECORD.

Copy link
Member Author

Choose a reason for hiding this comment

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

Look at the SSL3_RECORD_set_data() call a few lines above. An SSL3_RECORD structure never actually stores data itself, it just holds pointers to data somewhere else. In this case we set the data to point at the data that we just reserved in the WPACKET_reserve_bytes() call.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, thanks.
(Do we have any tests that exercise the SSL compression functionality? I see that ssltest_old.c takes a -zlib argument, but am not finding any recipes that actually use it.)

p = RECORD_LAYER_get_packet(&s->rlayer);

if (!PACKET_buf_init(&pkt, RECORD_LAYER_get_packet(&s->rlayer),
RECORD_LAYER_get_packet_length(&s->rlayer))) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, maybe a RECORD_to_PACKET helper is in order?

Copy link
Member Author

Choose a reason for hiding this comment

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

Well, maybe...but its probably not worth it for just one instance of this.

/*
* TODO(TLS1.3): Padding goes here. Do we need an API to add this?
* For now, use no padding
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

There should probably be some sort of API. One could imagine letting the application choose amongst some predefined padding profiles, like "add random chaff" or "pad up to N-byte boundaries for various fixed N". I guess one could also imagine adding a callback to give the application packet-level control, which might be useful for tor-like applications, but is probably overkill for the first cut at things.

Copy link
Contributor

Choose a reason for hiding this comment

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

It might make sense to always add a padding byte for now, to exercise the read-side code (unless there are boringssl tests already covering that?).

Copy link
Contributor

@richsalz richsalz Dec 5, 2016

Choose a reason for hiding this comment

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

Look at what we did for CT. A callback, and provide a couple of fixed policies.

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'm thinking along similar lines. A later PR though.


if (TLSProxy::Proxy->is_tls13()) {
#Get the content type
my $content_type = unpack("C", substr($data, length($data) - 1));
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, does this mean the proxy is unable to cope with padding?

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. But that's ok. The proxy is only ever used as a test tool between two communicating OpenSSL instances. At the moment OpenSSL never sends padding, so this works. At some point in the future we will have to amend it when we start to send padding.

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