Bug 61583

Summary: Regression in PKCS11 keystores - incorrect alias being used
Product: Tomcat 8 Reporter: Daniel Ruggeri <DRuggeri>
Component: ConnectorsAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: normal CC: DRuggeri, jfclere
Priority: P2    
Version: 8.5.23   
Target Milestone: ----   
Hardware: PC   
OS: Linux   

Description Daniel Ruggeri 2017-10-03 14:30:02 UTC
After upgrading from 8.5.16 to 8.5.20, PKCS11 support was broken due to #61451. Upon receiving release announcement for 8.5.23 and testing (somehow missed 8.5.21), PKCS11 support still appears broken because it does not honor the key alias set on the connector. I have verified that 8.5.21 also displays the same behavior.

The testing configuration uses a single PKCS11 keystore (backed by NSS) with three keys inside: admin, server and client. The testing suite configures Tomcat with two connectors, one for administrative access and a second for "business" access. Upon running the test suite, Tomcat consistently uses the client certificate for both the server and administrative connectors. When examining the keystore with a java program, the client certificate is the first key in the store.

Example connector:
    <Connector name="https"
               enableLookups="false"
               xpoweredBy="false"
               address="192.168.40.216"
               scheme="https"
               server="server"
               port="25004"
               secure="true"
               maxHttpHeaderSize="8192"
               SSLEnabled="true"
               clientAuth="false"
               sslProtocol="TLS"
               sslEnabledProtocols="SSLv2Hello,TLSv1.1,TLSv1.2"
               ciphers="TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA"
               keyAlias="tomcatserver"
               keystoreFile="/tmp/pkcs11.0.cfg"
               keystorePass="nss"
               keystoreType="PKCS11"
               truststoreFile="/tmp/trust.jks"
               truststoreType="JKS"
               />


Store contents of NSS database:
$ certutil -d /tmp/pkcs11 -K
certutil: Checking token "NSS FIPS 140-2 Certificate DB" in slot "NSS FIPS 140-2 User Private Key Services"
Enter Password or Pin for "NSS FIPS 140-2 Certificate DB":
< 0> rsa      40261c884934d113672666784953129ea53a6492   NSS FIPS 140-2 Certificate DB:tomcatadmin
< 1> rsa      dba317a2b93e771032c0b5fafb019649229dcc7c   NSS FIPS 140-2 Certificate DB:tomcatserver
< 2> rsa      6ed07ff1e609c5daa965bf152004e1212177a87f   NSS FIPS 140-2 Certificate DB:tomcatclient

Viewed as a KeyStore object and iterating over the keys:
x509 test application
Keystore loaded
Certificate: tomcatclient (key entry)
Certificate: tomcatserver (key entry)
Certificate: tomcatadmin (key entry)

If there is any debug logging information I can provide, please let me know.
Comment 1 Daniel Ruggeri 2017-10-03 14:31:07 UTC
Also, as a side comment, I would be happy to help produce tests to catch these during release. I'm not sure where to start, but am motivated to assist.
Comment 2 Remy Maucherat 2017-10-03 15:00:02 UTC
It is true the alias setting will now only work if the key type is PKCS8.
Comment 3 Remy Maucherat 2017-10-03 15:18:10 UTC
After investigating, it would seem r1800874 has to be partially reverted since we cannot put the non PKCS8 key in the in memory keystore and may have to use the JSSEKeyManager wrapper instead. Unless it is always possible to do the memory keystore creation with other types [and go with putting the key there], in which case the condition "PKCS#8".equalsIgnoreCase(k.getFormat()) can simply be removed.

Unfortunately, no test case here to make sure I don't do anything wrong.
Comment 4 Daniel Ruggeri 2017-10-03 15:53:42 UTC
Sure, understood. If you can provide a jar, I can do testing to verify the change before committing.

Thinking about the ability to test this ongoing, I *think* that the Oracle PKCS11 provider works in software on Solaris, Linux and Windows. I can try putting together some test code if you think it would be worth doing.
Comment 5 Mark Thomas 2017-10-03 18:31:26 UTC
I agree with Rémy's analysis.

Since I messed this up, I'm happy to take a look at getting it fixed. First step will be setting up a software PKCS11 keystore for testing. Any pointers appreciated.
Comment 6 Mark Thomas 2017-10-03 20:38:12 UTC
I think I have fixed this. Snapshot build available here:
http://people.apache.org/~markt/dev/v8.5.24-dev/

If you could test and provide feedback that will be great.

Note: This is a snapshot, not an official release. It is intended for testing this issue only. If your server catches fire when you install it you are on your own, etc.
Comment 7 Daniel Ruggeri 2017-10-03 21:52:40 UTC
Hi, Mark;
   I can confirm that the preview build you shared corrects the problem... and I even detected no smoke!

   For testing, I was mistaken. The SunPKCS11 Provider does, indeed, ship on all Solaris, Windows and Linux builds but does not include a backing PKCS11 implementation - that's still separate. Can you help me understand what flexibility exists in the testing infrastructure for Tomcat? The way I test this in our environment is with NSS which is free, provides a PCKS11 implementation and is available on RedHat and Debian derivatives. If you have a Windows or Linux VM to do said testing, I can provide scripts that will generate the stores. I could also throw together a Dockerfile if docker is a thing for you.
Comment 8 Mark Thomas 2017-10-04 18:16:44 UTC
All of our testing is based around JUnit. Some variation of the unit tests in o.a.tomcat.util.net is probably required. Making them optional depending on the presence of NSS is probably the way to go. You should be able to re-use the keys/certs in that location.