test/jdk/sun/security/pkcs11/fips/TestTLS12.java
changeset 53734 cb1642ccc732
parent 53733 b5d45c2fe8a0
child 53735 fedc89081b57
equal deleted inserted replaced
53733:b5d45c2fe8a0 53734:cb1642ccc732
     1 /*
       
     2  * Copyright (c) 2018, 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.net.ssl.internal.ssl
       
    31  *          java.base/com.sun.crypto.provider
       
    32  * @library /test/lib ..
       
    33  * @run main/othervm/timeout=120 TestTLS12
       
    34  */
       
    35 
       
    36 import java.io.File;
       
    37 import java.io.FileInputStream;
       
    38 import java.io.InputStream;
       
    39 import java.nio.ByteBuffer;
       
    40 
       
    41 import java.security.interfaces.RSAPrivateKey;
       
    42 import java.security.interfaces.RSAPublicKey;
       
    43 import java.security.KeyStore;
       
    44 import java.security.NoSuchAlgorithmException;
       
    45 import java.security.Provider;
       
    46 import java.security.SecureRandom;
       
    47 import java.security.Security;
       
    48 
       
    49 import java.util.Arrays;
       
    50 
       
    51 import javax.crypto.Cipher;
       
    52 import javax.crypto.KeyGenerator;
       
    53 import javax.crypto.SecretKey;
       
    54 import javax.crypto.spec.SecretKeySpec;
       
    55 
       
    56 import javax.net.ssl.KeyManagerFactory;
       
    57 import javax.net.ssl.SSLContext;
       
    58 import javax.net.ssl.SSLEngine;
       
    59 import javax.net.ssl.SSLEngineResult;
       
    60 import javax.net.ssl.SSLEngineResult.HandshakeStatus;
       
    61 import javax.net.ssl.SSLParameters;
       
    62 import javax.net.ssl.SSLSession;
       
    63 import javax.net.ssl.TrustManagerFactory;
       
    64 
       
    65 import sun.security.internal.spec.TlsMasterSecretParameterSpec;
       
    66 import sun.security.internal.spec.TlsPrfParameterSpec;
       
    67 import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
       
    68 
       
    69 public final class TestTLS12 extends SecmodTest {
       
    70 
       
    71     private static final boolean enableDebug = true;
       
    72 
       
    73     private static Provider sunPKCS11NSSProvider;
       
    74     private static Provider sunJCEProvider;
       
    75     private static com.sun.net.ssl.internal.ssl.Provider jsseProvider;
       
    76     private static KeyStore ks;
       
    77     private static KeyStore ts;
       
    78     private static char[] passphrase = "JAHshj131@@".toCharArray();
       
    79     private static RSAPrivateKey privateKey;
       
    80     private static RSAPublicKey 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             return;
       
    89         }
       
    90 
       
    91         if (shouldRun()) {
       
    92             // Test against JCE
       
    93             testTlsAuthenticationCodeGeneration();
       
    94 
       
    95             // Self-integrity test (complete TLS 1.2 communication)
       
    96             new testTLS12SunPKCS11Communication().run();
       
    97 
       
    98             System.out.println("Test PASS - OK");
       
    99         } else {
       
   100             System.out.println("Test skipped: TLS 1.2 mechanisms" +
       
   101                     " not supported by current SunPKCS11 back-end");
       
   102         }
       
   103     }
       
   104 
       
   105     private static boolean shouldRun() {
       
   106         if (sunPKCS11NSSProvider == null) {
       
   107             return false;
       
   108         }
       
   109         try {
       
   110             KeyGenerator.getInstance("SunTls12MasterSecret",
       
   111                     sunPKCS11NSSProvider);
       
   112             KeyGenerator.getInstance(
       
   113                     "SunTls12RsaPremasterSecret", sunPKCS11NSSProvider);
       
   114             KeyGenerator.getInstance("SunTls12Prf", sunPKCS11NSSProvider);
       
   115         } catch (NoSuchAlgorithmException e) {
       
   116             return false;
       
   117         }
       
   118         return true;
       
   119     }
       
   120 
       
   121     private static void testTlsAuthenticationCodeGeneration()
       
   122             throws Exception {
       
   123         // Generate RSA Pre-Master Secret in SunPKCS11 provider
       
   124         SecretKey rsaPreMasterSecret = null;
       
   125         @SuppressWarnings("deprecation")
       
   126         TlsRsaPremasterSecretParameterSpec rsaPreMasterSecretSpec =
       
   127                 new TlsRsaPremasterSecretParameterSpec(0x0303, 0x0303);
       
   128         {
       
   129             KeyGenerator rsaPreMasterSecretKG = KeyGenerator.getInstance(
       
   130                     "SunTls12RsaPremasterSecret", sunPKCS11NSSProvider);
       
   131             rsaPreMasterSecretKG.init(rsaPreMasterSecretSpec, null);
       
   132             rsaPreMasterSecret = rsaPreMasterSecretKG.generateKey();
       
   133         }
       
   134 
       
   135         // Get RSA Pre-Master Secret in plain (from SunPKCS11 provider)
       
   136         byte[] rsaPlainPreMasterSecret = null;
       
   137         {
       
   138             Cipher rsaPreMasterSecretWrapperCipher =
       
   139                     Cipher.getInstance("RSA/ECB/PKCS1Padding",
       
   140                             sunPKCS11NSSProvider);
       
   141             rsaPreMasterSecretWrapperCipher.init(Cipher.WRAP_MODE, publicKey,
       
   142                     new SecureRandom());
       
   143             byte[] rsaEncryptedPreMasterSecret =
       
   144                     rsaPreMasterSecretWrapperCipher.wrap(rsaPreMasterSecret);
       
   145             Cipher rsaPreMasterSecretUnwrapperCipher =
       
   146                     Cipher.getInstance("RSA/ECB/PKCS1Padding", sunJCEProvider);
       
   147             rsaPreMasterSecretUnwrapperCipher.init(Cipher.UNWRAP_MODE,
       
   148                     privateKey, rsaPreMasterSecretSpec);
       
   149             rsaPlainPreMasterSecret = rsaPreMasterSecretUnwrapperCipher.unwrap(
       
   150                     rsaEncryptedPreMasterSecret, "TlsRsaPremasterSecret",
       
   151                     Cipher.SECRET_KEY).getEncoded();
       
   152 
       
   153             if (enableDebug) {
       
   154                 System.out.println("rsaPlainPreMasterSecret:");
       
   155                 for (byte b : rsaPlainPreMasterSecret) {
       
   156                     System.out.printf("%02X, ", b);
       
   157                 }
       
   158                 System.out.println("");
       
   159             }
       
   160         }
       
   161 
       
   162         // Generate Master Secret
       
   163         SecretKey sunPKCS11MasterSecret = null;
       
   164         SecretKey jceMasterSecret = null;
       
   165         {
       
   166             KeyGenerator sunPKCS11MasterSecretGenerator =
       
   167                     KeyGenerator.getInstance("SunTls12MasterSecret",
       
   168                             sunPKCS11NSSProvider);
       
   169             KeyGenerator jceMasterSecretGenerator = KeyGenerator.getInstance(
       
   170                     "SunTls12MasterSecret", sunJCEProvider);
       
   171             @SuppressWarnings("deprecation")
       
   172             TlsMasterSecretParameterSpec sunPKCS11MasterSecretSpec =
       
   173                     new TlsMasterSecretParameterSpec(rsaPreMasterSecret, 3, 3,
       
   174                             new byte[32], new byte[32], "SHA-256", 32, 64);
       
   175             @SuppressWarnings("deprecation")
       
   176             TlsMasterSecretParameterSpec jceMasterSecretSpec =
       
   177                     new TlsMasterSecretParameterSpec(
       
   178                             new SecretKeySpec(rsaPlainPreMasterSecret,
       
   179                                     "Generic"), 3, 3, new byte[32],
       
   180                             new byte[32], "SHA-256", 32, 64);
       
   181             sunPKCS11MasterSecretGenerator.init(sunPKCS11MasterSecretSpec,
       
   182                     null);
       
   183             jceMasterSecretGenerator.init(jceMasterSecretSpec, null);
       
   184             sunPKCS11MasterSecret =
       
   185                     sunPKCS11MasterSecretGenerator.generateKey();
       
   186             jceMasterSecret = jceMasterSecretGenerator.generateKey();
       
   187             if (enableDebug) {
       
   188                 System.out.println("Master Secret (SunJCE):");
       
   189                 if (jceMasterSecret != null) {
       
   190                     for (byte b : jceMasterSecret.getEncoded()) {
       
   191                         System.out.printf("%02X, ", b);
       
   192                     }
       
   193                     System.out.println("");
       
   194                 }
       
   195             }
       
   196         }
       
   197 
       
   198         // Generate authentication codes
       
   199         byte[] sunPKCS11AuthenticationCode = null;
       
   200         byte[] jceAuthenticationCode = null;
       
   201         {
       
   202             // Generate SunPKCS11 authentication code
       
   203             {
       
   204                 @SuppressWarnings("deprecation")
       
   205                 TlsPrfParameterSpec sunPKCS11AuthenticationCodeSpec =
       
   206                         new TlsPrfParameterSpec(sunPKCS11MasterSecret,
       
   207                                 "client finished", "a".getBytes(), 12,
       
   208                                 "SHA-256", 32, 64);
       
   209                 KeyGenerator sunPKCS11AuthCodeGenerator =
       
   210                         KeyGenerator.getInstance("SunTls12Prf",
       
   211                                 sunPKCS11NSSProvider);
       
   212                 sunPKCS11AuthCodeGenerator.init(
       
   213                         sunPKCS11AuthenticationCodeSpec);
       
   214                 sunPKCS11AuthenticationCode =
       
   215                         sunPKCS11AuthCodeGenerator.generateKey().getEncoded();
       
   216             }
       
   217 
       
   218             // Generate SunJCE authentication code
       
   219             {
       
   220                 @SuppressWarnings("deprecation")
       
   221                 TlsPrfParameterSpec jceAuthenticationCodeSpec =
       
   222                         new TlsPrfParameterSpec(jceMasterSecret,
       
   223                                 "client finished", "a".getBytes(), 12,
       
   224                                 "SHA-256", 32, 64);
       
   225                 KeyGenerator jceAuthCodeGenerator =
       
   226                         KeyGenerator.getInstance("SunTls12Prf",
       
   227                                 sunJCEProvider);
       
   228                 jceAuthCodeGenerator.init(jceAuthenticationCodeSpec);
       
   229                 jceAuthenticationCode =
       
   230                         jceAuthCodeGenerator.generateKey().getEncoded();
       
   231             }
       
   232 
       
   233             if (enableDebug) {
       
   234                 System.out.println("SunPKCS11 Authentication Code: ");
       
   235                 for (byte b : sunPKCS11AuthenticationCode) {
       
   236                     System.out.printf("%02X, ", b);
       
   237                 }
       
   238                 System.out.println("");
       
   239                 System.out.println("SunJCE Authentication Code: ");
       
   240                 for (byte b : jceAuthenticationCode) {
       
   241                     System.out.printf("%02X, ", b);
       
   242                 }
       
   243                 System.out.println("");
       
   244             }
       
   245         }
       
   246 
       
   247         if (sunPKCS11AuthenticationCode == null ||
       
   248                 jceAuthenticationCode == null ||
       
   249                 sunPKCS11AuthenticationCode.length == 0 ||
       
   250                 jceAuthenticationCode.length == 0 ||
       
   251                 !Arrays.equals(sunPKCS11AuthenticationCode,
       
   252                         jceAuthenticationCode)) {
       
   253             throw new Exception("Authentication codes from JCE" +
       
   254                         " and SunPKCS11 differ.");
       
   255         }
       
   256     }
       
   257 
       
   258     private static class testTLS12SunPKCS11Communication {
       
   259         public static void run() throws Exception {
       
   260             SSLEngine[][] enginesToTest = getSSLEnginesToTest();
       
   261 
       
   262             for (SSLEngine[] engineToTest : enginesToTest) {
       
   263 
       
   264                 SSLEngine clientSSLEngine = engineToTest[0];
       
   265                 SSLEngine serverSSLEngine = engineToTest[1];
       
   266 
       
   267                 // SSLEngine code based on RedhandshakeFinished.java
       
   268 
       
   269                 boolean dataDone = false;
       
   270 
       
   271                 ByteBuffer clientOut = null;
       
   272                 ByteBuffer clientIn = null;
       
   273                 ByteBuffer serverOut = null;
       
   274                 ByteBuffer serverIn = null;
       
   275                 ByteBuffer cTOs;
       
   276                 ByteBuffer sTOc;
       
   277 
       
   278                 SSLSession session = clientSSLEngine.getSession();
       
   279                 int appBufferMax = session.getApplicationBufferSize();
       
   280                 int netBufferMax = session.getPacketBufferSize();
       
   281 
       
   282                 clientIn = ByteBuffer.allocate(appBufferMax + 50);
       
   283                 serverIn = ByteBuffer.allocate(appBufferMax + 50);
       
   284 
       
   285                 cTOs = ByteBuffer.allocateDirect(netBufferMax);
       
   286                 sTOc = ByteBuffer.allocateDirect(netBufferMax);
       
   287 
       
   288                 clientOut = ByteBuffer.wrap(
       
   289                         "Hi Server, I'm Client".getBytes());
       
   290                 serverOut = ByteBuffer.wrap(
       
   291                         "Hello Client, I'm Server".getBytes());
       
   292 
       
   293                 SSLEngineResult clientResult;
       
   294                 SSLEngineResult serverResult;
       
   295 
       
   296                 while (!dataDone) {
       
   297                     clientResult = clientSSLEngine.wrap(clientOut, cTOs);
       
   298                     runDelegatedTasks(clientResult, clientSSLEngine);
       
   299                     serverResult = serverSSLEngine.wrap(serverOut, sTOc);
       
   300                     runDelegatedTasks(serverResult, serverSSLEngine);
       
   301                     cTOs.flip();
       
   302                     sTOc.flip();
       
   303 
       
   304                     if (enableDebug) {
       
   305                         System.out.println("Client -> Network");
       
   306                         printTlsNetworkPacket("", cTOs);
       
   307                         System.out.println("");
       
   308                         System.out.println("Server -> Network");
       
   309                         printTlsNetworkPacket("", sTOc);
       
   310                         System.out.println("");
       
   311                     }
       
   312 
       
   313                     clientResult = clientSSLEngine.unwrap(sTOc, clientIn);
       
   314                     runDelegatedTasks(clientResult, clientSSLEngine);
       
   315                     serverResult = serverSSLEngine.unwrap(cTOs, serverIn);
       
   316                     runDelegatedTasks(serverResult, serverSSLEngine);
       
   317 
       
   318                     cTOs.compact();
       
   319                     sTOc.compact();
       
   320 
       
   321                     if (!dataDone &&
       
   322                             (clientOut.limit() == serverIn.position()) &&
       
   323                             (serverOut.limit() == clientIn.position())) {
       
   324                         checkTransfer(serverOut, clientIn);
       
   325                         checkTransfer(clientOut, serverIn);
       
   326                         dataDone = true;
       
   327                     }
       
   328                 }
       
   329             }
       
   330         }
       
   331 
       
   332         static void printTlsNetworkPacket(String prefix, ByteBuffer bb) {
       
   333             ByteBuffer slice = bb.slice();
       
   334             byte[] buffer = new byte[slice.remaining()];
       
   335             slice.get(buffer);
       
   336             for (int i = 0; i < buffer.length; i++) {
       
   337                 System.out.printf("%02X, ", (byte)(buffer[i] & (byte)0xFF));
       
   338                 if (i % 8 == 0 && i % 16 != 0) {
       
   339                     System.out.print(" ");
       
   340                 }
       
   341                 if (i % 16 == 0) {
       
   342                     System.out.println("");
       
   343                 }
       
   344             }
       
   345             System.out.flush();
       
   346         }
       
   347 
       
   348         private static void checkTransfer(ByteBuffer a, ByteBuffer b)
       
   349                 throws Exception {
       
   350             a.flip();
       
   351             b.flip();
       
   352             if (!a.equals(b)) {
       
   353                 throw new Exception("Data didn't transfer cleanly");
       
   354             }
       
   355             a.position(a.limit());
       
   356             b.position(b.limit());
       
   357             a.limit(a.capacity());
       
   358             b.limit(b.capacity());
       
   359         }
       
   360 
       
   361         private static void runDelegatedTasks(SSLEngineResult result,
       
   362                 SSLEngine engine) throws Exception {
       
   363 
       
   364             if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
       
   365                 Runnable runnable;
       
   366                 while ((runnable = engine.getDelegatedTask()) != null) {
       
   367                     runnable.run();
       
   368                 }
       
   369                 HandshakeStatus hsStatus = engine.getHandshakeStatus();
       
   370                 if (hsStatus == HandshakeStatus.NEED_TASK) {
       
   371                     throw new Exception(
       
   372                         "handshake shouldn't need additional tasks");
       
   373                 }
       
   374             }
       
   375         }
       
   376 
       
   377         private static SSLEngine[][] getSSLEnginesToTest() throws Exception {
       
   378             SSLEngine[][] enginesToTest = new SSLEngine[2][2];
       
   379             String[][] preferredSuites = new String[][]{ new String[] {
       
   380                     "TLS_RSA_WITH_AES_128_CBC_SHA256"
       
   381             },  new String[] {
       
   382                     "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"
       
   383             }};
       
   384             for (int i = 0; i < enginesToTest.length; i++) {
       
   385                 enginesToTest[i][0] = createSSLEngine(true);
       
   386                 enginesToTest[i][1] = createSSLEngine(false);
       
   387                 enginesToTest[i][0].setEnabledCipherSuites(preferredSuites[i]);
       
   388                 enginesToTest[i][1].setEnabledCipherSuites(preferredSuites[i]);
       
   389             }
       
   390             return enginesToTest;
       
   391         }
       
   392 
       
   393         static private SSLEngine createSSLEngine(boolean client)
       
   394                 throws Exception {
       
   395             SSLEngine ssle;
       
   396             KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX",
       
   397                     jsseProvider);
       
   398             kmf.init(ks, passphrase);
       
   399 
       
   400             TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX",
       
   401                     jsseProvider);
       
   402             tmf.init(ts);
       
   403 
       
   404             SSLContext sslCtx = SSLContext.getInstance("TLSv1.2",
       
   405                     jsseProvider);
       
   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         if (initSecmod() == false) {
       
   418             return;
       
   419         }
       
   420         String configName = BASE + SEP + "fips.cfg";
       
   421         sunPKCS11NSSProvider = getSunPKCS11(configName);
       
   422         System.out.println("SunPKCS11 provider: " + sunPKCS11NSSProvider);
       
   423         Security.addProvider(sunPKCS11NSSProvider);
       
   424 
       
   425         sunJCEProvider = new com.sun.crypto.provider.SunJCE();
       
   426         Security.addProvider(sunJCEProvider);
       
   427 
       
   428         Security.removeProvider("SunJSSE");
       
   429         jsseProvider =new com.sun.net.ssl.internal.ssl.Provider(
       
   430                 sunPKCS11NSSProvider);
       
   431         Security.addProvider(jsseProvider);
       
   432         System.out.println(jsseProvider.getInfo());
       
   433 
       
   434         ks = KeyStore.getInstance("PKCS11", sunPKCS11NSSProvider);
       
   435         ks.load(null, "test12".toCharArray());
       
   436         ts = ks;
       
   437 
       
   438         KeyStore ksPlain = readTestKeyStore();
       
   439         privateKey = (RSAPrivateKey)ksPlain.getKey("rh_rsa_sha256",
       
   440                 passphrase);
       
   441         publicKey = (RSAPublicKey)ksPlain.getCertificate(
       
   442                 "rh_rsa_sha256").getPublicKey();
       
   443     }
       
   444 
       
   445     private static KeyStore readTestKeyStore() throws Exception {
       
   446         File file = new File(System.getProperty("test.src", "."), "keystore");
       
   447         InputStream in = new FileInputStream(file);
       
   448         KeyStore ks = KeyStore.getInstance("JKS");
       
   449         ks.load(in, "passphrase".toCharArray());
       
   450         in.close();
       
   451         return ks;
       
   452     }
       
   453 }