Skip to content

Gracefully handle exceptions from Security Providers#65464

Merged
jkakavas merged 7 commits intoelastic:masterfrom
jkakavas:fips-exception-handling
Nov 26, 2020
Merged

Gracefully handle exceptions from Security Providers#65464
jkakavas merged 7 commits intoelastic:masterfrom
jkakavas:fips-exception-handling

Conversation

@jkakavas
Copy link
Copy Markdown
Contributor

In certain situations, such as when configured in FIPS 140 mode,
the Java security provider in use might throw a subclass of
java.lang.Error. We currently do not catch these and as a result
the JVM exits, shutting down elasticsearch.

This commit attempts to address this by catching AssertionErrors
that we are aware that might be thrown when a PBKDF2 implementation
is used from a Security Provider in FIPS 140 mode, with the password
input being less than 14 bytes (112 bits).

  • In our PBKDF2 family of hashers, we catch the AssertionError and
    throw an ElasticsearchException while creating or verifying the
    hash. We throw on verification instead of simply returning false
    on purpose so that the message bubbles up and the cause becomes
    obvious (otherwise it would be indistinguishable from a wrong
    password).
  • In KeyStoreWrapper, we catch the AssertionError in order to
    wrap and rethrow with a helpful message. This can happen when using
    any of the keystore CLI commands, when the node starts or when we attempt
    to reload secure settings.
  • In the elasticsearch-users tool, we catch the AssertionError and
    throw an appropriate UserException.

Tests are missing because it's not trivial to set CI in fips approved mode
right now, and thus any tests would need to be muted. There is a parallel
effort in #64024 to enable that
and we can either hold off merging this until 64024 is merged and tests
added, or add tests in followup.

In certain situtations, such as when configured in FIPS 140 mode,
the Java security provider in use might throw a subclass of
java.lang.Error. We currently do not catch these and as a result
the JVM exits, shutting down elasticsearch.

This commit attempts to address this by catching AssertionErrors
that we are aware that might be thrown when a PBKDF2 implementation
is used from a Security Provider in FIPS 140 mode, with the password
input being less than 14 bytes (112 bits).

- In our PBKDF2 family of hashers, we catch the AssertionError and
throw an ElasticsearchException while creating or verifying the
hash. We throw on verification instead of simply returning false
on purpose so that the message bubbles up and the cause becomes
obvious (otherwise it would be indistinguishable from a wrong
password).
- In KeyStoreWrapper, we catch the AssertionError in order to
wrap and rethrow with a helpful message. This can happen when using
any of the keystore CLI commands, when the node starts or when we attempt
to reload secure settings.
- In the `elasticsearch-users` tool, we catch the AssertionError and
throw an appropriate UserException.
@jkakavas jkakavas added >bug :Security/Security Security issues without another label v8.0.0 v7.11.0 labels Nov 24, 2020
@elasticmachine elasticmachine added the Team:Security Meta label for security team label Nov 24, 2020
@elasticmachine
Copy link
Copy Markdown
Collaborator

Pinging @elastic/es-security (Team:Security)

PBEKeySpec keySpec = new PBEKeySpec(data.getChars(), salt, cost, PBKDF2_KEY_LENGTH);
result.put(Base64.getEncoder().encodeToString(secretKeyFactory.generateSecret(keySpec).getEncoded()));
return result.array();
} catch (AssertionError ae){
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

My thinking is that we should scope this tightly first and expand if/when we get reports/CI failures for additional errors. The ones we know are thrown are all AssertionError and catching all Error felt too wide of a net. Not holding a strong opinion on this, happy to discuss

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Somehow missed this comment in the previous pass ... I see you already considered it. I suggest a wider net (even wider then Error) because 1) any future fix to this would require a release which is purely overhead; 2) I cannot think of a valid reason for ES to shutdown here due to any kinda of error. So wider net (at least Error) should provide mostly benefit.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the comment Yang. I see your points. I'll let Lyudmila weigh in too and we can reach a consensus

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would leave an ability to throw and shutdown for when something unthinkable happens. Catching Error should be ok though

Copy link
Copy Markdown
Member

@ywangd ywangd left a comment

Choose a reason for hiding this comment

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

I left a few comments. The main question I have is whether we should be more liberal and catch Throwable instead of AssertionError, which is a choice of BC. Since we are trying to cover unexpected situations to avoid unpleasant surprises, I wonder whether widen the net is a viable option.

SecretKey secretKey;
try {
secretKey = keyFactory.generateSecret(keySpec);
} catch (AssertionError ae) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I wonder whether we could just be very liberal and catch a Throwable here. So we are sure nothing is going to trip it regardless of the provider.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I went back and forth as to how wide the net should be. My counter argument is that when something throws an Error instead of an Exception it supposedly denotes an irrecoverable error. We know that this is not true for the AssertionError that BCFIPS throws here, but can we be certain that we want to catch all Throwables that can be thrown from external code. We don't do that in any other place. WDYT ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

