Skip to content

Comments

Use ChaCha only if prioritized by clnt#4436

Closed
tmshort wants to merge 2 commits intoopenssl:masterfrom
akamai:master-chacha-pref
Closed

Use ChaCha only if prioritized by clnt#4436
tmshort wants to merge 2 commits intoopenssl:masterfrom
akamai:master-chacha-pref

Conversation

@tmshort
Copy link
Contributor

@tmshort tmshort commented Sep 28, 2017

IFF the client has ChaCha first, and server cipher priority is used,
and the new SSL_OP_PRIORITIZE_CHACHA_FOR_MOBILE option is used,
then reprioritize ChaCha above everything else. This way, A matching
ChaCha cipher will be selected if there is a match. If no ChaCha ciphers
match, then the other ciphers are used.

DO NOT SQUASH THE TWO COMMITS; ONE CAN BE BACK-PORTED TO
1.1.0, THE OTHER CANNOT.

Checklist
  • documentation is added or updated
  • tests are added or updated

@richsalz
Copy link
Contributor

We recently heard from several companies that performance is a concern, and this patch helps address that. Google had a patch that added "equivalence classes" to the ciphers string, but it was kind of incomplete. And the cipher string syntax is already cluttered. So while adding this as an option, only in the code isn't as comprehensive, it's cleaner and can be supported in the conf file.

Copy link
Contributor

Choose a reason for hiding this comment

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

2017 ?

@davidben
Copy link
Contributor

@richsalz I'm curious what you think is incomplete about the equipreference groups.

This design potentially runs into issues if new ciphers are added in front. I believe the list does skip unknown ciphers, so that clears the immediate extensibility failure, but one could imagine, e.g., SCSV ciphers being in front. It also breaks if, for whatever other reason, none of the ChaCha ciphers are suitable. Maybe all common ChaCha ciphers are for the wrong version. Or maybe they're all ECDHE and you have no curves in common.

@davidben
Copy link
Contributor

