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

Always check soter_rand() for success #570

Merged
merged 7 commits into from
Dec 30, 2019

Conversation

ilammy
Copy link
Collaborator

@ilammy ilammy commented Dec 23, 2019

As previously discussed, let's make sure that return value of soter_rand() is always checked. I have added these failsafes, manually reviewed all existing callsites, and ensured that we abort processing if we fail to generate random data.

Warn about unused result of soter_rand()

Checking random number generation for failures is pretty important [1] [2] so let's make it easier for users to track such issues. Introduce a SOTER_MUST_USE macro that adds an attribute to the function which will cause a compiler warning if the return value is not used (or not explicitly ignored by casting to void). See Clang docs.

Since we treat warnings as errors, CI compilation will fail like this:

compile build/obj/tests/common/test_utils.c.o
tests/common/test_utils.c:70:3: warning: ignoring return value of function declared with 'warn_unused_result' attribute [-Wunused-result]
                soter_rand((uint8_t*)(&res), sizeof(size_t));
                ^~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.

if anyone adds a soter_rand() call without checking the return value.

Add missing tests for themispp::secure_rand_t

We have this API, but it's not tested (or documented either). However, it's there and we should at least exercise it in the test suite. Turns out that it was not checking return value of soter_rand() and it's not visible if there are no tests.

Handle soter_rand() failures

Add missing error handling. For ThemisPP throw an exception. For tests just abort with non-zero exit code as the API does not allow for returning an error. That's actually the case for ed25519 code too.

Checklist

  • Change is covered by automated tests
  • Benchmark results are attached (N/A)
  • The coding guidelines are followed
  • Public API has proper documentation
  • Example projects and code samples are updated (N/A)
  • Changelog is updated if needed (internal change, no need to mention it right now)

Checking random number generation for failures is pretty imporant [1, 2]
so let's make it easier for users to track such issues. Introduce a
SOTER_MUST_USE macro that adds an attribute to the function which will
cause a compiler warning if the return value is not used (or not
explicitly ignored by casting to void). See [3] for description.

Since we treat warnings as errors, CI compilation will fail like this:

    compile build/obj/tests/common/test_utils.c.o
    tests/common/test_utils.c:70:3: warning: ignoring return value of function declared with 'warn_unused_result' attribute [-Wunused-result]
                    soter_rand((uint8_t*)(&res), sizeof(size_t));
                    ^~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    1 warning generated.

if anyone adds a soter_rand() call without checking the return value.

[1]: https://github.com/veorq/cryptocoding#use-strong-randomness
[2]: http://jbp.io/2014/01/16/openssl-rand-api
[3]: http://releases.llvm.org/9.0.0/tools/clang/docs/AttributeReference.html#nodiscard-warn-unused-result
We have this API, but it's not tested (or documented either). However,
it's there and we should at least exercise it in the test suite. Turns
out that it was not checking return value of soter_rand() and it's not
visible if there are no tests.

The API is... wacky, but that's what it is. I'm not really motivated to
clean it up at the moment (and that's out of scope).
Add missing error handling.

For ThemisPP throw an exception. For tests just abort with non-zero exit
code as the API does not allow for returning an error. That's actually
the case for ed25519 code too [1].

[1]: https://github.com/cossacklabs/themis/blob/5f886e1fa1742beb2070da93a2036ad79030dac5/src/soter/ed25519/gen_rand_32.c#L31-L35
@ilammy ilammy added core Themis Core written in C, its packages W-ThemisPP ⚔️ Wrapper: ThemisPP, C++ API tests Themis test suite labels Dec 23, 2019
Copy link
Collaborator

@Lagovas Lagovas left a comment

Choose a reason for hiding this comment

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

lgtm

Copy link
Contributor

@vixentael vixentael left a comment

Choose a reason for hiding this comment

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

👍

@vixentael
Copy link
Contributor

Looks like tests are failing
https://circleci.com/gh/cossacklabs/themis/7117?utm_campaign=vcs-integration-link&utm_medium=referral&utm_source=github-build-link

src/soter/soter_rand.h:53:1: error: 'nodiscard' attribute cannot be applied to types [clang-diagnostic-error]
SOTER_MUST_USE
^

@ilammy
Copy link
Collaborator Author

ilammy commented Dec 23, 2019

Yeah, I'm looking into it. It's weird since [[nodiscard]] should be allowed before a function, like [[deprecated]] so I have no idea why it treats it as if applied to the return type or something.

I have also noticed that apparently we do not test ThemisPP with C++14 and C++17. I was under impression that we do.

Nothing interestring. I have found this typo when trying to run
clang-tidy manually. It is obscured during normal runs due to
"2>/dev/null" which is added there because clang-tidy likes to talk
even when no errors are detected and this is treated as warning output
by our build system.
Make sure that it goes first because when compiling for C++14 this gets
expanded into

    __attribute__((visibility("default")))
    [[nodiscard]]
    soter_status_t soter_rand(uint8_t* buffer, size_t length);

which throws Clang off-guard with this GCC compatibility syntax for
attributes. For some reason Clang thinks that [[nodiscard]] applies
only to "soter_status_t" which is not allowed.

Make sure that C++ attributes go before non-standard attributes.
@ilammy
Copy link
Collaborator Author

ilammy commented Dec 23, 2019

Okay, I got it. That’s because Clang behaves weirdly when non-standard attributes get mixed with standard ones (only C++ has standard attributes). If you expand the macros the compiler sees

__attribute__((visibility("default")))
[[nodiscard]]
soter_status_t soter_rand(uint8_t* buffer, size_t length);

and that triggers something in Clang, but not in GCC. Making [[nodiscard]] go first fixes the issue.

I wonder whether we should check the whole codebase with both GCC and Clang now. The analysis stage compiles and runs tests with some recent versions of GCC and Clang, but we do not check ThemisPP compilation with both compilers, for example.

@vixentael
Copy link
Contributor

you've fixed the build!

we do not check ThemisPP compilation with both compilers

this might be a good idea!

@vixentael
Copy link
Contributor

I believe we can merge this, @ilammy?

@ilammy
Copy link
Collaborator Author

ilammy commented Dec 30, 2019

Uh... yeah, the issue with the build got fixed, and now we test ThemisPP with both GCC and Clang.

@ilammy ilammy merged commit 9198fca into cossacklabs:master Dec 30, 2019
@ilammy ilammy deleted the check-rand-result branch December 30, 2019 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Themis Core written in C, its packages tests Themis test suite W-ThemisPP ⚔️ Wrapper: ThemisPP, C++ API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants