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