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

Removing connection properties: fipsProvider and fips #433

Closed
wants to merge 4 commits into from

Conversation

ulvii
Copy link
Contributor

@ulvii ulvii commented Aug 5, 2017

This is a breaking change and should not be merged. Creating this PR early to allow discussions.

  1. Removing connection property fipsProvider
    Currently, this property is only used to specify the name of a provider which guarantees that the implementation of the type requested is from the named provider. Note that, the specified provider must still be registered in the security provider list.
KeyStore.getInstance(trustStoreType, fipsProvider);

If fipsProvider is not specified,KeyStore.getInstance traverses the list of registered security Providers, starting with the most preferred Provider.

  1. Removing connection property fips.
    Once FIPS mode is enabled for JAVA (either from JAVA options or java.security), all the driver needs to know is trustStoreType. There is no need to set fips to true, because the driver does not really enable FIPS.

To sum up, after proposed changes, user will have to enable FIPS mode for JAVA and pass trustStoreType to driver.

@msftclas
Copy link

msftclas commented Aug 5, 2017

@ulvii,
Thanks for your contribution as a Microsoft full-time employee or intern. You do not need to sign a CLA.
Thanks,
Microsoft Pull Request Bot

@ulvii
Copy link
Contributor Author

ulvii commented Aug 5, 2017

Hi @v-nisidh/ @nsidhaye, please feel free to leave feedback.

@codecov-io
Copy link

codecov-io commented Aug 5, 2017

Codecov Report

Merging #433 into dev will decrease coverage by 0.03%.
The diff coverage is 0%.

Impacted file tree graph

@@             Coverage Diff              @@
##                dev     #433      +/-   ##
============================================
- Coverage     45.95%   45.92%   -0.04%     
+ Complexity     2200     2197       -3     
============================================
  Files           108      108              
  Lines         25210    25167      -43     
  Branches       4164     4150      -14     
============================================
- Hits          11585    11557      -28     
- Misses        11702    11705       +3     
+ Partials       1923     1905      -18
Flag Coverage Δ Complexity Δ
#JDBC41 45.75% <0%> (-0.01%) 2188 <0> (+1)
#JDBC42 45.77% <0%> (-0.06%) 2190 <0> (-3)
Impacted Files Coverage Δ Complexity Δ
...om/microsoft/sqlserver/jdbc/SQLServerResource.java 100% <ø> (ø) 4 <0> (ø) ⬇️
.../microsoft/sqlserver/jdbc/SQLServerDataSource.java 46.92% <ø> (-0.2%) 64 <0> (-2)
.../com/microsoft/sqlserver/jdbc/SQLServerDriver.java 75.15% <ø> (-0.3%) 25 <0> (ø)
...in/java/com/microsoft/sqlserver/jdbc/IOBuffer.java 55.17% <0%> (-0.12%) 0 <0> (ø)
...java/com/microsoft/sqlserver/jdbc/StringUtils.java 25% <0%> (-12.5%) 3% <0%> (-1%)
...m/microsoft/sqlserver/jdbc/SQLServerResultSet.java 33.1% <0%> (-0.09%) 251% <0%> (-1%)
.../microsoft/sqlserver/jdbc/SQLServerConnection.java 45.91% <0%> (-0.04%) 287% <0%> (-1%)
...om/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java 52.99% <0%> (+0.12%) 244% <0%> (+1%) ⬆️
...m/microsoft/sqlserver/jdbc/SQLServerStatement.java 59.87% <0%> (+0.3%) 139% <0%> (+1%) ⬆️

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 3d5097c...ec72a94. Read the comment docs.

1 similar comment
@codecov-io
Copy link

codecov-io commented Aug 5, 2017

Codecov Report

Merging #433 into dev will decrease coverage by 0.03%.
The diff coverage is 0%.

Impacted file tree graph

@@             Coverage Diff              @@
##                dev     #433      +/-   ##
============================================
- Coverage     45.95%   45.92%   -0.04%     
+ Complexity     2200     2197       -3     
============================================
  Files           108      108              
  Lines         25210    25167      -43     
  Branches       4164     4150      -14     
