Skip to content
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

fix HMAC_DRBG edge case #3165

Merged
merged 2 commits into from
Aug 11, 2020
Merged

fix HMAC_DRBG edge case #3165

merged 2 commits into from
Aug 11, 2020

Conversation

keks
Copy link
Contributor

@keks keks commented Aug 4, 2020

The NIST SP 800-90A spec of HMAC_DRBG uses "!= Null" checks, but "Null" is never defined in the document. In the current implementation, it was interpreted as nil. However, the NIST examples document uses "<empty>" values, so []byte{} should be passed in the test cases. If that happens, the nil checks do not work as expected. Therefore, instead of checking equality with nil, it should be checked whether the length of additional_info is zero.

As additional evidence I cite the openssl implementation, which checks for zero length instead of NULL pointer equality.

I do not expect this to have a concrete security impact, but still it would be nice if the implementation was correct.

@codecov
Copy link

codecov bot commented Aug 4, 2020

Codecov Report

Merging #3165 into master will increase coverage by 0.24%.
The diff coverage is 50.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #3165      +/-   ##
==========================================
+ Coverage   68.48%   68.72%   +0.24%     
==========================================
  Files         386      386              
  Lines       37962    37962              
==========================================
+ Hits        25997    26091      +94     
+ Misses       8658     8559      -99     
- Partials     3307     3312       +5     
Impacted Files Coverage Δ
go/common/crypto/drbg/hmac_drbg.go 71.08% <50.00%> (ø)
go/worker/common/p2p/error/error.go 71.42% <0.00%> (-28.58%) ⬇️
go/runtime/host/sandbox/sandbox.go 67.28% <0.00%> (-10.04%) ⬇️
go/worker/common/committee/runtime_host.go 65.71% <0.00%> (-4.77%) ⬇️
go/storage/client/client.go 73.33% <0.00%> (-3.75%) ⬇️
go/runtime/host/protocol/connection.go 62.16% <0.00%> (-1.94%) ⬇️
go/runtime/registry/registry.go 74.69% <0.00%> (-1.21%) ⬇️
go/consensus/tendermint/abci/state.go 68.72% <0.00%> (-0.66%) ⬇️
go/worker/compute/merge/committee/node.go 76.27% <0.00%> (-0.49%) ⬇️
go/worker/common/committee/group.go 81.75% <0.00%> (ø)
... and 26 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 5083907...383608c. Read the comment docs.

Copy link
Member

@kostko kostko left a comment

Choose a reason for hiding this comment

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

Thank you for your contribution! The fix seems to make sense, @Yawning can you also take a quick look?

A few minor nits also flagged by the linter:

go/common/crypto/drbg/hmac_drbg_test.go Show resolved Hide resolved
@keks
Copy link
Contributor Author

keks commented Aug 4, 2020

I duplicated the tests and in one of them use nil and in the other []byte{}. Additionally, I added a changelog fragement and capitalized the commit subject line. Unfortunately, the URLs are wider than 80 characters, and I wasn't sure how to wrap them.

Finally, I'm not 100% sure if any part of Oasis uses an empty slice somewhere in it's code, so I left a TODO in the fragment. I can update it if you have a definite answer for me.

@Yawning
Copy link
Contributor

Yawning commented Aug 4, 2020

Finally, I'm not 100% sure if any part of Oasis uses an empty slice somewhere in it's code, so I left a TODO in the fragment. I can update it if you have a definite answer for me.

No, we don't, and in fact, there is no way for the edge case to be triggered. Since the affected routines are package private, it's fairly easy to confirm this via manual review.

  • Drbg.Read always passes nil as additionalInput
  • New always passes a non-0 length slice (seedMaterial) as additionalInput

@keks
Copy link
Contributor Author

keks commented Aug 4, 2020

I briefly skimmed the output of git grep drbg but from my experience the package maintainers usually have a much better overview 🙂

I feel like the URLs are helpful in the commit messages so I'm hesitant to remove them in order to make the linter happy. How do you want to proceed?

@kostko
Copy link
Member

kostko commented Aug 4, 2020

I feel like the URLs are helpful in the commit messages so I'm hesitant to remove them in order to make the linter happy. How do you want to proceed?

Good point, I just fixed the linter in #3168, once that's merged, you can rebase and the linter should pass. I'll also trigger the non-lint CI workflow again after your rebase.

The NIST SP 800-90A[1] spec of HMAC_DRBG uses "!= Null" checks,
but "Null" is never defined in the document. In the current
implementation, this was interpreteted as nil.
However, the NIST examples document[2] uses "<empty>" values,
so []byte{} should be passed in the test cases. If that happens,
the nil checks do not work as expected. Therefore, instead of checking
equality with nil, it should be checked whether the length of
additional_info is zero.

As additional evidence I cite the openssl implementation[3], which checks
for zero length instead of NULL pointer equality.

[1]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf
[2]: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_DRBG.pdf
[3]: https://github.com/openssl/openssl/pull/6779/files#diff-c44c9681c4fc49b1d7e9e74578085212R77-R79
@keks
Copy link
Contributor Author

keks commented Aug 11, 2020

@kostko

Sorry this took so long. I think the linter regex doesn't like the hash fragment. On line 10, it says:

 URL_RE_RAW = r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+' 

Note that the third bracket after :// we have [$-_@.&+], where $-_ means all characters between $ (0x24) and _ (0x5f). However, the hash sign # is 0x23, so it doesn't match this bracket expression.

Do you want to fix the regex or should we skip the more precise reference and use a link without hash fragment?

@kostko
Copy link
Member

kostko commented Aug 11, 2020

Aw sorry, I only tested with the first URL. Feel free to fix the regexp in this PR, just in a separate commit.

@kostko
Copy link
Member

kostko commented Aug 11, 2020

Thanks again! I also triggered the other CI workflow to run now.

@kostko kostko merged commit 481bbd9 into oasisprotocol:master Aug 11, 2020
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.

None yet

3 participants