(Oh, sorry, scratch the second comment. I'd missed that you do pull in the rest of the ciphers. Though looking at the first cipher is still a little fragile.)

@richsalz
Copy link
Contributor

As I recall, you document that the equiv class means you can't sort after it? I forget.

@davidben
Copy link
Contributor

Ah, that's true. Adding an equivalence class disables most opcodes. But it's pretty clear how to make them work. I've been meaning to do it but the need hadn't really come up yet.

@levitte
Copy link
Member

levitte commented Sep 29, 2017

Small nit to pick: please drop _FOR_MOBILE / ForMobile... the library has no way of knowing anyway.

@tmshort
Copy link
Contributor Author

tmshort commented Sep 29, 2017

(Oh, sorry, scratch the second comment. I'd missed that you do pull in the rest of the ciphers. Though looking at the first cipher is still a little fragile.)

This just reorders the server ciphers. I've seen other patches for similar functionality that discard all other ciphers, and as you point out that won't work. Most (all?) mobile clients indicate their preference for ChaCha by putting it at the beginning of their cipher list, so that's the key we look at.

SCSV is only present in client hellos; it won't matter how the server ciphers are ordered. I am not aware of any client that puts SCSV in the front.

@tmshort
Copy link
Contributor Author

tmshort commented Sep 29, 2017

Small nit to pick: please drop _FOR_MOBILE / ForMobile... the library has no way of knowing anyway.

It was to indicate intended use of the option; it was a last minute addition.

@tmshort
Copy link
Contributor Author

tmshort commented Sep 29, 2017

The last commit fixes the nits found thus far.

ssl/s3_lib.c Outdated
Copy link
Member

Choose a reason for hiding this comment

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

This if 's { } seems not necessary...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, the coding standard indicates that braces are not needed for one-statement blocks.

Copy link
Contributor

Choose a reason for hiding this comment

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

HOWEVER, if the code is more clear, feel free to put them. :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That thought did cross my mind...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll hold off doing anything here, unless there are other required changes.

ssl/s3_lib.c Outdated
Copy link
Member

Choose a reason for hiding this comment

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

as above

@InfoHunter
Copy link
Member

If this could be merged into 1.1.1, then many people don't need to struggle with maintaining a patch...

Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't comply with Oxford dictionary, which offers to meanings, to call and to act as.

Copy link
Contributor

Choose a reason for hiding this comment

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

I mean two meanings for the verb.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In my own defense, 's' and 'd' are next to each other on the keyboard, and I did type a real word. :)

Copy link
Contributor

Choose a reason for hiding this comment

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

What's rationale behind choice of constant? Basically there is contradiction. If rationale is that 0x00100000 was removed in 1.1.0, while 0x00200000 in 1.0.2, then it doesn't add up with previous constant. I mean if this is the reason that one probably should adjust even previous constant... But formally speaking removed constant should not be a problem, because you are forced to recompile when upgrading to 1.1.x and it's sufficient to just redefine corresponding macros as zeros. I mean at source code level they won't cause backward compatibility clash...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The rational is that I have another outstanding PR #3910 using 0x00100000

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(There was a prior issue with values that were in SSL_OP_ALL in 1.1.0 and unused, but those values have been marked reserved until 1.2.0)

ssl/s3_lib.c Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

Why does one have to compose the rest of the list?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Although both lists may have ChaCha20, they may not be the same cipher suite; so the rest of the cipher list is necessary. This prevents a failure case (no matching cipher) that would have otherwise succeeded.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(I have seen other ChaCha20 priority patches that have this failure mode because they don't consider the non-ChaCha ciphers their processing)

Copy link
Contributor

Choose a reason for hiding this comment

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

Git it.

Copy link
Contributor

Choose a reason for hiding this comment

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

:-) I missed one centimeter too! I mean I meant to write "got it"...

ssl/s3_lib.c Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

One can wonder if it's appropriate to do so in tls1_suiteb case... Well, it might happen that Chacha won't make into server list in such case, but then making a copy of cipher list would be waste of resources...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

One would have to iterate through the stack to see if there's ChaCha to make the decision to re-order. But is that worth it?

Copy link
Contributor

Choose a reason for hiding this comment

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

Here is my line of reasoning. Note that tls1_suiteb effectively takes precedence over SSL_OP_CIPHER_SERVER_PREFERENCE(*). It's natural to expect that it should take precedence even over SSL_OP_PRIORITIZE_CHACHA. So that for this reason alone one can wonder if check for SSL_OP_PRIORITIZE_CHACHA should be performed only in non-suiteb case. But on the other hand chances are that in suiteb case Chacha isn't even there(**) so one can use tls1_suiteb as criteria for not executing effectively no-op code.

(*) In sense that tls1_suiteb prioritizes server ciphers even without SSL_OP_CIPHER_SERVER_PREFERENCE. In the context one can even wonder if flipping the two in if condition would make code more readable. Or even if (tls1_suiteb) {} else if (SSL_OP_CIPHER_SERVER_PREFERENCE) {} else {}.

(**) This seems to be untrue in sense that if I s_server -suiteB_128 I can still connect with s_client -cipher ECDHE-RSA-CHACHA20-POLY1305. But nevertheless, first reason is probably sufficient by itself.

Copy link
Contributor

@dot-asm dot-asm Oct 4, 2017

Choose a reason for hiding this comment

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

Well, there is also chance that I'm missing something specific about tls1_suiteb. But it does look like that it would be appropriate to give precedence to tls1_suiteb even in SSL_OP_PRIORITIZE_CHACHA case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

re: tls1_suiteb; I don't care, just give me a definitive answer. :)

Copy link
Contributor

Choose a reason for hiding this comment

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

Among other things RFC6460 says that "A Suite B TLS server ... MUST accept ... the TLS_ECDHE_ECDSA_WITH_AES_* cipher suite if it is offered in the ClientHello message." Well, there still is certain ambiguity, because when it comes to client side it says that "One of these two cipher suites MUST be the first (most preferred) cipher suites in the ClientHello message." So that Chacha being first in list presented in ClientHello formally disqualifies it as compliant, and then one can wonder if server is in turn obliged to comply with the requirement... I'd say in case of doubt assume the worst, i.e. make server comply. Or in other words don't SSL_OP_PRIORITIZE_CHACHA in tls1_suiteb case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

ssl/s3_lib.c Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

There is now sk_*_reserve that should be preferred to use here. [And it would make sense to check for its return value.] Though if goal is to back-port it, then of course one can't use it. But one can and probably should add it afterward. Or as separate commit, so that one could be cherry-picked, but not the other...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done as a separate commit

ssl/s3_lib.c Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

One can actually do it in single loop: if (c->algorithm_enc == SSL_CHACHA20POLY1305) sl_SSL_CIPHER_unsift(new_chacha, c); else sk_SSL_CIPHER_push(new_chacha, c);. I also wonder if compiler keeps calling sk_SSL_CIPHER_num for each iteration. I mean maybe it makes sense to ensure that it's called only once...

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, it calls sk_SSL_CIPHER_num for each iteration.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So, how would one prevent it from being called?

Copy link
Contributor

Choose a reason for hiding this comment

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

Obviously

int num = sk_SSL_CIPHER_num(x)
for (i = 0; i < num; i++) {}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Obviously

Oh, yeah, duh. I wasn't looking at the code when I commented. I was working in a totally different context, and thought it had to do with the calls to sk_XXX_push() and the sk_XXX_reserve() (but, as pointed out, it might be better to do that separate)

ssl/s3_lib.c Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

There is now sk_*_reserve that should be preferred to use here. [And it would make sense to check for its return value.] Though if goal is to back-port it, then of course one can't use it. But one can and probably should add it afterward. Or as separate commit, so that one could be cherry-picked, but not the other...

Copy link
Contributor

Choose a reason for hiding this comment

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

??? Can browser play trick on you and submit same message twice with more than ~10 minutes interval? I mean this is duplicate...

@dot-asm
Copy link
Contributor

dot-asm commented Oct 4, 2017

Note that it needs re-base.

@tmshort tmshort force-pushed the master-chacha-pref branch from 5ad4fca to 455bc99 Compare October 4, 2017 13:25
ssl/s3_lib.c Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

??? You already have c to push, you don't need this loop at all, just sk_SSL_CIPHER_push(new_chacha, c)...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it's needed, there can be more than one ChaCha20 cipher in the server list, and they all need to be put at the start. The first loop at 4168~4174 attempts to avoid allocating the new stack, if possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I suppose I could shorten the loop by pushing the found cipher first; then iterating through the rest.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah! You mean that there are other fields in client's head of list and goal is to prioritize all Chachas. One could omit this loop if the match was exact...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We're still doing server priority; there's a decent chance (>=50% given the number of ChaCha20 ciphers) that they won't match, but another ChaCha20 cipher in the list will.

Copy link
Contributor

Choose a reason for hiding this comment

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

Question is if prioritizing all Chachas is actually what client wants. Would maybe starting to push ciphers from client list till it's not Chacha, and then append server list omitting all Chachas more adequate?

Copy link
Contributor

Choose a reason for hiding this comment

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

No, this would be problematic, right? Because in this case you wouldn't be able to interchange prio and allow...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We still want server priority, not client priority; so we want to only include those ChaCha ciphers in the server list, in the order that the server has them.

Copy link
Contributor

Choose a reason for hiding this comment

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

All right, rename new_chacha to prio_chacha, optionally start loop from i+1 instead of 0 (you'll have to push c first), and add comment explaining that we pull up all Chacha ciphers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

ssl/s3_lib.c Outdated
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't you find prio_chacha being a better name for this variable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure

@dot-asm
Copy link
Contributor

dot-asm commented Oct 4, 2017

Does the fact that it's two commits mean that this in fact is nominated for 1.1.0? I for one would vote against it in present state, because it's new feature [specifically visible from source code]. Note "in present state" as I for one would consider even implicit prioritization acceptable, i.e. with no enable flag. But that would be surely considered too radical by others :-)

@richsalz
Copy link
Contributor

richsalz commented Oct 4, 2017

I think it's hard to see how this could be a bugfix, and therefore it's master-only.

@tmshort
Copy link
Contributor Author

tmshort commented Oct 4, 2017

@InfoHunter suggested that it might be nice to add to 1.1.0; a comment on the use of sk_reserve indicated that it should be done separately() so as to allow a 1.1.0 backport. And there's PR #3922, which would also be a backport of a feature.

@tmshort tmshort force-pushed the master-chacha-pref branch from 455bc99 to 2f3999d Compare October 4, 2017 15:11
Copy link
Contributor

@dot-asm dot-asm left a comment

Choose a reason for hiding this comment

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

for master, as I haven't actually examined how suitable it would be for 1.1.0

@dot-asm dot-asm added the approval: review pending This pull request needs review by a committer label Oct 5, 2017

Choose a reason for hiding this comment

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

s/sever/server/
Replace mobile with more general language.

@vdukhovni
Copy link

I am not convinced that this is a good long-term interface. It feels somewhat like a quick hack, and we have a few too many of these as a legacy. Perhaps implementing cipher equivalence classes makes more sense, that way the server can order lists of classes that ignore the distinction between AESGCM and CHACHA, or even between AES128 and AES256, and between SHA2-256 and SHA2-384 and chooses the first class in which there is a common cipher. Within that class we can then go with the client preference or the server preference. That is the server preference bit becomes two bits whose class to choose, and whose cipher to choose within that class.

@richsalz
Copy link
Contributor

I think adding equivalence classes and further complicating that syntax is also not optimal. This is a relatively clean, although not generic, solution to a big existing problem: Mobile wants chacha and desktop wants AES.

@vdukhovni
Copy link

@richsalz I think adding equivalence classes and further complicating that syntax is also not optimal. This is a relatively clean, although not generic, solution to a big existing problem: Mobile wants chacha and desktop wants AES.
The syntax need not be made more complicated, this could be an opportunity to simplify it. We can add an "@v=1" to the front of the cipher string to indicate a brand new syntax that better reflects 20 years of experience. The "not generic" part is precisely the problem here. This is a stop-gap, not an architectural feature. And yet we may be stuck with it for a long time once introduced. We should I think at least discuss alternative designs.

@richsalz
Copy link
Contributor

I understand the issue; nobody would talk about it before, when the equivalence classes issue was raised multiple times. I'd rather see site-wide cipher profiles (from RedHat) as a better solution. But nobody is stepping forward to do that -- in fact, attempts to address this, in many ways, have been ignored or rebuffed so far.

Tnis code should go into the next release.

@vdukhovni
Copy link

Often doing nothing is better than doing something that lacks a solid design. If this issue needs to be addressed, let's prioritize it and put on the roadmap, and see some design proposals before code is written. This is a major part of the public API, one that many users find confusing, and this is probably as good a time as any to address it. We've managed without a ChaCha optimization for some time, it can wait if need be.

@richsalz
Copy link
Contributor

Disagree, and we'll leave it at that.

@t-j-h
Copy link
Member

t-j-h commented Nov 21, 2017

There is strong demand for this capability ... and pushing it off simply means we end up with a whole range of approaches that get put into production to achieve the same effect - leading to slower updates and more custom patches for something that is relatively straight forward and focused. It isn't generalised - but we also haven't seen strong demand for a generalised solution.

@vdukhovni do you feel strongly enough to -1 this?
I'm ready to approve it - but if you'd prefer to take it to an OMC vote I'm fine with that too.

IFF the client has ChaCha first, and server cipher priority is used,
and the new SSL_OP_PRIORITIZE_CHACHA_FOR_MOBILE option is used,
then reprioritize ChaCha above everything else. This way, A matching
ChaCha cipher will be selected if there is a match. If no ChaCha ciphers
match, then the other ciphers are used.
This is a specific 1.1.1 change; do not squash if the chacha
prioritization code is to be backported
@tmshort
Copy link
Contributor Author

tmshort commented Nov 21, 2017

Tweaked the documentation.
Fixed to use sk_SSL_CIPHER_new_reserve()

@vdukhovni
Copy link

vdukhovni commented Nov 21, 2017

@t-j-h @vdukhovni do you feel strongly enough to -1 this? I'm ready to approve it - but if you'd prefer to take it to an OMC vote I'm fine with that too.

I feel strongly that whoever does feel the itch strongly enough to actually address an issue is on the hook for doing it right and not saddling the project with a legacy of short-term work-arounds. So once we have a pull request it should be high-quality design, not just high-quality implementation.

In this case, I don't think an up/down on vote on whether to merge the change would really address my concerns. I'd like to suggest we take a short pause to consider a more ambitious design that makes it easier to optimize the cipher order using a syntax that most mortals can understand and one that avoids out-of-band control bits (like prioritize chacha) and puts all the controls in the cipher string.

@vdukhovni
Copy link

Perhaps the author of this PR is willing to propose a more radical overhaul after considering how this is solved in BoringSSL, GnuTLS, TLS toolkits in other languages, ... and proposing something that is realistic and combines some of the best features of the existing approaches.

@tmshort
Copy link
Contributor Author

tmshort commented Nov 22, 2017

Given the nature of the request; it is doubtful that it could be completed in any reasonable about of time; and would likely miss the 1.1.1 timeframe. The existing cipher specification is arcane and easily broken; especially where forward and backward compatibility are required.
This option is not incompatible with any possible proposed preference list mechanism that might be implemented in the future.

TL;DR: no.

@t-j-h
Copy link
Member

t-j-h commented Nov 22, 2017

If no one steps forward to tackle a more comprehensive solution I'll add approval to this tomorrow so @paulidale or @dot-asm can merge.

@vdukhovni
Copy link

vdukhovni commented Nov 22, 2017

@tmshort Given the nature of the request; it is doubtful that it could be completed in any reasonable about of time; and would likely miss the 1.1.1 timeframe. The existing cipher specification is arcane and easily broken; especially where forward and backward compatibility are required. This option is not incompatible with any possible proposed preference list mechanism that might be implemented in the future.

This is disappointing, we should not be in such a hurry that we introduce long-term API extensions that are layered on top of weak foundations, rather than revisit the design. Sure someone might do something better "some day", but "some day" rarely comes. The time to ask for better care is when the patient is opened up and the surgeon has the scalpel in hand.

The current design with internal stacks manipulated by a series of push/pop operations that move around groups of ciphers while maintaining the internal order of the groups, and putting removed ciphers back in the order in which they removed is much too arcane. Translating a preference for (kECDHE, kEDH, kRSA) with (aRSA, aECDSA) with (AESGCM, AES, ...) ordered by cipher strength into a cipherlist requires fancy gymnastics.

It should instead be possible to state that all other things being equal one prefers some key exchange algorithms over (or the same as) others, some public key algorithms over (or the same as) others, some bulk ciphers over others, ... and be able to set up equivalences which might go with the client's preference when the server otherwise does not care. It is time to create a new cipherlist string syntax, and the need to address new use-cases is a good time to take that on. Surely we can do better than what we've got, and do so in fact in a reasonable amount of time.

@tmshort
Copy link
Contributor Author

tmshort commented Nov 29, 2017

@t-j-h ?

Copy link
Member

@t-j-h t-j-h left a comment

Choose a reason for hiding this comment

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

@paulidale or @dot-asm feel free to merge ...

paulidale pushed a commit to paulidale/openssl that referenced this pull request Nov 29, 2017
IFF the client has ChaCha first, and server cipher priority is used,
and the new SSL_OP_PRIORITIZE_CHACHA_FOR_MOBILE option is used,
then reprioritize ChaCha above everything else. This way, A matching
ChaCha cipher will be selected if there is a match. If no ChaCha ciphers
match, then the other ciphers are used.

Reviewed-by: Paul Dale <[email protected]>
Reviewed-by: Tim Hudson <[email protected]>
Reviewed-by: Andy Polyakov <[email protected]>
(Merged from openssl#4436)
paulidale pushed a commit to paulidale/openssl that referenced this pull request Nov 29, 2017
This is a specific 1.1.1 change; do not squash if the chacha
prioritization code is to be backported

Reviewed-by: Paul Dale <[email protected]>
Reviewed-by: Tim Hudson <[email protected]>
Reviewed-by: Andy Polyakov <[email protected]>
(Merged from openssl#4436)
@paulidale
Copy link
Contributor

Merged to master.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

branch: master Applies to master branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.