============================================
- Hits          11585    11557      -28     
- Misses        11702    11705       +3     
+ Partials       1923     1905      -18
Flag Coverage Δ Complexity Δ
#JDBC41 45.75% <0%> (-0.01%) 2188 <0> (+1)
#JDBC42 45.77% <0%> (-0.06%) 2190 <0> (-3)
Impacted Files Coverage Δ Complexity Δ
...om/microsoft/sqlserver/jdbc/SQLServerResource.java 100% <ø> (ø) 4 <0> (ø) ⬇️
.../microsoft/sqlserver/jdbc/SQLServerDataSource.java 46.92% <ø> (-0.2%) 64 <0> (-2)
.../com/microsoft/sqlserver/jdbc/SQLServerDriver.java 75.15% <ø> (-0.3%) 25 <0> (ø)
...in/java/com/microsoft/sqlserver/jdbc/IOBuffer.java 55.17% <0%> (-0.12%) 0 <0> (ø)
...java/com/microsoft/sqlserver/jdbc/StringUtils.java 25% <0%> (-12.5%) 3% <0%> (-1%)
...m/microsoft/sqlserver/jdbc/SQLServerResultSet.java 33.1% <0%> (-0.09%) 251% <0%> (-1%)
.../microsoft/sqlserver/jdbc/SQLServerConnection.java 45.91% <0%> (-0.04%) 287% <0%> (-1%)
...om/microsoft/sqlserver/jdbc/SQLServerBulkCopy.java 52.99% <0%> (+0.12%) 244% <0%> (+1%) ⬆️
...m/microsoft/sqlserver/jdbc/SQLServerStatement.java 59.87% <0%> (+0.3%) 139% <0%> (+1%) ⬆️

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 3d5097c...ec72a94. Read the comment docs.

else {
tm = new TrustManager[] {new HostNameOverrideX509TrustManager(this, (X509TrustManager) tm[0], host)};
}
// if the host name in cert provided use it or use the host name
Copy link
Contributor

@nsidhaye nsidhaye Aug 5, 2017

Choose a reason for hiding this comment

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

In case of FIPS our driver should delegate responsibility of validating certificate to JVM.

In this case we are using our own TrustManager i.e. HostNameOverrideX509TrustManager which will throw following exception :

FIPS mode: only SunJSSE TrustManagers may be used

Ref: OpenJDK: SSLContextImpl

If I am correctly remember in order to remove error FIPS mode: only SunJSSE TrustManagers may be used we reviewed our FIPS implementation and added fips attribute.

If you want to get rid of fips attribute then you have to come up with function which will detect if JVM is in FIPS mode or not. You can find logic in our test cases as well as on internet. And then in case of configured FIPS one should not used custom created TrustManagers.

I will suggest instead of merging back in master / dev branch come up with FIPS or FIPSRnD branch and test with different FIPS implementation. If users are comfortable with changes; then merge back in main stream.

Remember to test with at-least following FIPS implementations:

  1. BouncyCastle
  2. IBM
  3. OpenJDK 9 (Not Tested yet)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you for pointing this out. I am able to reproduce the exception, will investigate and get back to you.

String trustStoreType = null;
String fipsProvider = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

Removing fipsProvider will not directly impact. But think of following cases:

You can configure BouncyCastle FIPS provider in two ways :

  1. By configuration files (java.security)
  2. Run time by passing FIPS provider .

I added fipsProvider for 2nd case.

Also on Oracle site mentioned following:

Configuring SunJSSE for FIPS Mode

