Use ChaCha only if prioritized by clnt#4436
Conversation
|
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. |
test/ssl-tests/25-cipher.conf.in
Outdated
|
@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. |
|
(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.) |
|
As I recall, you document that the equiv class means you can't sort after it? I forget. |
|
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. |
|
Small nit to pick: please drop |
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. |
It was to indicate intended use of the option; it was a last minute addition. |
|
The last commit fixes the nits found thus far. |
ssl/s3_lib.c
Outdated
There was a problem hiding this comment.
This if 's { } seems not necessary...
There was a problem hiding this comment.
Yes, the coding standard indicates that braces are not needed for one-statement blocks.
There was a problem hiding this comment.
HOWEVER, if the code is more clear, feel free to put them. :)
There was a problem hiding this comment.
That thought did cross my mind...
There was a problem hiding this comment.
I'll hold off doing anything here, unless there are other required changes.
ssl/s3_lib.c
Outdated
|
If this could be merged into 1.1.1, then many people don't need to struggle with maintaining a patch... |
doc/man3/SSL_CTX_set_options.pod
Outdated
There was a problem hiding this comment.
This doesn't comply with Oxford dictionary, which offers to meanings, to call and to act as.
There was a problem hiding this comment.
I mean two meanings for the verb.
There was a problem hiding this comment.
In my own defense, 's' and 'd' are next to each other on the keyboard, and I did type a real word. :)
include/openssl/ssl.h
Outdated
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
The rational is that I have another outstanding PR #3910 using 0x00100000
There was a problem hiding this comment.
(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
There was a problem hiding this comment.
Why does one have to compose the rest of the list?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
(I have seen other ChaCha20 priority patches that have this failure mode because they don't consider the non-ChaCha ciphers their processing)
There was a problem hiding this comment.
:-) I missed one centimeter too! I mean I meant to write "got it"...
ssl/s3_lib.c
Outdated
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
re: tls1_suiteb; I don't care, just give me a definitive answer. :)
There was a problem hiding this comment.
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.
ssl/s3_lib.c
Outdated
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
Done as a separate commit
ssl/s3_lib.c
Outdated
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
Yes, it calls sk_SSL_CIPHER_num for each iteration.
There was a problem hiding this comment.
So, how would one prevent it from being called?
There was a problem hiding this comment.
Obviously
int num = sk_SSL_CIPHER_num(x)
for (i = 0; i < num; i++) {}
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
??? Can browser play trick on you and submit same message twice with more than ~10 minutes interval? I mean this is duplicate...
|
Note that it needs re-base. |
5ad4fca to
455bc99
Compare
ssl/s3_lib.c
Outdated
There was a problem hiding this comment.
??? You already have c to push, you don't need this loop at all, just sk_SSL_CIPHER_push(new_chacha, c)...
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
I suppose I could shorten the loop by pushing the found cipher first; then iterating through the rest.
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
No, this would be problematic, right? Because in this case you wouldn't be able to interchange prio and allow...
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
ssl/s3_lib.c
Outdated
There was a problem hiding this comment.
Wouldn't you find prio_chacha being a better name for this variable?
|
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 :-) |
|
I think it's hard to see how this could be a bugfix, and therefore it's master-only. |
|
@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. |
455bc99 to
2f3999d
Compare
dot-asm
left a comment
There was a problem hiding this comment.
for master, as I haven't actually examined how suitable it would be for 1.1.0
doc/man3/SSL_CTX_set_options.pod
Outdated
There was a problem hiding this comment.
s/sever/server/
Replace mobile with more general language.
|
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. |
|
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. |
|
|
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. |
|
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. |
|
Disagree, and we'll leave it at that. |
|
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? |
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
3f0c12e to
5532aab
Compare
|
Tweaked the documentation. |
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. |
|
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. |
|
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. TL;DR: no. |
|
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. |
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. |
|
@t-j-h ? |
t-j-h
left a comment
There was a problem hiding this comment.
@paulidale or @dot-asm feel free to merge ...
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)
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)
|
Merged to master. |
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