Path: blob/master/test/jdk/sun/security/pkcs11/tls/tls12/FipsModeTLS12.java
41161 views
/*1* Copyright (c) 2019, Red Hat, Inc.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 802966126* @summary Test TLS 1.227* @modules java.base/sun.security.internal.spec28* java.base/sun.security.util29* java.base/com.sun.crypto.provider30* @library /test/lib ../..31* @run main/othervm/timeout=120 -Djdk.tls.useExtendedMasterSecret=false FipsModeTLS1232*/3334import java.io.File;35import java.io.FileInputStream;36import java.io.InputStream;37import java.nio.ByteBuffer;3839import java.security.PrivateKey;40import java.security.PublicKey;41import java.security.KeyStore;42import java.security.NoSuchAlgorithmException;43import java.security.Provider;44import java.security.SecureRandom;45import java.security.Security;4647import java.util.Arrays;48import java.util.LinkedList;49import java.util.List;5051import javax.crypto.Cipher;52import javax.crypto.KeyGenerator;53import javax.crypto.SecretKey;54import javax.crypto.spec.SecretKeySpec;5556import javax.net.ssl.KeyManagerFactory;57import javax.net.ssl.SSLContext;58import javax.net.ssl.SSLEngine;59import javax.net.ssl.SSLEngineResult;60import javax.net.ssl.SSLEngineResult.HandshakeStatus;61import javax.net.ssl.SSLParameters;62import javax.net.ssl.SSLSession;63import javax.net.ssl.TrustManagerFactory;6465import sun.security.internal.spec.TlsMasterSecretParameterSpec;66import sun.security.internal.spec.TlsPrfParameterSpec;67import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;6869public final class FipsModeTLS12 extends SecmodTest {7071private static final boolean enableDebug = true;7273private static Provider sunPKCS11NSSProvider;74private static Provider sunJCEProvider;75private static KeyStore ks;76private static KeyStore ts;77private static char[] passphrase = "JAHshj131@@".toCharArray();78private static PrivateKey privateKey;79private static PublicKey publicKey;8081public static void main(String[] args) throws Exception {82try {83initialize();84} catch (Exception e) {85System.out.println("Test skipped: failure during" +86" initialization");87if (enableDebug) {88System.out.println(e);89}90return;91}9293if (shouldRun()) {94// Test against JCE95testTlsAuthenticationCodeGeneration();9697// Self-integrity test (complete TLS 1.2 communication)98new testTLS12SunPKCS11Communication().run();99100System.out.println("Test PASS - OK");101} else {102System.out.println("Test skipped: TLS 1.2 mechanisms" +103" not supported by current SunPKCS11 back-end");104}105}106107private static boolean shouldRun() {108if (sunPKCS11NSSProvider == null) {109return false;110}111try {112KeyGenerator.getInstance("SunTls12MasterSecret",113sunPKCS11NSSProvider);114KeyGenerator.getInstance(115"SunTls12RsaPremasterSecret", sunPKCS11NSSProvider);116KeyGenerator.getInstance("SunTls12Prf", sunPKCS11NSSProvider);117} catch (NoSuchAlgorithmException e) {118return false;119}120return true;121}122123private static void testTlsAuthenticationCodeGeneration()124throws Exception {125// Generate RSA Pre-Master Secret in SunPKCS11 provider126SecretKey rsaPreMasterSecret = null;127@SuppressWarnings("deprecation")128TlsRsaPremasterSecretParameterSpec rsaPreMasterSecretSpec =129new TlsRsaPremasterSecretParameterSpec(0x0303, 0x0303);130{131KeyGenerator rsaPreMasterSecretKG = KeyGenerator.getInstance(132"SunTls12RsaPremasterSecret", sunPKCS11NSSProvider);133rsaPreMasterSecretKG.init(rsaPreMasterSecretSpec, null);134rsaPreMasterSecret = rsaPreMasterSecretKG.generateKey();135}136137// Get RSA Pre-Master Secret in plain (from SunPKCS11 provider)138byte[] rsaPlainPreMasterSecret = null;139{140Cipher rsaPreMasterSecretWrapperCipher =141Cipher.getInstance("RSA/ECB/PKCS1Padding",142sunPKCS11NSSProvider);143rsaPreMasterSecretWrapperCipher.init(Cipher.WRAP_MODE, publicKey,144new SecureRandom());145byte[] rsaEncryptedPreMasterSecret =146rsaPreMasterSecretWrapperCipher.wrap(rsaPreMasterSecret);147Cipher rsaPreMasterSecretUnwrapperCipher =148Cipher.getInstance("RSA/ECB/PKCS1Padding", sunJCEProvider);149rsaPreMasterSecretUnwrapperCipher.init(Cipher.UNWRAP_MODE,150privateKey, rsaPreMasterSecretSpec);151rsaPlainPreMasterSecret = rsaPreMasterSecretUnwrapperCipher.unwrap(152rsaEncryptedPreMasterSecret, "TlsRsaPremasterSecret",153Cipher.SECRET_KEY).getEncoded();154155if (enableDebug) {156System.out.println("rsaPlainPreMasterSecret:");157for (byte b : rsaPlainPreMasterSecret) {158System.out.printf("%02X, ", b);159}160System.out.println("");161}162}163164// Generate Master Secret165SecretKey sunPKCS11MasterSecret = null;166SecretKey jceMasterSecret = null;167{168KeyGenerator sunPKCS11MasterSecretGenerator =169KeyGenerator.getInstance("SunTls12MasterSecret",170sunPKCS11NSSProvider);171KeyGenerator jceMasterSecretGenerator = KeyGenerator.getInstance(172"SunTls12MasterSecret", sunJCEProvider);173@SuppressWarnings("deprecation")174TlsMasterSecretParameterSpec sunPKCS11MasterSecretSpec =175new TlsMasterSecretParameterSpec(rsaPreMasterSecret, 3, 3,176new byte[32], new byte[32], "SHA-256", 32, 64);177@SuppressWarnings("deprecation")178TlsMasterSecretParameterSpec jceMasterSecretSpec =179new TlsMasterSecretParameterSpec(180new SecretKeySpec(rsaPlainPreMasterSecret,181"Generic"), 3, 3, new byte[32],182new byte[32], "SHA-256", 32, 64);183sunPKCS11MasterSecretGenerator.init(sunPKCS11MasterSecretSpec,184null);185jceMasterSecretGenerator.init(jceMasterSecretSpec, null);186sunPKCS11MasterSecret =187sunPKCS11MasterSecretGenerator.generateKey();188jceMasterSecret = jceMasterSecretGenerator.generateKey();189if (enableDebug) {190System.out.println("Master Secret (SunJCE):");191if (jceMasterSecret != null) {192for (byte b : jceMasterSecret.getEncoded()) {193System.out.printf("%02X, ", b);194}195System.out.println("");196}197}198}199200// Generate authentication codes201byte[] sunPKCS11AuthenticationCode = null;202byte[] jceAuthenticationCode = null;203{204// Generate SunPKCS11 authentication code205{206@SuppressWarnings("deprecation")207TlsPrfParameterSpec sunPKCS11AuthenticationCodeSpec =208new TlsPrfParameterSpec(sunPKCS11MasterSecret,209"client finished", "a".getBytes(), 12,210"SHA-256", 32, 64);211KeyGenerator sunPKCS11AuthCodeGenerator =212KeyGenerator.getInstance("SunTls12Prf",213sunPKCS11NSSProvider);214sunPKCS11AuthCodeGenerator.init(215sunPKCS11AuthenticationCodeSpec);216sunPKCS11AuthenticationCode =217sunPKCS11AuthCodeGenerator.generateKey().getEncoded();218}219220// Generate SunJCE authentication code221{222@SuppressWarnings("deprecation")223TlsPrfParameterSpec jceAuthenticationCodeSpec =224new TlsPrfParameterSpec(jceMasterSecret,225"client finished", "a".getBytes(), 12,226"SHA-256", 32, 64);227KeyGenerator jceAuthCodeGenerator =228KeyGenerator.getInstance("SunTls12Prf",229sunJCEProvider);230jceAuthCodeGenerator.init(jceAuthenticationCodeSpec);231jceAuthenticationCode =232jceAuthCodeGenerator.generateKey().getEncoded();233}234235if (enableDebug) {236System.out.println("SunPKCS11 Authentication Code: ");237for (byte b : sunPKCS11AuthenticationCode) {238System.out.printf("%02X, ", b);239}240System.out.println("");241System.out.println("SunJCE Authentication Code: ");242for (byte b : jceAuthenticationCode) {243System.out.printf("%02X, ", b);244}245System.out.println("");246}247}248249if (sunPKCS11AuthenticationCode == null ||250jceAuthenticationCode == null ||251sunPKCS11AuthenticationCode.length == 0 ||252jceAuthenticationCode.length == 0 ||253!Arrays.equals(sunPKCS11AuthenticationCode,254jceAuthenticationCode)) {255throw new Exception("Authentication codes from JCE" +256" and SunPKCS11 differ.");257}258}259260private static class testTLS12SunPKCS11Communication {261public static void run() throws Exception {262SSLEngine[][] enginesToTest = getSSLEnginesToTest();263264for (SSLEngine[] engineToTest : enginesToTest) {265266SSLEngine clientSSLEngine = engineToTest[0];267SSLEngine serverSSLEngine = engineToTest[1];268269// SSLEngine code based on RedhandshakeFinished.java270271boolean dataDone = false;272273ByteBuffer clientOut = null;274ByteBuffer clientIn = null;275ByteBuffer serverOut = null;276ByteBuffer serverIn = null;277ByteBuffer cTOs;278ByteBuffer sTOc;279280SSLSession session = clientSSLEngine.getSession();281int appBufferMax = session.getApplicationBufferSize();282int netBufferMax = session.getPacketBufferSize();283284clientIn = ByteBuffer.allocate(appBufferMax + 50);285serverIn = ByteBuffer.allocate(appBufferMax + 50);286287cTOs = ByteBuffer.allocateDirect(netBufferMax);288sTOc = ByteBuffer.allocateDirect(netBufferMax);289290clientOut = ByteBuffer.wrap(291"Hi Server, I'm Client".getBytes());292serverOut = ByteBuffer.wrap(293"Hello Client, I'm Server".getBytes());294295SSLEngineResult clientResult;296SSLEngineResult serverResult;297298while (!dataDone) {299clientResult = clientSSLEngine.wrap(clientOut, cTOs);300runDelegatedTasks(clientResult, clientSSLEngine);301serverResult = serverSSLEngine.wrap(serverOut, sTOc);302runDelegatedTasks(serverResult, serverSSLEngine);303cTOs.flip();304sTOc.flip();305306if (enableDebug) {307System.out.println("Client -> Network");308printTlsNetworkPacket("", cTOs);309System.out.println("");310System.out.println("Server -> Network");311printTlsNetworkPacket("", sTOc);312System.out.println("");313}314315clientResult = clientSSLEngine.unwrap(sTOc, clientIn);316runDelegatedTasks(clientResult, clientSSLEngine);317serverResult = serverSSLEngine.unwrap(cTOs, serverIn);318runDelegatedTasks(serverResult, serverSSLEngine);319320cTOs.compact();321sTOc.compact();322323if (!dataDone &&324(clientOut.limit() == serverIn.position()) &&325(serverOut.limit() == clientIn.position())) {326checkTransfer(serverOut, clientIn);327checkTransfer(clientOut, serverIn);328dataDone = true;329}330}331}332}333334static void printTlsNetworkPacket(String prefix, ByteBuffer bb) {335ByteBuffer slice = bb.slice();336byte[] buffer = new byte[slice.remaining()];337slice.get(buffer);338for (int i = 0; i < buffer.length; i++) {339System.out.printf("%02X, ", (byte)(buffer[i] & (byte)0xFF));340if (i % 8 == 0 && i % 16 != 0) {341System.out.print(" ");342}343if (i % 16 == 0) {344System.out.println("");345}346}347System.out.flush();348}349350private static void checkTransfer(ByteBuffer a, ByteBuffer b)351throws Exception {352a.flip();353b.flip();354if (!a.equals(b)) {355throw new Exception("Data didn't transfer cleanly");356}357a.position(a.limit());358b.position(b.limit());359a.limit(a.capacity());360b.limit(b.capacity());361}362363private static void runDelegatedTasks(SSLEngineResult result,364SSLEngine engine) throws Exception {365366if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {367Runnable runnable;368while ((runnable = engine.getDelegatedTask()) != null) {369runnable.run();370}371HandshakeStatus hsStatus = engine.getHandshakeStatus();372if (hsStatus == HandshakeStatus.NEED_TASK) {373throw new Exception(374"handshake shouldn't need additional tasks");375}376}377}378379private static SSLEngine[][] getSSLEnginesToTest() throws Exception {380SSLEngine[][] enginesToTest = new SSLEngine[2][2];381// TLS_RSA_WITH_AES_128_GCM_SHA256 ciphersuite is available but382// must not be chosen for the TLS connection if not supported.383// See JDK-8222937.384String[][] preferredSuites = new String[][]{ new String[] {385"TLS_RSA_WITH_AES_128_GCM_SHA256",386"TLS_RSA_WITH_AES_128_CBC_SHA256"387}, new String[] {388"TLS_RSA_WITH_AES_128_GCM_SHA256",389"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"390}};391for (int i = 0; i < enginesToTest.length; i++) {392enginesToTest[i][0] = createSSLEngine(true);393enginesToTest[i][1] = createSSLEngine(false);394// All CipherSuites enabled for the client.395enginesToTest[i][1].setEnabledCipherSuites(preferredSuites[i]);396}397return enginesToTest;398}399400static private SSLEngine createSSLEngine(boolean client)401throws Exception {402SSLEngine ssle;403KeyManagerFactory kmf = KeyManagerFactory.getInstance("PKIX", "SunJSSE");404kmf.init(ks, passphrase);405406TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX", "SunJSSE");407tmf.init(ts);408409SSLContext sslCtx = SSLContext.getInstance("TLSv1.2", "SunJSSE");410sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);411ssle = sslCtx.createSSLEngine("localhost", 443);412ssle.setUseClientMode(client);413SSLParameters sslParameters = ssle.getSSLParameters();414ssle.setSSLParameters(sslParameters);415416return ssle;417}418}419420private static void initialize() throws Exception {421//422// For a successful FIPS-mode TLS connection, the following423// cryptographic providers will be installed:424//425// 1. SunPKCS11 (with an NSS FIPS mode backend)426// 2. SUN (to handle X.509 certificates)427// 3. SunJSSE (for a TLS engine)428//429// RSASSA-PSS algorithm is not currently supported in SunPKCS11430// but in SUN provider. As a result, it can be negotiated by the431// TLS engine. The problem is that SunPKCS11 keys are sensitive432// in FIPS mode and cannot be used in a SUN algorithm (conversion433// fails as plain values cannot be extracted).434//435// To workaround this issue, we disable RSASSA-PSS algorithm for436// TLS connections. Once JDK-8222937 is fixed, this workaround can437// (and should) be removed.438//439// On a final note, the list of disabled TLS algorithms440// (jdk.tls.disabledAlgorithms) has to be updated at this point,441// before it is read in sun.security.ssl.SSLAlgorithmConstraints442// class initialization.443String disabledAlgorithms =444Security.getProperty("jdk.tls.disabledAlgorithms");445if (disabledAlgorithms.length() > 0) {446disabledAlgorithms += ", ";447}448disabledAlgorithms += "RSASSA-PSS";449Security.setProperty("jdk.tls.disabledAlgorithms", disabledAlgorithms);450451if (initSecmod() == false) {452return;453}454String configName = BASE + SEP + "nss.cfg";455sunPKCS11NSSProvider = getSunPKCS11(configName);456System.out.println("SunPKCS11 provider: " + sunPKCS11NSSProvider);457458List<Provider> installedProviders = new LinkedList<>();459for (Provider p : Security.getProviders()){460installedProviders.add(p);461Security.removeProvider(p.getName());462}463Security.addProvider(sunPKCS11NSSProvider);464for (Provider p : installedProviders){465String providerName = p.getName();466if (providerName.equals("SunJSSE") || providerName.equals("SUN")) {467Security.addProvider(p);468} else if (providerName.equals("SunJCE")) {469sunJCEProvider = p;470}471}472473ks = KeyStore.getInstance("PKCS11", sunPKCS11NSSProvider);474ks.load(null, "test12".toCharArray());475ts = ks;476477KeyStore ksPlain = readTestKeyStore();478privateKey = (PrivateKey)ksPlain.getKey("rh_rsa_sha256",479passphrase);480publicKey = (PublicKey)ksPlain.getCertificate(481"rh_rsa_sha256").getPublicKey();482}483484private static KeyStore readTestKeyStore() throws Exception {485File file = new File(System.getProperty("test.src", "."), "keystore");486InputStream in = new FileInputStream(file);487KeyStore ks = KeyStore.getInstance("JKS");488ks.load(in, "passphrase".toCharArray());489in.close();490return ks;491}492}493494495