+1 to leave it this way, we shoudn't catch potentially irrecoverable exceptions

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You got me thinking again @ywangd .. On the one hand, I tried to limit the scope of these try-catch blocks to a min so it makes sense that we would catch all irrecoverable errors from that line and give out an error message. On the other hand, the very limited scope makes it less possible that a wider net would catch issues thrown by other security providers that we know nothing of (other than the PBKDF2 112 bits limitation). I'm a bit torn on this one

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Had a short chat with Yang and we decided that catching Error is the way to go based on the arguments that have been made already in this PR

@BigPandaToo
Copy link
Copy Markdown
Contributor

Should we add a test?

SecretKey secretKey;
try {
secretKey = keyFactory.generateSecret(keySpec);
} catch (AssertionError ae) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

+1 to leave it this way, we shoudn't catch potentially irrecoverable exceptions

@jkakavas
Copy link
Copy Markdown
Contributor Author

Should we add a test?

see description:

Tests are missing because it's not trivial to set CI in fips approved mode
right now, and thus any tests would need to be muted. There is a parallel
effort in #64024 to enable that
and we can either hold off merging this until 64024 is merged and tests
added, or add tests in followup.

@BigPandaToo
Copy link
Copy Markdown
Contributor

LGTM

Copy link
Copy Markdown
Member

@ywangd ywangd left a comment

Choose a reason for hiding this comment

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

LGTM

@jkakavas jkakavas merged commit e7d0684 into elastic:master Nov 26, 2020
@jkakavas jkakavas deleted the fips-exception-handling branch November 26, 2020 13:58
jkakavas added a commit to jkakavas/elasticsearch that referenced this pull request Nov 26, 2020
In certain situations, such as when configured in FIPS 140 mode,
the Java security provider in use might throw a subclass of
java.lang.Error. We currently do not catch these and as a result
the JVM exits, shutting down elasticsearch.

This commit attempts to address this by catching subclasses of Error
that might be thrown for instance when a PBKDF2 implementation
is used from a Security Provider in FIPS 140 mode, with the password
input being less than 14 bytes (112 bits).

- In our PBKDF2 family of hashers, we catch the Error and
throw an ElasticsearchException while creating or verifying the
hash. We throw on verification instead of simply returning false
on purpose so that the message bubbles up and the cause becomes
obvious (otherwise it would be indistinguishable from a wrong
password).
- In KeyStoreWrapper, we catch the Error in order to wrap and re-throw 
a GeneralSecurityException with a helpful message. This can happen when 
using any of the keystore CLI commands, when the node starts or when we 
attempt to reload secure settings.
- In the `elasticsearch-users` tool, we catch the ElasticsearchException that
the Hasher class re-throws and throw an appropriate UserException.

Tests are missing because it's not trivial to set CI in fips approved mode
right now, and thus any tests would need to be muted. There is a parallel
effort in elastic#64024 to enable that and tests will be added in a followup.
jkakavas added a commit to jkakavas/elasticsearch that referenced this pull request Nov 26, 2020
In certain situations, such as when configured in FIPS 140 mode,
the Java security provider in use might throw a subclass of
java.lang.Error. We currently do not catch these and as a result
the JVM exits, shutting down elasticsearch.

This commit attempts to address this by catching subclasses of Error
that might be thrown for instance when a PBKDF2 implementation
is used from a Security Provider in FIPS 140 mode, with the password
input being less than 14 bytes (112 bits).

- In our PBKDF2 family of hashers, we catch the Error and
throw an ElasticsearchException while creating or verifying the
hash. We throw on verification instead of simply returning false
on purpose so that the message bubbles up and the cause becomes
obvious (otherwise it would be indistinguishable from a wrong
password).
- In KeyStoreWrapper, we catch the Error in order to wrap and re-throw 
a GeneralSecurityException with a helpful message. This can happen when 
using any of the keystore CLI commands, when the node starts or when we 
attempt to reload secure settings.
- In the `elasticsearch-users` tool, we catch the ElasticsearchException that
the Hasher class re-throws and throw an appropriate UserException.

Tests are missing because it's not trivial to set CI in fips approved mode
right now, and thus any tests would need to be muted. There is a parallel
effort in elastic#64024 to enable that and tests will be added in a followup.
jkakavas added a commit that referenced this pull request Nov 26, 2020
In certain situations, such as when configured in FIPS 140 mode,
the Java security provider in use might throw a subclass of
java.lang.Error. We currently do not catch these and as a result
the JVM exits, shutting down elasticsearch.