SunJSSE is configured in FIPS mode by associating it with an appropriate FIPS 140 certified cryptographic provider that supplies the implementations for all cryptographic algorithms required by SunJSSE. This can be done in one of the following ways:

  1. edit the file ${java.home}/lib/security/java.security and modify the line that lists com.sun.net.ssl.internal.ssl.Provider to list the provider name of the FIPS 140 certified cryptographic provider. For example if the name of the cryptographic provider is SunPKCS11-NSS, change the line from

    security.provider.4=com.sun.net.ssl.internal.ssl.Provider`

    to

    security.provider.4=com.sun.net.ssl.internal.ssl.Provider SunPKCS11-NSS

    The class for the provider of the given name must also be listed as a security provider in the java.security file.

  2. at runtime, call the constructor of the SunJSSE provider that takes a java.security.Provider object as a parameter. For example, if the variable cryptoProvider is a reference to the cryptographic provider, call new com.sun.net.ssl.internal.ssl.Provider(cryptoProvider).

  3. at runtime, call the constructor of the SunJSSE provider that takes a String object as a parameter. For example if the cryptographic provider is called SunPKCS11-NSS call new com.sun.net.ssl.internal.ssl.Provider("SunPKCS11-NSS"). A provider with the specified name must be one of the configured security providers.

Within a given Java process, SunJSSE can be used either in FIPS mode or in default mode, but not both at the same time. Once SunJSSE has been initialized, it is not possible to change the mode. This means that if one of the runtime configuration options is used (option 2 or 3), the configuration must take place before any SSL/TLS operation.

Ref: Oracle FIPS

Copy link
Contributor Author

@ulvii ulvii Aug 8, 2017

Choose a reason for hiding this comment

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

Hi @nsidhaye ,
Thank you so much for detailed comments. We appreciate the time and effort.

As I mentioned above, if fipsProvider is not specified,KeyStore.getInstance() traverses the list of registered security Providers - Security.getProviders() and returns the matching KeyStore object.

Example, in case of option 3, user would make sure BouncyCastleFipsProvider is installed before creating a connection.

Security.addProvider(new org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider());
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider ("BCFIPS"));
ds.setTrustStoreType("BCFKS");
connection = (SQLServerConnection) ds.getConnection();

When the drivers calls KeyStore.getInstance(trustStoreType) before TLS Handshake, BCFIPS will already be in the list of installed providers.

Please let me know if I am missing something.

Copy link
Contributor Author

@ulvii ulvii Aug 8, 2017

Choose a reason for hiding this comment

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

After further investigation, I figured out the root cause of the issue,
Provider IBMJCEFIPS does not contain a keystore. When an application calls ds.setFIPSProvider("IBMJCEFIPS"); , the driver throws an exception, because there are no matching keystore types for IBMJCEFIPS. The users should use non-IBMJCEFIPS keystores to store the keys. See this page. This means, the provider that contains keystore is not necessarily the same as the provider that contains FIPS-complaint algorithms. Below is a sample app that would work for IBM users with the current implementation.

ds.setTrustStoreType("JCEKS");
ds.setFIPS(true);
ds.setFIPSProvider("IBMJCE");  //Not IBMJCEFIPS
connection = (SQLServerConnection) ds.getConnection();

This way we are not introducing any breaking changes, but the connection property fipsProvider has a confusing name.

Copy link
Contributor

@nsidhaye nsidhaye Aug 13, 2017

Choose a reason for hiding this comment

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

@ulvi :

In this case as FIPSProvider is non-FIPS it's not fip connection. One can test it by FipsEnvTest#isFips

ds.setTrustStoreType("JCEKS");
ds.setFIPS(true);
ds.setFIPSProvider("IBMJCE"); //Not IBMJCEFIPS
connection = (SQLServerConnection) ds.getConnection();

For one of user I forked out SSLProtocol which having 2 fixes:

  1. Configurable SSL Protocol (Which you already worked on)
  2. Made FIPSProvider optional as IBMFIPS does not like FIPSProvider while calling Keystore.getInstance(...) . (Need to test what happens in JDK 9 & Bouncy Castle for configurable configuration)

Unfortunately, we did not finalize on solution with user, but this worked on user environment with appropriate SSL certificate.

If you use my SSLProtocol fork and use following code for IBM FIPS.

//ds.setTrustStoreType("JCEKS"); (As per my understanding IBM works well with JKS too in FIPS)
ds.setFIPS(true);
//ds.setFIPSProvider("IBMJCE");  For IBM FIPS one should not set FIPSProvider.
connection = (SQLServerConnection) ds.getConnection();

Possibly @v-xiangs might have some information. Feel free to call me.

Copy link
Contributor Author

@ulvii ulvii Aug 13, 2017

Choose a reason for hiding this comment

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

Hi @nsidhaye ,
Thank you for the comments. I am definitely open to a discussion over a call. Please email me your contact details at v-ulibra@microsoft.com.

In this case as FIPSProvider is non-FIPS it's not fip connection.

fipsProvider connection property is only used to load the keys. Users will still have to create the keys using a FIPS-approved provider. Non FIPS provider keystores can be used to store those keys and this will not affect FIPS compliant mode. Please, take a look at this article., especially the last section.

One can test it by FipsEnvTest#isFips

Of course this test will fail if you pass in non-FIPS provider. That test just checks whether a provider is FIPS compliant or not, it does not check if FIPS mode is enabled. As I mentioned above, non FIPS provider is used to only store the keys.

If you use my SSLProtocol fork and use following code for IBM FIPS.

Let me explain what happens when you don't set fipsProvider property. In this case, since you did not specify the provider, the driver will traverse the registered providers and find the matching keystore. So if you set keystoreType to JKS, the matching provider that contains this Keystore is a non-FIPS provider. You can put a breakpoint at this line and check the provider name.

Made FIPSProvider optional as IBMFIPS does not like FIPSProvider while calling Keystore.getInstance(...)

Keystore.getInstance(storeType, "IBMJCEFIPS") does not work, because IBMJCEFIPS does not contain any keystores. That's why we need to use non-FIPS provider to store the keys. If the given provider contains the specified storeType, Keystore.getInstance(storeType, provider) is perfectly valid. See this page.

Thanks again for valuable comments and talk to you soon :)

@ulvii
Copy link
Contributor Author

ulvii commented Aug 25, 2017

Closing this PR and creating a new one which removes fipsProvider connection property only. #460

@ulvii ulvii closed this Aug 25, 2017
@ulvii ulvii deleted the FIPSFix2 branch August 31, 2017 23:52
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.

5 participants