-
Notifications
You must be signed in to change notification settings - Fork 58
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
Add build option for exposing self-test failure messages #433
Add build option for exposing self-test failure messages #433
Conversation
* `AWS_LC_fips_failure_callback` is a method invoked by AWS-LC in case a FIPS related check fails * ACCP updates a global flag to false in case this callback is invoked * The value of the global flag is returned as the result of `isFipsStatusOk` * ACCP built in FIPS mode checks `isFipsStatusOk` whenever a crypto service is requested
Co-authored-by: Will Childs-Klein <[email protected]> Co-authored-by: Gerardo Ravago 🇵🇭 <[email protected]>
This reverts commit dea1db2.
d3b69d5
to
3a8643d
Compare
3a8643d
to
0323a8d
Compare
private native int fipsStatusErrorCount(); | ||
|
||
/** | ||
* @return true if and only if the underlying libcrypto library's FIPS related checks pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you guarantee that there are in fact 0 errors rather than we simply haven't run the self-test yet? There's no logic here to guard against returning a false-positive from an untested module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We run AWS-LC's self-tests when ACCP's INSTANCE
is constructed in a java static block. Those self-tests get executed in a threadpool, so there's a very slight potential for a race, but we do run AWS-LC self-tests immediately on load.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooh, I guess we could checkTests()
here, but that might be expensive.
EDIT: no, this is a function in ACCPService, not AmazonCorrettoCryptoProvider...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, even better, I can just check testsPassed
!
EDIT: no, this is a function in ACCPService, not AmazonCorrettoCryptoProvider...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended up going with getSelfTestStatus()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@geedo0 -- looking into this a little more, this behavioral change will break callers (and our tests) when SkipAbort is enabled. we now check isFIpsStatusOk()
in every call to ACCPService.newInstance
, so unless the caller busy-polls getSelfTestStatus() != SelfTestStatus.NOT_RUN
before using the provider, calls to newInstance
will throw an exception until the power-on self tests have completed.
we could busy-poll that status in this method, and maybe that's OK because this is a very specialized build option, but that seems like a recipe for strange behavior. but maybe it's favorable in order to preserve current semantics? removing this check basically changes the semantics of true
in this method from "self-tests have affirmatively passed" to "no self-test failures have occurred".
i removed this check in 34faca36e, but perhaps busy-polling in isFipsStatusOk
is the better approach.
please let me know what you think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Talked offline with @geedo0 and we convinced ourselves that busy polling in isFipsStatusOk
is the way to go so we can guarantee we don't provide any crypto algorithms until the self tests have affirmatively passed.
Implemented busy poll with a deadline in 6d9a71a0c.
A more general solution would be to block the main thread here, but there's a scary comment advising against that. I'll do some experiments out-of-band of this PR.
@@ -157,6 +159,7 @@ static String getProperty(String propertyName, String def) { | |||
PROVIDER_VERSION = oldVersion; | |||
FIPS_BUILD = available && isFipsMode(); | |||
EXPERIMENTAL_FIPS_BUILD = available && isExperimentalFipsMode(); | |||
FIPS_SELF_TEST_SKIP_ABORT = available && isFipsSelfTestFailureSkipAbort(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logic here is confusing me and a bit concerning. Why should all these be be false if the module is unavailable? I worry that a library load failure might break our assertions and slip through the detection cracks of failing loudly. It's happened before with our customers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was pattern-matching here, so can't speak to original intent. I think it might be reasonable to throw a RuntimeException if library loading fails, but that seems out of scope for this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a small nit, otherwise LGTM
src/com/amazon/corretto/crypto/provider/AmazonCorrettoCryptoProvider.java
Outdated
Show resolved
Hide resolved
*Issue #, if available:* ACCP-129 _**THIS FEATURE IS NOT INTENDED FOR PRODUCTION AND IS THUS LEFT UNDOCUMENTED IN OUR README**_ ## Notes This PR builds on prior work from @amirhosv on the `fips-experimentation` branch to provide an alternative mode of handling AWS-LC self test failures. We call this (non-default) mode `FIPS_SELF_TEST_SKIP_ABORT`, and it is only usable when ACCP is built in FIPS mode. By default, AWS-LC will `abort()` on self-test failures. However, as of AWS-LC v1.47, when built with the `AWSLC_FIPS_FAILURE_CALLBACK` build flag AWS-LC will [call][1] a [weak symbol][2] `AWS_LC_fips_failure_callback` function to handle self test failures instead of aborting. When ACCP is built with `-DFIPS_SELF_TEST_SKIP_ABORT`, ACCP defines `AWS_LC_fips_failure_callback` such that it appends to a queue of error strings in ACCP's native heap. To manage the accumulated error strings, we add a native `std::vector` wrapper `ConcurrentStringVector` providing a minimal, threadsafe API. Once the error queue is non-empty, all subsequent `getInstance` calls on an algorithm provided by ACCP will throw `FipsStatusException`. We provide two functions for callers to query fips self test error state on an `AmazonCorrettoCryptoProvider` instance: - `public boolean isFipsStatusOk()` - `public List<String> getFipsSelfTestFailures()` We could get away with only the latter function, but we provide `isFipsStatusOk()` to avoid performance costs of copying error strings over the JNI. [1]: https://github.com/aws/aws-lc/blob/1d8b807ed1ae75c89beda6c73a4ae27c404fa46f/crypto/fipsmodule/bcm.c#L416 [2]: https://github.com/aws/aws-lc/blob/1d8b807ed1ae75c89beda6c73a4ae27c404fa46f/crypto/internal.h#L1427-L1432 ## Testing To adequately test the new mode, we need to build AWS-LC with `FIPS_BREAK_TEST=TESTS` to programmatically break AWS-LC's pairwise consistency tests (PCTs). We test against each available PCT breakage during key generation by setting the appropriate environment variable, indicating which PCT to break. Unfortunately, Java doesn't appear to have a standard utility for manipulating process environment variables at runtime, so we create our own `TestUtil.setEnv` that calls POSIX `setenv`/`unsetenv` over the JNI. In addition to CI tests, I've also executed `run_accp_basic_tests.sh` with the new `--fips-self-test-failure-no-abort` flag, which will eventually be incorporated into our GitHub CI. ``` $ TEST_JAVA_HOME=/usr/lib/jvm/java-17-amazon-corretto.x86_64 ./tests/ci/run_accp_basic_tests.sh --fips-self-test-failure-no-abort ... BUILD SUCCESSFUL in 40m 15s 18 actionable tasks: 13 executed, 5 up-to-date ``` --- By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. --------- Co-authored-by: Amir Vakili <[email protected]> Co-authored-by: Amir Vakili <[email protected]> Co-authored-by: Gerardo Ravago 🇵🇭 <[email protected]>
Issue #, if available: ACCP-129
THIS FEATURE IS NOT INTENDED FOR PRODUCTION AND IS THUS LEFT UNDOCUMENTED IN OUR README
Notes
This PR builds on prior work from @amirhosv on the
fips-experimentation
branch to provide an alternative mode of handling AWS-LC self test failures. We call this (non-default) modeFIPS_SELF_TEST_SKIP_ABORT
, and it is only usable when ACCP is built in FIPS mode.By default, AWS-LC will
abort()
on self-test failures. However, as of AWS-LC v1.47, when built with theAWSLC_FIPS_FAILURE_CALLBACK
build flag AWS-LC will call a weak symbolAWS_LC_fips_failure_callback
function to handle self test failures instead of aborting. When ACCP is built with-DFIPS_SELF_TEST_SKIP_ABORT
, ACCP definesAWS_LC_fips_failure_callback
such that it appends to a queue of error strings in ACCP's native heap. To manage the accumulated error strings, we add a nativestd::vector
wrapperConcurrentStringVector
providing a minimal, threadsafe API. Once the error queue is non-empty, all subsequentgetInstance
calls on an algorithm provided by ACCP will throwFipsStatusException
.We provide two functions for callers to query fips self test error state on an
AmazonCorrettoCryptoProvider
instance:public boolean isFipsStatusOk()
public List<String> getFipsSelfTestFailures()
We could get away with only the latter function, but we provide
isFipsStatusOk()
to avoid performance costs of copying error strings over the JNI.Testing
To adequately test the new mode, we need to build AWS-LC with
FIPS_BREAK_TEST=TESTS
to programmatically break AWS-LC's pairwise consistency tests (PCTs). We test against each available PCT breakage during key generation by setting the appropriate environment variable, indicating which PCT to break. Unfortunately, Java doesn't appear to have a standard utility for manipulating process environment variables at runtime, so we create our ownTestUtil.setEnv
that calls POSIXsetenv
/unsetenv
over the JNI.In addition to CI tests, I've also executed
run_accp_basic_tests.sh
with the new--fips-self-test-failure-no-abort
flag, which will eventually be incorporated into our GitHub CI.By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.