This commit attempts to address this by catching subclasses of Error
that might be thrown for instance when a PBKDF2 implementation
is used from a Security Provider in FIPS 140 mode, with the password
input being less than 14 bytes (112 bits).

- In our PBKDF2 family of hashers, we catch the Error and
throw an ElasticsearchException while creating or verifying the
hash. We throw on verification instead of simply returning false
on purpose so that the message bubbles up and the cause becomes
obvious (otherwise it would be indistinguishable from a wrong
password).
- In KeyStoreWrapper, we catch the Error in order to wrap and re-throw 
a GeneralSecurityException with a helpful message. This can happen when 
using any of the keystore CLI commands, when the node starts or when we 
attempt to reload secure settings.
- In the `elasticsearch-users` tool, we catch the ElasticsearchException that
the Hasher class re-throws and throw an appropriate UserException.

Tests are missing because it's not trivial to set CI in fips approved mode
right now, and thus any tests would need to be muted. There is a parallel
effort in #64024 to enable that and tests will be added in a followup.
jkakavas added a commit that referenced this pull request Nov 26, 2020
In certain situations, such as when configured in FIPS 140 mode,
the Java security provider in use might throw a subclass of
java.lang.Error. We currently do not catch these and as a result
the JVM exits, shutting down elasticsearch.

This commit attempts to address this by catching subclasses of Error
that might be thrown for instance when a PBKDF2 implementation
is used from a Security Provider in FIPS 140 mode, with the password
input being less than 14 bytes (112 bits).

- In our PBKDF2 family of hashers, we catch the Error and
throw an ElasticsearchException while creating or verifying the
hash. We throw on verification instead of simply returning false
on purpose so that the message bubbles up and the cause becomes
obvious (otherwise it would be indistinguishable from a wrong
password).
- In KeyStoreWrapper, we catch the Error in order to wrap and re-throw 
a GeneralSecurityException with a helpful message. This can happen when 
using any of the keystore CLI commands, when the node starts or when we 
attempt to reload secure settings.
- In the `elasticsearch-users` tool, we catch the ElasticsearchException that
the Hasher class re-throws and throw an appropriate UserException.

Tests are missing because it's not trivial to set CI in fips approved mode
right now, and thus any tests would need to be muted. There is a parallel
effort in #64024 to enable that and tests will be added in a followup.
jkakavas added a commit that referenced this pull request Nov 26, 2020
…#65554)"

This reverts commit 12ba9e3. This
commit was mechanically backported to 7.10 while it shouldn't have
been.
jkakavas added a commit to jkakavas/elasticsearch that referenced this pull request Jan 11, 2021
We handled the exceptions thrown by Security Providers in the case
of short encryption keys in elastic#65464 and this commit adds a couple
of tests to validate that the appropriate exceptions are thrown
when encryption keys derived from short passwords are in use, in
FIPS 140-2 mode.
jkakavas added a commit that referenced this pull request Jan 14, 2021
We handled the exceptions thrown by Security Providers in the case
of short encryption keys in #65464 and this commit adds a couple
of tests to validate that the appropriate exceptions are thrown
when encryption keys derived from short passwords are in use, in
FIPS 140-2 mode.
jkakavas added a commit to jkakavas/elasticsearch that referenced this pull request Jan 15, 2021
We handled the exceptions thrown by Security Providers in the case
of short encryption keys in elastic#65464 and this commit adds a couple
of tests to validate that the appropriate exceptions are thrown
when encryption keys derived from short passwords are in use, in
FIPS 140-2 mode.
jkakavas added a commit to jkakavas/elasticsearch that referenced this pull request Jan 15, 2021
We handled the exceptions thrown by Security Providers in the case
of short encryption keys in elastic#65464 and this commit adds a couple
of tests to validate that the appropriate exceptions are thrown
when encryption keys derived from short passwords are in use, in
FIPS 140-2 mode.
jkakavas added a commit that referenced this pull request Jan 15, 2021
We handled the exceptions thrown by Security Providers in the case
of short encryption keys in #65464 and this commit adds a couple
of tests to validate that the appropriate exceptions are thrown
when encryption keys derived from short passwords are in use, in
FIPS 140-2 mode.
jkakavas added a commit that referenced this pull request Jan 15, 2021
We handled the exceptions thrown by Security Providers in the case
of short encryption keys in #65464 and this commit adds a couple
of tests to validate that the appropriate exceptions are thrown
when encryption keys derived from short passwords are in use, in
FIPS 140-2 mode.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

>bug :Security/Security Security issues without another label Team:Security Meta label for security team v7.11.0 v8.0.0-alpha1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants