test/jdk/sun/security/pkcs11/tls/tls12/FipsModeTLS12.java
changeset 54611 bebb82ef3434
parent 54584 2de1c3fa3e7d
child 55072 d0f73fccf5f3
equal deleted inserted replaced
54610:a9ab154b1384 54611:bebb82ef3434
       
     1 /*
       
     2  * Copyright (c) 2019, Red Hat, Inc.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 /*
       
    25  * @test
       
    26  * @bug 8029661
       
    27  * @summary Test TLS 1.2
       
    28  * @modules java.base/sun.security.internal.spec
       
    29  *          java.base/sun.security.util
       
    30  *          java.base/com.sun.crypto.provider
       
    31  * @library /test/lib ../..
       
    32  * @run main/othervm/timeout=120 -Djdk.tls.useExtendedMasterSecret=false FipsModeTLS12
       
    33  */
       
    34 
       
    35 import java.io.File;
       
    36 import java.io.FileInputStream;
       
    37 import java.io.InputStream;
       
    38 import java.nio.ByteBuffer;
       
    39 
       
    40 import java.security.PrivateKey;
       
    41 import java.security.PublicKey;
       
    42 import java.security.KeyStore;
       
    43 import java.security.NoSuchAlgorithmException;
       
    44 import java.security.Provider;
       
    45 import java.security.SecureRandom;
       
    46 import java.security.Security;
       
    47 
       
    48 import java.util.Arrays;
       
    49 import java.util.LinkedList;
       
    50 import java.util.List;
       
    51 
       
    52 import javax.crypto.Cipher;
       
    53 import javax.crypto.KeyGenerator;
       
    54 import javax.crypto.SecretKey;
       
    55 import javax.crypto.spec.SecretKeySpec;
       
    56 
       
    57 import javax.net.ssl.KeyManagerFactory;
       
    58 import javax.net.ssl.SSLContext;
       
    59 import javax.net.ssl.SSLEngine;
       
    60 import javax.net.ssl.SSLEngineResult;
       
    61 import javax.net.ssl.SSLEngineResult.HandshakeStatus;
       
    62 import javax.net.ssl.SSLParameters;
       
    63 import javax.net.ssl.SSLSession;
       
    64 import javax.net.ssl.TrustManagerFactory;
       
    65 
       
    66 import sun.security.internal.spec.TlsMasterSecretParameterSpec;
       
    67 import sun.security.internal.spec.TlsPrfParameterSpec;
       
    68 import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
       
    69 
       
    70 public final class FipsModeTLS12 extends SecmodTest {
       
    71 
       
    72     private static final boolean enableDebug = true;
       
    73 
       
    74     private static Provider sunPKCS11NSSProvider;
       
    75     private static Provider sunJCEProvider;
       
    76     private static KeyStore ks;
       
    77     private static KeyStore ts;
       
    78     private static char[] passphrase = "JAHshj131@@".toCharArray();
       
    79     private static PrivateKey privateKey;
       
    80     private static PublicKey publicKey;
       
    81 
       
    82     public static void main(String[] args) throws Exception {
       
    83         try {
       
    84             initialize();
       
    85         } catch (Exception e) {
       
    86             System.out.println("Test skipped: failure during" +
       
    87                     " initialization");
       
    88             if (enableDebug) {
       
    89                 System.out.println(e);
       
    90             }
       
    91             return;
       
    92         }
       
    93 
       
    94         if (shouldRun()) {
       
    95             // Test against JCE
       
    96             testTlsAuthenticationCodeGeneration();
       
    97 
       
    98             // Self-integrity test (complete TLS 1.2 communication)
       
    99             new testTLS12SunPKCS11Communication().run();
       
   100 
       
   101             System.out.println("Test PASS - OK");
       
   102         } else {
       
   103             System.out.println("Test skipped: TLS 1.2 mechanisms" +
       
   104                     " not supported by current SunPKCS11 back-end");
       
   105         }
       
   106     }
       
   107 
       
   108     private static boolean shouldRun() {
       
   109         if (sunPKCS11NSSProvider == null) {
       
   110             return false;
       
   111         }
       
   112         try {
       
   113             KeyGenerator.getInstance("SunTls12MasterSecret",
       
   114                     sunPKCS11NSSProvider);
       
   115             KeyGenerator.getInstance(
       
   116                     "SunTls12RsaPremasterSecret", sunPKCS11NSSProvider);
       
   117             KeyGenerator.getInstance("SunTls12Prf", sunPKCS11NSSProvider);
       
   118         } catch (NoSuchAlgorithmException e) {
       
   119             return false;
       
   120         }
       
   121         return true;
       
   122     }
       
   123 
       
   124     private static void testTlsAuthenticationCodeGeneration()
       
   125             throws Exception {
       
   126         // Generate RSA Pre-Master Secret in SunPKCS11 provider
       
   127         SecretKey rsaPreMasterSecret = null;
       
   128         @SuppressWarnings("deprecation")
       
   129         TlsRsaPremasterSecretParameterSpec rsaPreMasterSecretSpec =
       
   130                 new TlsRsaPremasterSecretParameterSpec(0x0303, 0x0303);
       
   131         {
       
   132             KeyGenerator rsaPreMasterSecretKG = KeyGenerator.getInstance(
       
   133                     "SunTls12RsaPremasterSecret", sunPKCS11NSSProvider);
       
   134             rsaPreMasterSecretKG.init(rsaPreMasterSecretSpec, null);
       
   135             rsaPreMasterSecret = rsaPreMasterSecretKG.generateKey();
       
   136         }
       
   137 
       
   138         // Get RSA Pre-Master Secret in plain (from SunPKCS11 provider)
       
   139         byte[] rsaPlainPreMasterSecret = null;
       
   140         {
       
   141             Cipher rsaPreMasterSecretWrapperCipher =
       
   142                     Cipher.getInstance("RSA/ECB/PKCS1Padding",
       
   143                             sunPKCS11NSSProvider);
       
   144             rsaPreMasterSecretWrapperCipher.init(Cipher.WRAP_MODE, publicKey,
       
   145                     new SecureRandom());
       
   146             byte[] rsaEncryptedPreMasterSecret =
       
   147                     rsaPreMasterSecretWrapperCipher.wrap(rsaPreMasterSecret);
       
   148             Cipher rsaPreMasterSecretUnwrapperCipher =
       
   149                     Cipher.getInstance("RSA/ECB/PKCS1Padding", sunJCEProvider);
       
   150             rsaPreMasterSecretUnwrapperCipher.init(Cipher.UNWRAP_MODE,
       
   151                     privateKey, rsaPreMasterSecretSpec);
       
   152             rsaPlainPreMasterSecret = rsaPreMasterSecretUnwrapperCipher.unwrap(
       
   153                     rsaEncryptedPreMasterSecret, "TlsRsaPremasterSecret",
       
   154                     Cipher.SECRET_KEY).getEncoded();
       
   155 
       
   156             if (enableDebug) {
       
   157                 System.out.println("rsaPlainPreMasterSecret:");
       
   158                 for (byte b : rsaPlainPreMasterSecret) {
       
   159                     System.out.printf("%02X, ", b);
       
   160                 }
       
   161                 System.out.println("");
       
   162             }
       
   163         }
       
   164 
       
   165         // Generate Master Secret
       
   166         SecretKey sunPKCS11MasterSecret = null;
       
   167         SecretKey jceMasterSecret = null;
       
   168         {
       
   169             KeyGenerator sunPKCS11MasterSecretGenerator =
       
   170                     KeyGenerator.getInstance("SunTls12MasterSecret",
       
   171                             sunPKCS11NSSProvider);
       
   172             KeyGenerator jceMasterSecretGenerator = KeyGenerator.getInstance(
       
   173                     "SunTls12MasterSecret", sunJCEProvider);
       
   174             @SuppressWarnings("deprecation")
       
   175             TlsMasterSecretParameterSpec sunPKCS11MasterSecretSpec =
       
   176                     new TlsMasterSecretParameterSpec(rsaPreMasterSecret, 3, 3,
       
   177                             new byte[32], new byte[32], "SHA-256", 32, 64);
       
   178             @SuppressWarnings("deprecation")
       
   179             TlsMasterSecretParameterSpec jceMasterSecretSpec =
       
   180                     new TlsMasterSecretParameterSpec(
       
   181                             new SecretKeySpec(rsaPlainPreMasterSecret,
       
   182                                     "Generic"), 3, 3, new byte[32],
       
   183                             new byte[32], "SHA-256", 32, 64);
       
   184             sunPKCS11MasterSecretGenerator.init(sunPKCS11MasterSecretSpec,
       
   185                     null);
       
   186             jceMasterSecretGenerator.init(jceMasterSecretSpec, null);
       
   187             sunPKCS11MasterSecret =
       
   188                     sunPKCS11MasterSecretGenerator.generateKey();
       
   189             jceMasterSecret = jceMasterSecretGenerator.generateKey();
       
   190             if (enableDebug) {
       
   191                 System.out.println("Master Secret (SunJCE):");
       
   192                 if (jceMasterSecret != null) {
       
   193                     for (byte b : jceMasterSecret.getEncoded()) {
       
   194                         System.out.printf("%02X, ", b);
       
   195                     }
       
   196                     System.out.println("");
       
   197                 }
       
   198             }
       
   199         }
       
   200 
       
   201         // Generate authentication codes
       
   202         byte[] sunPKCS11AuthenticationCode = null;
       
   203         byte[] jceAuthenticationCode = null;
       
   204         {
       
   205             // Generate SunPKCS11 authentication code
       
   206             {
       
   207                 @SuppressWarnings("deprecation")
       
   208                 TlsPrfParameterSpec sunPKCS11AuthenticationCodeSpec =
       
   209                         new TlsPrfParameterSpec(sunPKCS11MasterSecret,
       
   210                                 "client finished", "a".getBytes(), 12,
       
   211                                 "SHA-256", 32, 64);
       
   212                 KeyGenerator sunPKCS11AuthCodeGenerator =
       
   213                         KeyGenerator.getInstance("SunTls12Prf",
       
   214                                 sunPKCS11NSSProvider);
       
   215                 sunPKCS11AuthCodeGenerator.init(
       
   216                         sunPKCS11AuthenticationCodeSpec);
       
   217                 sunPKCS11AuthenticationCode =
       
   218                         sunPKCS11AuthCodeGenerator.generateKey().getEncoded();
       
   219             }
       
   220 
       
   221             // Generate SunJCE authentication code
       
   222             {
       
   223                 @SuppressWarnings("deprecation")
       
   224                 TlsPrfParameterSpec jceAuthenticationCodeSpec =
       
   225                         new TlsPrfParameterSpec(jceMasterSecret,
       
   226                                 "client finished", "a".getBytes(), 12,
       
   227                                 "SHA-256", 32, 64);
       
   228                 KeyGenerator jceAuthCodeGenerator =
       
   229                         KeyGenerator.getInstance("SunTls12Prf",
       
   230                                 sunJCEProvider);
       
   231                 jceAuthCodeGenerator.init(jceAuthenticationCodeSpec);
       
   232                 jceAuthenticationCode =
       
   233                         jceAuthCodeGenerator.generateKey().getEncoded();
       
   234             }
       
   235 
       
   236             if (enableDebug) {
       
   237                 System.out.println("SunPKCS11 Authentication Code: ");
       
   238                 for (byte b : sunPKCS11AuthenticationCode) {
       
   239                     System.out.printf("%02X, ", b);
       
   240                 }
       
   241                 System.out.println("");
       
   242                 System.out.println("SunJCE Authentication Code: ");
       
   243                 for (byte b : jceAuthenticationCode) {
       
   244                     System.out.printf("%02X, ", b);
       
   245                 }
       
   246                 System.out.println("");
       
   247             }
       
   248         }
       
   249 
       
   250         if (sunPKCS11AuthenticationCode == null ||
       
   251                 jceAuthenticationCode == null ||
       
   252                 sunPKCS11AuthenticationCode.length == 0 ||
       
   253                 jceAuthenticationCode.length == 0 ||
       
   254                 !Arrays.equals(sunPKCS11AuthenticationCode,
       
   255                         jceAuthenticationCode)) {
       
   256             throw new Exception("Authentication codes from JCE" +
       
   257                         " and SunPKCS11 differ.");
       
   258         }
       
   259     }
       
   260 
       
   261     private static class testTLS12SunPKCS11Communication {
       
   262         public static void run() throws Exception {
       
   263             SSLEngine[][] enginesToTest = getSSLEnginesToTest();
       
   264 
       
   265             for (SSLEngine[] engineToTest : enginesToTest) {
       
   266 
       
   267                 SSLEngine clientSSLEngine = engineToTest[0];
       
   268                 SSLEngine serverSSLEngine = engineToTest[1];
       
   269 
       
   270                 // SSLEngine code based on RedhandshakeFinished.java
       
   271 
       
   272                 boolean dataDone = false;
       
   273 
       
   274                 ByteBuffer clientOut = null;
       
   275                 ByteBuffer clientIn = null;
       
   276                 ByteBuffer serverOut = null;
       
   277                 ByteBuffer serverIn = null;
       
   278                 ByteBuffer cTOs;
       
   279                 ByteBuffer sTOc;
       
   280 
       
   281                 SSLSession session = clientSSLEngine.getSession();
       
   282                 int appBufferMax = session.getApplicationBufferSize();
       
   283                 int netBufferMax = session.getPacketBufferSize();
       
   284 
       
   285                 clientIn = ByteBuffer.allocate(appBufferMax + 50);
       
   286                 serverIn = ByteBuffer.allocate(appBufferMax + 50);
       
   287 
       
   288                 cTOs = ByteBuffer.allocateDirect(netBufferMax);
       
   289                 sTOc = ByteBuffer.allocateDirect(netBufferMax);
       
   290 
       
   291                 clientOut = ByteBuffer.wrap(
       
   292                         "Hi Server, I'm Client".getBytes());
       
   293                 serverOut = ByteBuffer.wrap(
       
   294                         "Hello Client, I'm Server".getBytes());
       
   295 
       
   296                 SSLEngineResult clientResult;
       
   297                 SSLEngineResult serverResult;
       
   298 
       
   299                 while (!dataDone) {
       
   300                     clientResult = clientSSLEngine.wrap(clientOut, cTOs);
       
   301                     runDelegatedTasks(clientResult, clientSSLEngine);
       
   302                     serverResult = serverSSLEngine.wrap(serverOut, sTOc);
       
   303                     runDelegatedTasks(serverResult, serverSSLEngine);
       
   304                     cTOs.flip();
       
   305                     sTOc.flip();
       
   306 
       
   307                     if (enableDebug) {
       
   308                         System.out.println("Client -> Network");
       
   309                         printTlsNetworkPacket("", cTOs);
       
   310                         System.out.println("");
       
   311                         System.out.println("Server -> Network");
       
   312                         printTlsNetworkPacket("", sTOc);
       
   313                         System.out.println("");
       
   314                     }
       
   315 
       
   316                     clientResult = clientSSLEngine.unwrap(sTOc, clientIn);
       
   317                     runDelegatedTasks(clientResult, clientSSLEngine);
       
   318                     serverResult = serverSSLEngine.unwrap(cTOs, serverIn);
       
   319                     runDelegatedTasks(serverResult, serverSSLEngine);
       
   320 
       
   321                     cTOs.compact();
       
   322                     sTOc.compact();
       
   323 
       
   324                     if (!dataDone &&
       
   325                             (clientOut.limit() == serverIn.position()) &&
       
   326                             (serverOut.limit() == clientIn.position())) {
       
   327                         checkTransfer(serverOut, clientIn);
       
   328                         checkTransfer(clientOut, serverIn);
       
   329                         dataDone = true;
       
   330                     }
       
   331                 }
       
   332             }
       
   333         }
       
   334 
       
   335         static void printTlsNetworkPacket(String prefix, ByteBuffer bb) {
       
   336             ByteBuffer slice = bb.slice();
       
   337             byte[] buffer = new byte[slice.remaining()];
       
   338             slice.get(buffer);
       
   339             for (int i = 0; i < buffer.length; i++) {
       
   340                 System.out.printf("%02X, ", (byte)(buffer[i] & (byte)0xFF));
       
   341                 if (i % 8 == 0 && i % 16 != 0) {
       
   342                     System.out.print(" ");
       
   343                 }
       
   344                 if (i % 16 == 0) {
       
   345                     System.out.println("");
       
   346                 }
       
   347             }
       
   348             System.out.flush();
       
   349         }
       
   350 
       
   351         private static void checkTransfer(ByteBuffer a, ByteBuffer b)
       
   352                 throws Exception {
       
   353             a.flip();
       
   354             b.flip();
       
   355             if (!a.equals(b)) {
       
   356                 throw new Exception("Data didn't transfer cleanly");
       
   357             }
       
   358             a.position(a.limit());
       
   359             b.position(b.limit());
       
   360             a.limit(a.capacity());
       
   361             b.limit(b.capacity());
       
   362         }
       
   363 
       
   364         private static void runDelegatedTasks(SSLEngineResult result,
       
   365                 SSLEngine engine) throws Exception {
       
   366 
       
   367             if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
       
   368                 Runnable runnable;
       
   369                 while ((runnable = engine.getDelegatedTask()) != null) {
       
   370                     runnable.run();
       
   371                 }
       
   372                 HandshakeStatus hsStatus = engine.getHandshakeStatus();
       
   373                 if (hsStatus == HandshakeStatus.NEED_TASK) {
       
   374                     throw new Exception(
       
   375                         "handshake shouldn't need additional tasks");
       
   376                 }
       
   377             }
       
   378         }
       
   379 
       
   380         private static SSLEngine[][] getSSLEnginesToTest() throws Exception {
       
   381             SSLEngine[][] enginesToTest = new SSLEngine[2][2];
       
   382             String[][] preferredSuites = new String[][]{ new String[] {
       
   383                     "TLS_RSA_WITH_AES_128_CBC_SHA256"
       
   384             },  new String[] {
       
   385                     "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"
       
   386             }};
       
   387             for (int i = 0; i < enginesToTest.length; i++) {
       
   388                 enginesToTest[i][0] = createSSLEngine(true);
       
   389                 enginesToTest[i][1] = createSSLEngine(false);
       
   390                 enginesToTest[i][0].setEnabledCipherSuites(preferredSuites[i]);
       
   391                 enginesToTest[i][1].setEnabledCipherSuites(preferredSuites[i]);
       
   392             }
       
   393             return enginesToTest;
       
   394         }
       
   395 
       
   396         static private SSLEngine createSSLEngine(boolean client)
       
   397                 throws Exception {
       
   398             SSLEngine ssle;
       
   399             KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX", "SunJSSE");
       
   400             kmf.init(ks, passphrase);
       
   401 
       
   402             TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX", "SunJSSE");
       
   403             tmf.init(ts);
       
   404 
       
   405             SSLContext sslCtx = SSLContext.getInstance("TLSv1.2", "SunJSSE");
       
   406             sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
       
   407             ssle = sslCtx.createSSLEngine("localhost", 443);
       
   408             ssle.setUseClientMode(client);
       
   409             SSLParameters sslParameters = ssle.getSSLParameters();
       
   410             ssle.setSSLParameters(sslParameters);
       
   411 
       
   412             return ssle;
       
   413         }
       
   414     }
       
   415 
       
   416     private static void initialize() throws Exception {
       
   417         //
       
   418         // For a successful FIPS-mode TLS connection, the following
       
   419         // cryptographic providers will be installed:
       
   420         //
       
   421         //  1. SunPKCS11 (with an NSS FIPS mode backend)
       
   422         //  2. SUN (to handle X.509 certificates)
       
   423         //  3. SunJSSE (for a TLS engine)
       
   424         //
       
   425         // RSASSA-PSS algorithm is not currently supported in SunPKCS11
       
   426         // but in SUN provider. As a result, it can be negotiated by the
       
   427         // TLS engine. The problem is that SunPKCS11 keys are sensitive
       
   428         // in FIPS mode and cannot be used in a SUN algorithm (conversion
       
   429         // fails as plain values cannot be extracted).
       
   430         //
       
   431         // To workaround this issue, we disable RSASSA-PSS algorithm for
       
   432         // TLS connections. Once JDK-8222937 is fixed, this workaround can
       
   433         // (and should) be removed.
       
   434         //
       
   435         // On a final note, the list of disabled TLS algorithms
       
   436         // (jdk.tls.disabledAlgorithms) has to be updated at this point,
       
   437         // before it is read in sun.security.ssl.SSLAlgorithmConstraints
       
   438         // class initialization.
       
   439         String disabledAlgorithms =
       
   440                 Security.getProperty("jdk.tls.disabledAlgorithms");
       
   441         if (disabledAlgorithms.length() > 0) {
       
   442             disabledAlgorithms += ", ";
       
   443         }
       
   444         disabledAlgorithms += "RSASSA-PSS";
       
   445         Security.setProperty("jdk.tls.disabledAlgorithms", disabledAlgorithms);
       
   446 
       
   447         if (initSecmod() == false) {
       
   448             return;
       
   449         }
       
   450         String configName = BASE + SEP + "nss.cfg";
       
   451         sunPKCS11NSSProvider = getSunPKCS11(configName);
       
   452         System.out.println("SunPKCS11 provider: " + sunPKCS11NSSProvider);
       
   453 
       
   454         List<Provider> installedProviders = new LinkedList<>();
       
   455         for (Provider p : Security.getProviders()){
       
   456             installedProviders.add(p);
       
   457             Security.removeProvider(p.getName());
       
   458         }
       
   459         Security.addProvider(sunPKCS11NSSProvider);
       
   460         for (Provider p : installedProviders){
       
   461             String providerName = p.getName();
       
   462             if (providerName.equals("SunJSSE") ||
       
   463                     providerName.equals("SUN") ||
       
   464                     providerName.equals("SunJCE")) {
       
   465                 Security.addProvider(p);
       
   466                 if (providerName.equals("SunJCE")) {
       
   467                     sunJCEProvider = p;
       
   468                 }
       
   469             }
       
   470         }
       
   471 
       
   472         ks = KeyStore.getInstance("PKCS11", sunPKCS11NSSProvider);
       
   473         ks.load(null, "test12".toCharArray());
       
   474         ts = ks;
       
   475 
       
   476         KeyStore ksPlain = readTestKeyStore();
       
   477         privateKey = (PrivateKey)ksPlain.getKey("rh_rsa_sha256",
       
   478                 passphrase);
       
   479         publicKey = (PublicKey)ksPlain.getCertificate(
       
   480                 "rh_rsa_sha256").getPublicKey();
       
   481     }
       
   482 
       
   483     private static KeyStore readTestKeyStore() throws Exception {
       
   484         File file = new File(System.getProperty("test.src", "."), "keystore");
       
   485         InputStream in = new FileInputStream(file);
       
   486         KeyStore ks = KeyStore.getInstance("JKS");
       
   487         ks.load(in, "passphrase".toCharArray());
       
   488         in.close();
       
   489         return ks;
       
   490     }
       
   491 }