-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Replace OpenSSL in cross-testing with micro-ecc(uECC) #738
base: master
Are you sure you want to change the base?
Conversation
…777c with source files only
Hey, great stuff! I haven't looked at the code yet but here are some quick initial thoughts and discussion points:
|
It sounds like upstream knows about this, not sure why they decided to do that https://github.com/kmackay/micro-ecc/blob/master/uECC.c#L1374
I got something along these lines: a bit faster than openssl but not by much.
That's a good question, I'm fine however, I did it like this to minimize the amount of junk I'm adding here, but if people prefer I can do a subtree instead |
I think subtree is a good option since it has been integrated in git. |
I guess it's about performance and simplicity. Endianness is arguably not so interesting for a random integer. :D |
Subtree won't work if we need local modifications. |
Oh right! I confused subtree with this thing here https://github.com/ingydotnet/git-subrepo that I used once in a different project. It's very neat but not sure if it's overkill for us. It's something like a dev dependency (only people that want to use subrepo commands need to install it, you don't need it for a normal checkout and build.) |
@elichai It's offtopic, but since you edited the microecc code, I'm confused by: "* We just use H(m) directly rather than bits2octets(H(m)) (it is not reduced modulo curve_n)." IIRC, in RFC6979 you're supposed to truncate to ceil(log2(n)) bits then use rejection sampling. For some curves like the nist160 curve that microecc supports, the order is extremely far from a power of two, and so the rejection sampling actually avoids a security vulnerability. There isn't one hidden there is there? |
It's late here so maybe I'm not reading right, but reading RFC6979 Maybe you're confusing the result of the HMAC (which is |
Ah, indeed that's right! I don't see how to exploit that particular behaviour, either. Thanks for answering my question! |
Hm I looked at the status of micro-ecc, and it's not very satisfying. It's not actively maintained (I guess that's okay for us) but there are a lot of bug reports about incorrect computations:
Cross-testing is a good issue but cross-testing against a known-to-be-buggy library will probably create too much more headache to be useful. |
@real-or-random if it's buggy and the cross tests pass that in and of itself is extremely informative as the tests should be catching real bugs. ... though the first link is that it doesn't produce low-S signatures and isn't actually a bug. Cross-testing with openssl turned up real bugs in openssl: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3570 If it's too buggy then sure it might not be worth using if it takes too much effort to fix it, but the exercise of exposing the bugs would presumably improve the tests a lot. |
I can't really parse your first sentence, sorry. I think the goal is to find bugs in our library and not in micro-ecc, no? I mean of course we want to find discrepancies first and then see who's wrong but it seems to me that micro-ecc is quite often wrong, e.g. 128 and 160 are for sure bugs in micro-ecc.
Okay indeed. |
The main purpose of cross testing is to find (or avoid) deficiencies in the tests and prevent them from concealing complementary bugs in the library. If those bugs in microecc are real (and not reporting errors) then the tests in libsecp256k1 are deficient if it passes crosstesting. It's not necessary that the thing being crosstested against is great. OpenSSL wasn't great, it was-- in fact-- outright defective. For crosstesting it's important that it fails differently. If it has some bugs too, they're areas that libsecp256k1's test should make sure to test in case libsecp256k1 eventually gains similar bugs. If it's too broken and too hard to fix, then sure it could be a waste of time. I think you didn't mean 160? It's not a bug at all, it's someone asking about bugs. 128 and 161 are bugs that if they exists libsecp256k1 tests should totally catch, they're obvious test vectors. 163 is so bad its hard to believe its correct (and if its doing it on nonces too, it's pretty much a total break-- kinda perplexing that it would have that issue for keygen and not nonces). |
A future PR can integrate this into all of our edge cases tests. about the low-S as @gmaxwell that's not a bug and I handle it in the tests: Line 5128 in 50eaa53
Line 5136 in 50eaa53
|
And yeah kmackay/micro-ecc#163 doesn't make a lot of sense. |
Yes, I meant 161. Having those as test vectors is certainly useful. What's not clear in my mind yet is how this should work in the end. Let me try to say it in my own words: Assume the cross-tests fail, we discover some differences and add test vectors. Then the cross-tests still fail. So we need to exclude the failing instances from the cross-tests (as we can't hope for micro-ecc to fix them). Excluding is okay for cases like 161, 128 because these happen with negligible probability on random vectors. If it's a bug that we run into now and then even on random inputs, that's probably more annoying. But hopefully this won't happen. Does this match your ideas?
I feel we should do be doing this right now for OpenSSL. |
I can look into it if it helps, but too many parts of the tests use internal APIs for no reason right now. |
You should be extremely cautious doing anything with this library, by all means test it and break it, but never trust it. Privately we've had concerns about how it operates for quite a while, and this particular piece of code has shown up in a large number of places recently. It is used in Sony products, Intel products, numerous Bitcoin hardware wallets, security sensitive bootloaders, and even security appliances.
|
This to me is a pretty good demonstration of code laundering. A library that nobody would ever have considered using in its current state is being included in a large number of projects, and its existence in those is being used as a justification of its safety. if studying it does not result in at least a dozen CVEs I would be very surprised. |
Just fix 'em locally. Unless it takes a heroic effort to fix them, in which case that would be an argument against using it as a comparison point. Another way to look at it: is that if the project had unlimited resources it would be attractive to go and get two non-overlapping set of developers and get them to implement the same functionality without ever looking at libsecp256k1; and forbid one of them from using a list of techniques that are in libsecp256k1. Then use both of those as comparison points. The resources to do that don't exist, but grabbing some already existing code is a good approximation. It may share some bugs with libsecp256k1 but its unlikely to share all. Having to apply fixes takes some work, but less than writing the whole thing from scratch. Applying fixes may increase the failure correlation but it won't make it worse than not having the comparison at all. |
I think this will be very useful and then we could have a more generic thing that is able to call a number of different implementations (OpenSSL, micro-ecc, ...?) and get cross-tests for free for a lot of (future) tests. Then this will actually a reason to keep the OpenSSL tests first. But I will be good to have some more opinions on the entire thing. @sipa @jonasnick @apoelstra
Yeah, this is what I'm most skeptical about in terms of effort but I guess we should give it a try. |
It's safe to say that this PR is in line with not trusting it. |
FWIW this is what I've done in #641, I wrote my impl without looking at the code here, or honestly any code, I intentionally implemented it from papers only.
|
Some thoughts after discussion with @sipa and @jonasnick: It's not entirely clear how useful cross-testing only ECDSA is: The confidence in our ECDSA code is pretty good. There's cryptofuzz and there's Wycheproof vectors now (which are explicitly based on differential testing or built to catch differences.) So, the approach in this PR would probably be more useful if it covered more than just ECDSA. But even if this approach covered more, we'd need to see if it's worth the hassle.
If the answer to all of these three questions is yes, then we should probably keep talking. If not, we should close this. |
Adding cross testing against non-openssl implementation was suggested multiple times
#691
I attempted to do it in #641 but there wasn't good consensus to add rust even to the testing suite.
@gmaxwell suggested in #716 that we can use https://github.com/kmackay/micro-ecc for that.
So I integrated uECC into our tests build system and replaced the current openssl cross testing with uECC tests.
This is IMHO better for a couple of reasons:
cc #736 #734