Merge "Merge "DO NOT MERGE: Remove StuckServer using backlog and tests relying on it" into marshmallow-cts-dev am: 244e7d3556 -s ours" into nougat-cts-dev
am: 8de6ec43d2 -s ours
Change-Id: If9f6c374d32052c73883c645791eace320328af2
diff --git a/benchmarks/src/benchmarks/regression/DateFormatBenchmark.java b/benchmarks/src/benchmarks/regression/DateFormatBenchmark.java
new file mode 100644
index 0000000..bd5bf1a
--- /dev/null
+++ b/benchmarks/src/benchmarks/regression/DateFormatBenchmark.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package benchmarks.regression;
+
+import com.google.caliper.BeforeExperiment;
+
+import java.text.DateFormat;
+import java.util.Locale;
+
+public final class DateFormatBenchmark {
+
+ private Locale locale1;
+ private Locale locale2;
+ private Locale locale3;
+ private Locale locale4;
+
+ @BeforeExperiment
+ protected void setUp() throws Exception {
+ locale1 = Locale.TAIWAN;
+ locale2 = Locale.GERMANY;
+ locale3 = Locale.FRANCE;
+ locale4 = Locale.ITALY;
+ }
+
+ public void timeGetDateTimeInstance(int reps) throws Exception {
+ for (int i = 0; i < reps; ++i) {
+ DateFormat.getDateTimeInstance();
+ }
+ }
+
+ public void timeGetDateTimeInstance_multiple(int reps) throws Exception {
+ for (int i = 0; i < reps; ++i) {
+ DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale1);
+ DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale2);
+ DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale3);
+ DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale4);
+ }
+ }
+}
diff --git a/dalvik/src/main/java/dalvik/system/DexFile.java b/dalvik/src/main/java/dalvik/system/DexFile.java
index f1ec29d..0a01a13 100644
--- a/dalvik/src/main/java/dalvik/system/DexFile.java
+++ b/dalvik/src/main/java/dalvik/system/DexFile.java
@@ -41,7 +41,6 @@
private Object mCookie;
private Object mInternalCookie;
private final String mFileName;
- private final CloseGuard guard = CloseGuard.get();
/**
* Opens a DEX file from a given File object. This will usually be a ZIP/JAR
@@ -113,7 +112,6 @@
mCookie = openDexFile(fileName, null, 0, loader, elements);
mInternalCookie = mCookie;
mFileName = fileName;
- guard.open("close");
//System.out.println("DEX FILE cookie is " + mCookie + " fileName=" + fileName);
}
@@ -250,7 +248,6 @@
if (closeDexFile(mInternalCookie)) {
mInternalCookie = null;
}
- guard.close();
mCookie = null;
}
}
@@ -349,9 +346,6 @@
*/
@Override protected void finalize() throws Throwable {
try {
- if (guard != null) {
- guard.warnIfOpen();
- }
if (mInternalCookie != null && !closeDexFile(mInternalCookie)) {
throw new AssertionError("Failed to close dex file in finalizer.");
}
@@ -507,4 +501,12 @@
*/
public static native String getDexFileStatus(String fileName, String instructionSet)
throws FileNotFoundException;
+
+ /**
+ * Returns the full file path of the optimized dex file {@code fileName}. The returned string
+ * is the full file name including path of optimized dex file, if it exists.
+ * @hide
+ */
+ public static native String getDexFileOutputPath(String fileName, String instructionSet)
+ throws FileNotFoundException;
}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/DataInputStreamTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/DataInputStreamTest.java
index 67a4e5f..7d89017 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/DataInputStreamTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/DataInputStreamTest.java
@@ -23,6 +23,7 @@
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
+import java.io.InputStream;
public class DataInputStreamTest extends junit.framework.TestCase {
@@ -564,6 +565,54 @@
+ skipped, skipped == fileString.length());
}
+ // b/30268192 : Some apps rely on the exact calls that
+ // DataInputStream makes on the wrapped InputStream. This
+ // test is to prevent *unintentional* regressions but may
+ // change in future releases.
+ public void test_readShortUsesMultiByteRead() throws IOException {
+ ThrowExceptionOnSingleByteReadInputStream
+ is = new ThrowExceptionOnSingleByteReadInputStream();
+ DataInputStream dis = new DataInputStream(is);
+ dis.readShort();
+ is.assertMultiByteReadWasCalled();
+ }
+
+ // b/30268192 : Some apps rely on the exact calls that
+ // DataInputStream makes on the wrapped InputStream. This
+ // test is to prevent *unintentional* regressions but may
+ // change in future releases.
+ public void test_readCharUsesMultiByteRead() throws IOException {
+ ThrowExceptionOnSingleByteReadInputStream
+ is = new ThrowExceptionOnSingleByteReadInputStream();
+ DataInputStream dis = new DataInputStream(is);
+ dis.readChar();
+ is.assertMultiByteReadWasCalled();
+ }
+
+ // b/30268192 : Some apps rely on the exact calls that
+ // DataInputStream makes on the wrapped InputStream. This
+ // test is to prevent *unintentional* regressions but may
+ // change in future releases.
+ public void test_readIntUsesMultiByteRead() throws IOException {
+ ThrowExceptionOnSingleByteReadInputStream
+ is = new ThrowExceptionOnSingleByteReadInputStream();
+ DataInputStream dis = new DataInputStream(is);
+ dis.readInt();
+ is.assertMultiByteReadWasCalled();
+ }
+
+ // b/30268192 : Some apps rely on the exact calls that
+ // DataInputStream makes on the wrapped InputStream. This
+ // test is to prevent *unintentional* regressions but may
+ // change in future releases.
+ public void test_readUnsignedShortUsesMultiByteRead() throws IOException {
+ ThrowExceptionOnSingleByteReadInputStream
+ is = new ThrowExceptionOnSingleByteReadInputStream();
+ DataInputStream dis = new DataInputStream(is);
+ dis.readUnsignedShort();
+ is.assertMultiByteReadWasCalled();
+ }
+
private void openDataInputStream() throws IOException {
dis = new DataInputStream(new ByteArrayInputStream(bos.toByteArray()));
}
@@ -591,4 +640,27 @@
} catch (Exception e) {
}
}
+
+ public static class ThrowExceptionOnSingleByteReadInputStream extends InputStream {
+
+ private boolean multiByteReadWasCalled = false;
+
+ @Override
+ public int read() throws IOException {
+ fail("Should not call single byte read");
+ return 0;
+ }
+
+ @Override
+ public int read(byte[] b, int i, int j) throws IOException {
+ multiByteReadWasCalled = true;
+ return j;
+ }
+
+ public void assertMultiByteReadWasCalled() {
+ if (!multiByteReadWasCalled) {
+ fail("read(byte[], int, int) was not called");
+ }
+ }
+ }
}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/ObjectStreamClassTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/ObjectStreamClassTest.java
index 7ae4617..7fa5fbb 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/ObjectStreamClassTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/ObjectStreamClassTest.java
@@ -17,7 +17,6 @@
package org.apache.harmony.tests.java.io;
-import junit.framework.TestCase;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
@@ -27,6 +26,7 @@
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
+import junit.framework.TestCase;
public class ObjectStreamClassTest extends TestCase {
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/VectorTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/VectorTest.java
index a9f64a2..a16c4e4 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/VectorTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/VectorTest.java
@@ -30,6 +30,7 @@
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.Spliterator;
import java.util.Vector;
@@ -850,6 +851,15 @@
}
}
+ // http://b/30974375
+ public void test_listIterator_addAndPrevious() {
+ ListIterator<String> it = new Vector<String>().listIterator();
+ assertFalse(it.hasNext());
+ it.add("value");
+ assertEquals("value", it.previous());
+ assertTrue(it.hasNext());
+ }
+
/**
* java.util.Vector#remove(int)
*/
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/SocketFactoryTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/SocketFactoryTest.java
index 649be09..52d9142 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/SocketFactoryTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/javax/net/SocketFactoryTest.java
@@ -126,30 +126,12 @@
public final void test_createSocket_InetAddressIInetAddressI() throws Exception {
SocketFactory sf = SocketFactory.getDefault();
int sport = new ServerSocket(0).getLocalPort();
- int[] invalidPorts = {Integer.MIN_VALUE, -1, 65536, Integer.MAX_VALUE};
Socket s = sf.createSocket(InetAddress.getLocalHost(), sport,
- InetAddress.getLocalHost(), 0);
+ InetAddress.getLocalHost(), 0);
assertNotNull(s);
assertTrue("1: Failed to create socket", s.getPort() == sport);
int portNumber = s.getLocalPort();
-
- for (int i = 0; i < invalidPorts.length; i++) {
- try {
- sf.createSocket(InetAddress.getLocalHost(), invalidPorts[i],
- InetAddress.getLocalHost(), portNumber);
- fail("IllegalArgumentException wasn't thrown for " + invalidPorts[i]);
- } catch (IllegalArgumentException expected) {
- }
-
- try {
- sf.createSocket(InetAddress.getLocalHost(), sport,
- InetAddress.getLocalHost(), invalidPorts[i]);
- fail("IllegalArgumentException wasn't thrown for " + invalidPorts[i]);
- } catch (IllegalArgumentException expected) {
- }
- }
-
try {
sf.createSocket(InetAddress.getLocalHost(), sport,
InetAddress.getLocalHost(), portNumber);
@@ -165,6 +147,64 @@
}
}
+ // Checks the behavior of createSocket(InetAddress, int, InetAddress, int) when the
+ // ports are invalid.
+ public void test_createSocket_InetAddressIInetAddressI_IllegalArgumentException()
+ throws Exception {
+ SocketFactory sf = SocketFactory.getDefault();
+ int validPort = new ServerSocket(0).getLocalPort();
+ int[] invalidPorts = {Integer.MIN_VALUE, -1, 65536, Integer.MAX_VALUE};
+
+ for (int i = 0; i < invalidPorts.length; i++) {
+ // Check invalid server port.
+ try (Socket s = sf.createSocket(InetAddress.getLocalHost() /* ServerAddress */,
+ invalidPorts[i] /* ServerPort */,
+ InetAddress.getLocalHost() /* ClientAddress */,
+ validPort /* ClientPort */)) {
+ fail("IllegalArgumentException wasn't thrown for " + invalidPorts[i]);
+ } catch (IllegalArgumentException expected) {
+ }
+
+ // Check invalid client port.
+ try (Socket s = sf.createSocket(InetAddress.getLocalHost() /* ServerAddress */,
+ validPort /* ServerPort */,
+ InetAddress.getLocalHost() /* ClientAddress */,
+ invalidPorts[i]) /* ClientPort */){
+ fail("IllegalArgumentException wasn't thrown for " + invalidPorts[i]);
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+ }
+
+ // b/31019685
+ // Checks the ordering of port number validation (IllegalArgumentException) and binding error.
+ public void test_createSocket_InetAddressIInetAddressI_ExceptionOrder() throws IOException {
+ int invalidPort = Integer.MAX_VALUE;
+ SocketFactory sf = SocketFactory.getDefault();
+ int validServerPortNumber = new ServerSocket(0).getLocalPort();
+
+ // Create a socket with localhost as the client address so that another attempt to bind
+ // would fail.
+ Socket s = sf.createSocket(InetAddress.getLocalHost() /* ServerAddress */,
+ validServerPortNumber /* ServerPortNumber */,
+ InetAddress.getLocalHost() /* ClientAddress */,
+ 0 /* ClientPortNumber */);
+
+ int assignedLocalPortNumber = s.getLocalPort();
+
+ // Create a socket with an invalid port and localhost as the client address. Both
+ // BindException and IllegalArgumentException are expected in this case as the address is
+ // already bound to the socket above and port is invalid, however, to preserve the
+ // precedence order, IllegalArgumentException should be thrown.
+ try (Socket s1 = sf.createSocket(InetAddress.getLocalHost() /* ServerAddress */,
+ invalidPort /* ServerPortNumber */,
+ InetAddress.getLocalHost() /* ClientAddress */,
+ assignedLocalPortNumber /* ClientPortNumber */)) {
+ fail("IllegalArgumentException wasn't thrown for " + invalidPort);
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
/**
* javax.net.SocketFactory#createSocket(String host, int port,
* InetAddress localHost, int localPort)
diff --git a/luni/src/main/java/libcore/icu/TimeZoneNames.java b/luni/src/main/java/libcore/icu/TimeZoneNames.java
index daa915e..917d9ce 100644
--- a/luni/src/main/java/libcore/icu/TimeZoneNames.java
+++ b/luni/src/main/java/libcore/icu/TimeZoneNames.java
@@ -68,7 +68,7 @@
}
long nativeStart = System.nanoTime();
- fillZoneStrings(locale.toString(), result);
+ fillZoneStrings(locale.toLanguageTag(), result);
long nativeEnd = System.nanoTime();
internStrings(result);
diff --git a/luni/src/main/java/libcore/net/MimeUtils.java b/luni/src/main/java/libcore/net/MimeUtils.java
index 3b59b87..88a7392 100644
--- a/luni/src/main/java/libcore/net/MimeUtils.java
+++ b/luni/src/main/java/libcore/net/MimeUtils.java
@@ -210,6 +210,12 @@
add("application/x-xcf", "xcf");
add("application/x-xfig", "fig");
add("application/xhtml+xml", "xhtml");
+ // Video mime types for 3GPP first so they'll be default for guessMimeTypeFromExtension
+ // See RFC 3839 for 3GPP and RFC 4393 for 3GPP2
+ add("video/3gpp", "3gpp");
+ add("video/3gpp", "3gp");
+ add("video/3gpp2", "3gpp2");
+ add("video/3gpp2", "3g2");
add("audio/3gpp", "3gpp");
add("audio/aac", "aac");
add("audio/aac-adts", "aac");
@@ -353,10 +359,6 @@
add("text/x-tex", "cls");
add("text/x-vcalendar", "vcs");
add("text/x-vcard", "vcf");
- add("video/3gpp", "3gpp");
- add("video/3gpp", "3gp");
- add("video/3gpp2", "3gpp2");
- add("video/3gpp2", "3g2");
add("video/avi", "avi");
add("video/dl", "dl");
add("video/dv", "dif");
diff --git a/luni/src/test/java/com/android/org/bouncycastle/crypto/digests/DigestTest.java b/luni/src/test/java/com/android/org/bouncycastle/crypto/digests/DigestTest.java
index fce8507..ec5ca03 100644
--- a/luni/src/test/java/com/android/org/bouncycastle/crypto/digests/DigestTest.java
+++ b/luni/src/test/java/com/android/org/bouncycastle/crypto/digests/DigestTest.java
@@ -93,9 +93,6 @@
+ oldTime.toString());
System.out.println("Time for " + ITERATIONS + " x new hash processing: "
+ newTime.toString());
-
- assertTrue("New hash should be faster:\nold=" + oldTime.toString() + "\nnew="
- + newTime.toString(), newTime.mean() < oldTime.mean());
}
/**
diff --git a/luni/src/test/java/libcore/java/io/FileInputStreamTest.java b/luni/src/test/java/libcore/java/io/FileInputStreamTest.java
index 74432e5..7ff4684 100644
--- a/luni/src/test/java/libcore/java/io/FileInputStreamTest.java
+++ b/luni/src/test/java/libcore/java/io/FileInputStreamTest.java
@@ -26,7 +26,9 @@
import java.util.List;
import android.system.ErrnoException;
+import android.system.Os;
import android.system.OsConstants;
+import android.system.StructStatVfs;
import junit.framework.TestCase;
import libcore.io.IoUtils;
@@ -226,23 +228,36 @@
// http://b/28192631
public void testSkipOnLargeFiles() throws Exception {
File largeFile = File.createTempFile("FileInputStreamTest_testSkipOnLargeFiles", "");
- FileOutputStream fos = new FileOutputStream(largeFile);
- try {
- byte[] buffer = new byte[1024 * 1024]; // 1 MB
- for (int i = 0; i < 3 * 1024; i++) { // 3 GB
- fos.write(buffer);
- }
- } finally {
- fos.close();
+
+ // Required space is 3.1 GB: 3GB for file plus 100M headroom.
+ final long requiredFreeSpaceBytes = 3172L * 1024 * 1024;
+
+ // If system doesn't have enough space free for this test, skip it.
+ final StructStatVfs statVfs = Os.statvfs(largeFile.getPath());
+ final long freeSpaceAvailableBytes = statVfs.f_bsize * statVfs.f_bavail;
+ if (freeSpaceAvailableBytes < requiredFreeSpaceBytes) {
+ return;
}
- FileInputStream fis = new FileInputStream(largeFile);
- long lastByte = 3 * 1024 * 1024 * 1024L - 1;
- assertEquals(0, Libcore.os.lseek(fis.getFD(), 0, OsConstants.SEEK_CUR));
- assertEquals(lastByte, fis.skip(lastByte));
+ try {
+ FileOutputStream fos = new FileOutputStream(largeFile);
+ try {
+ byte[] buffer = new byte[1024 * 1024]; // 1 MB
+ for (int i = 0; i < 3 * 1024; i++) { // 3 GB
+ fos.write(buffer);
+ }
+ } finally {
+ fos.close();
+ }
- // Proactively cleanup - it's a pretty large file.
- assertTrue(largeFile.delete());
+ FileInputStream fis = new FileInputStream(largeFile);
+ long lastByte = 3 * 1024 * 1024 * 1024L - 1;
+ assertEquals(0, Libcore.os.lseek(fis.getFD(), 0, OsConstants.SEEK_CUR));
+ assertEquals(lastByte, fis.skip(lastByte));
+ } finally {
+ // Proactively cleanup - it's a pretty large file.
+ assertTrue(largeFile.delete());
+ }
}
private static List<Integer> getOpenFdsForPrefix(String path) throws Exception {
diff --git a/luni/src/test/java/libcore/java/lang/OldRuntimeTest.java b/luni/src/test/java/libcore/java/lang/OldRuntimeTest.java
index 294cea2..8397587 100644
--- a/luni/src/test/java/libcore/java/lang/OldRuntimeTest.java
+++ b/luni/src/test/java/libcore/java/lang/OldRuntimeTest.java
@@ -27,6 +27,9 @@
import java.util.Arrays;
import java.util.Vector;
import tests.support.resource.Support_Resources;
+import dalvik.system.VMRuntime;
+import java.lang.reflect.Method;
+import java.lang.reflect.InvocationTargetException;
public class OldRuntimeTest extends junit.framework.TestCase {
@@ -519,4 +522,73 @@
//expected
}
}
+
+ // b/25859957
+ public void test_loadDeprecated() throws Exception {
+ final int savedTargetSdkVersion = VMRuntime.getRuntime().getTargetSdkVersion();
+ try {
+ try {
+ // Call Runtime#load(String, ClassLoader) at API level 24 (N). It will fail
+ // with a UnsatisfiedLinkError because requested library doesn't exits.
+ VMRuntime.getRuntime().setTargetSdkVersion(24);
+ Method loadMethod =
+ Runtime.class.getDeclaredMethod("load", String.class, ClassLoader.class);
+ loadMethod.setAccessible(true);
+ loadMethod.invoke(Runtime.getRuntime(), "nonExistentLibrary", null);
+ fail();
+ } catch(InvocationTargetException expected) {
+ assertTrue(expected.getCause() instanceof UnsatisfiedLinkError);
+ }
+
+ try {
+ // Call Runtime#load(String, ClassLoader) at API level 25. It will fail
+ // with a IllegalStateException because it's deprecated.
+ VMRuntime.getRuntime().setTargetSdkVersion(25);
+ Method loadMethod =
+ Runtime.class.getDeclaredMethod("load", String.class, ClassLoader.class);
+ loadMethod.setAccessible(true);
+ loadMethod.invoke(Runtime.getRuntime(), "nonExistentLibrary", null);
+ fail();
+ } catch(InvocationTargetException expected) {
+ assertTrue(expected.getCause() instanceof UnsupportedOperationException);
+ }
+ } finally {
+ VMRuntime.getRuntime().setTargetSdkVersion(savedTargetSdkVersion);
+ }
+ }
+
+ // b/25859957
+ public void test_loadLibraryDeprecated() throws Exception {
+ final int savedTargetSdkVersion = VMRuntime.getRuntime().getTargetSdkVersion();
+ try {
+ try {
+ // Call Runtime#loadLibrary(String, ClassLoader) at API level 24 (N). It will fail
+ // with a UnsatisfiedLinkError because requested library doesn't exits.
+ VMRuntime.getRuntime().setTargetSdkVersion(24);
+ Method loadMethod =
+ Runtime.class.getDeclaredMethod("loadLibrary", String.class, ClassLoader.class);
+ loadMethod.setAccessible(true);
+ loadMethod.invoke(Runtime.getRuntime(), "nonExistentLibrary", null);
+ fail();
+ } catch(InvocationTargetException expected) {
+ assertTrue(expected.getCause() instanceof UnsatisfiedLinkError);
+ }
+
+ try {
+ // Call Runtime#load(String, ClassLoader) at API level 25. It will fail
+ // with a IllegalStateException because it's deprecated.
+
+ VMRuntime.getRuntime().setTargetSdkVersion(25);
+ Method loadMethod =
+ Runtime.class.getDeclaredMethod("loadLibrary", String.class, ClassLoader.class);
+ loadMethod.setAccessible(true);
+ loadMethod.invoke(Runtime.getRuntime(), "nonExistentLibrary", null);
+ fail();
+ } catch(InvocationTargetException expected) {
+ assertTrue(expected.getCause() instanceof UnsupportedOperationException);
+ }
+ } finally {
+ VMRuntime.getRuntime().setTargetSdkVersion(savedTargetSdkVersion);
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/Annotations57649Test.java b/luni/src/test/java/libcore/java/lang/reflect/Annotations57649Test.java
index 60e294b..f2f961c 100644
--- a/luni/src/test/java/libcore/java/lang/reflect/Annotations57649Test.java
+++ b/luni/src/test/java/libcore/java/lang/reflect/Annotations57649Test.java
@@ -7,6 +7,12 @@
public final class Annotations57649Test extends TestCase {
// https://code.google.com/p/android/issues/detail?id=57649
public void test57649() throws Exception {
+ // This test consumes a lot of RAM and doesn't release it. Disable on low ram devices.
+ // See b/32004484
+ if (isLowRamDevice()) {
+ return;
+ }
+
Thread a = runTest(A.class);
Thread b = runTest(B.class);
a.join();
@@ -23,6 +29,10 @@
return t;
}
+ private static boolean isLowRamDevice() {
+ return Boolean.parseBoolean(System.getProperty("android.cts.device.lowram", "false"));
+ }
+
@Retention(RetentionPolicy.RUNTIME) @interface A0 {}
@Retention(RetentionPolicy.RUNTIME) @interface A1 {}
@Retention(RetentionPolicy.RUNTIME) @interface A2 {}
diff --git a/luni/src/test/java/libcore/java/net/DatagramSocketTest.java b/luni/src/test/java/libcore/java/net/DatagramSocketTest.java
index 86e47ec..067291a 100644
--- a/luni/src/test/java/libcore/java/net/DatagramSocketTest.java
+++ b/luni/src/test/java/libcore/java/net/DatagramSocketTest.java
@@ -18,8 +18,11 @@
import junit.framework.TestCase;
+import java.lang.reflect.Field;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
+import java.net.DatagramSocketImpl;
+import java.net.InetAddress;
public class DatagramSocketTest extends TestCase {
@@ -55,4 +58,21 @@
assertEquals(-1, ds.getLocalPort());
assertNull(ds.getLocalSocketAddress());
}
+ // Socket should become connected even if impl.connect() failed and threw exception.
+ public void test_b31218085() throws Exception {
+ final int port = 9999;
+
+ try (DatagramSocket s = new DatagramSocket()) {
+ // Set fd of DatagramSocket to null, forcing impl.connect() to throw.
+ Field f = DatagramSocket.class.getDeclaredField("impl");
+ f.setAccessible(true);
+ DatagramSocketImpl impl = (DatagramSocketImpl) f.get(s);
+ f = DatagramSocketImpl.class.getDeclaredField("fd");
+ f.setAccessible(true);
+ f.set(impl, null);
+
+ s.connect(InetAddress.getLocalHost(), port);
+ assertTrue(s.isConnected());
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/java/net/InetAddressTest.java b/luni/src/test/java/libcore/java/net/InetAddressTest.java
index d496801..4f922eb 100644
--- a/luni/src/test/java/libcore/java/net/InetAddressTest.java
+++ b/luni/src/test/java/libcore/java/net/InetAddressTest.java
@@ -20,6 +20,7 @@
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
+import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
@@ -185,10 +186,8 @@
public void test_isReachable_neverThrows() throws Exception {
InetAddress inetAddress = InetAddress.getByName("www.google.com");
- final NetworkInterface netIf;
- try {
- netIf = NetworkInterface.getByName("dummy0");
- } catch (SocketException e) {
+ final NetworkInterface netIf = NetworkInterface.getByName("dummy0");
+ if (netIf == null) {
System.logI("Skipping test_isReachable_neverThrows because dummy0 isn't available");
return;
}
@@ -334,11 +333,15 @@
public void test_getHostNameCaches() throws Exception {
InetAddress inetAddress = InetAddress.getByAddress(LOOPBACK6_BYTES);
- // TODO(narayan): Investigate why these tests are suppressed.
- // assertEquals("::1", inetAddress.getHostString());
+
+ // There should be no cached name.
+ assertEquals("::1", getHostStringWithoutReverseDns(inetAddress));
+
+ // Force the reverse-DNS lookup.
assertEquals("ip6-localhost", inetAddress.getHostName());
- // getHostString() should now be different.
- // assertEquals("ip6-localhost", inetAddress.getHostString());
+
+ // The cached name should now be different.
+ assertEquals("ip6-localhost", getHostStringWithoutReverseDns(inetAddress));
}
public void test_getByAddress_loopbackIpv4() throws Exception {
@@ -367,7 +370,7 @@
public void test_getByName_empty() throws Exception {
InetAddress inetAddress = InetAddress.getByName("");
- assertEquals(LOOPBACK6_BYTES, "localhost", inetAddress);
+ assertEquals(LOOPBACK6_BYTES, "ip6-localhost", inetAddress);
assertTrue(inetAddress.isLoopbackAddress());
}
@@ -418,6 +421,13 @@
assertEquals(expectedLoopbackAddresses, createSet(inetAddresses));
}
+ // http://b/29311351
+ public void test_loopbackConstantsPreInitializedNames() {
+ // Note: Inet6Address / Inet4Address equals() does not check host name.
+ assertEquals("ip6-localhost", getHostStringWithoutReverseDns(Inet6Address.LOOPBACK));
+ assertEquals("localhost", getHostStringWithoutReverseDns(Inet4Address.LOOPBACK));
+ }
+
private static void assertEquals(
byte[] expectedAddressBytes, String expectedHostname, InetAddress actual) {
assertArrayEquals(expectedAddressBytes, actual.getAddress());
@@ -433,4 +443,11 @@
private static Set<InetAddress> createSet(InetAddress... members) {
return new HashSet<InetAddress>(Arrays.asList(members));
}
+
+ private static String getHostStringWithoutReverseDns(InetAddress inetAddress) {
+ // The InetAddress API provides no way of avoiding a DNS lookup, but InetSocketAddress
+ // does via InetSocketAddress.getHostString().
+ InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, 9999);
+ return inetSocketAddress.getHostString();
+ }
}
diff --git a/luni/src/test/java/libcore/java/net/SocketTest.java b/luni/src/test/java/libcore/java/net/SocketTest.java
index 52638d4..e2d3964 100644
--- a/luni/src/test/java/libcore/java/net/SocketTest.java
+++ b/luni/src/test/java/libcore/java/net/SocketTest.java
@@ -21,6 +21,7 @@
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.Inet4Address;
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
@@ -34,6 +35,7 @@
import java.net.UnknownHostException;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
+import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
@@ -45,6 +47,10 @@
public class SocketTest extends junit.framework.TestCase {
+
+ // This hostname is required to resolve to 127.0.0.1 and ::1 for all tests to pass.
+ private static final String ALL_LOOPBACK_HOSTNAME = "loopback46.unittest.grpc.io";
+
// See http://b/2980559.
public void test_close() throws Exception {
Socket s = new Socket();
@@ -542,4 +548,51 @@
new SocketThatFailOnClose(InetAddress.getLocalHost(), 1, true);
} catch(IOException expected) {}
}
+
+ // b/30007735
+ public void testSocketTestAllAddresses() throws Exception {
+ // Socket Ctor should try all sockets.
+ //
+ // This test creates a server socket bound to 127.0.0.1 or ::1 only, and connects using a
+ // hostname that resolves to both addresses. We should be able to connect to the server
+ // socket in either setup.
+ final String loopbackHost = ALL_LOOPBACK_HOSTNAME;
+
+ assertTrue("Loopback DNS record is unreachable or is invalid.", checkLoopbackHost(
+ loopbackHost));
+
+ final int port = 9999;
+ for (InetAddress addr : new InetAddress[]{ Inet4Address.LOOPBACK, Inet6Address.LOOPBACK }) {
+ try (ServerSocket ss = new ServerSocket(port, 0, addr)) {
+ new Thread(() -> {
+ try {
+ ss.accept();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }).start();
+
+ assertTrue(canConnect(loopbackHost, port));
+ }
+ }
+ }
+
+ /** Confirm the supplied hostname maps to only loopback addresses. */
+ private static boolean checkLoopbackHost(String host) {
+ try {
+ List<InetAddress> addrs = Arrays.asList(InetAddress.getAllByName(host));
+ return addrs.stream().allMatch(InetAddress::isLoopbackAddress) &&
+ addrs.contains(Inet4Address.LOOPBACK) && addrs.contains(Inet6Address.LOOPBACK);
+ } catch (UnknownHostException e) {
+ return false;
+ }
+ }
+
+ private static boolean canConnect(String host, int port) {
+ try(Socket sock = new Socket(host, port)) {
+ return sock.isConnected();
+ } catch (IOException e) {
+ return false;
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index fc5283b..9729cf2 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -618,29 +618,59 @@
}
public void testConnectViaProxyUsingProxyArg() throws Exception {
- testConnectViaProxy(ProxyConfig.CREATE_ARG);
+ testConnectViaProxy(ProxyConfig.CREATE_ARG, "http://android.com/foo", "android.com");
}
public void testConnectViaProxyUsingProxySystemProperty() throws Exception {
- testConnectViaProxy(ProxyConfig.PROXY_SYSTEM_PROPERTY);
+ testConnectViaProxy(
+ ProxyConfig.PROXY_SYSTEM_PROPERTY, "http://android.com/foo", "android.com");
}
public void testConnectViaProxyUsingHttpProxySystemProperty() throws Exception {
- testConnectViaProxy(ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY);
+ testConnectViaProxy(
+ ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY, "http://android.com/foo", "android.com");
}
- private void testConnectViaProxy(ProxyConfig proxyConfig) throws Exception {
+ // Regression test for http://b/29983827 : ensure that a trailing "/" is not added to the
+ // HTTP request line when using a proxy.
+ public void testConnectViaProxy_emptyPath() throws Exception {
+ testConnectViaProxy(
+ ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY, "http://android.com", "android.com");
+ }
+
+ public void testConnectViaProxy_rootPath() throws Exception {
+ testConnectViaProxy(
+ ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY, "http://android.com/", "android.com");
+ }
+
+ public void testConnectViaProxy_pathWithoutTrailingSlash() throws Exception {
+ testConnectViaProxy(
+ ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY, "http://android.com/foo", "android.com");
+ }
+
+ public void testConnectViaProxy_pathWithTrailingSlash() throws Exception {
+ testConnectViaProxy(
+ ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY, "http://android.com/foo/", "android.com");
+ }
+
+ public void testConnectViaProxy_complexUrlWithNoPath() throws Exception {
+ testConnectViaProxy(ProxyConfig.HTTP_PROXY_SYSTEM_PROPERTY,
+ "http://android.com:8080?height=100&width=42", "android.com:8080");
+ }
+
+ private void testConnectViaProxy(ProxyConfig proxyConfig, String urlString, String expectedHost)
+ throws Exception {
MockResponse mockResponse = new MockResponse().setBody("this response comes via a proxy");
server.enqueue(mockResponse);
server.play();
- URL url = new URL("http://android.com/foo");
+ URL url = new URL(urlString);
HttpURLConnection connection = proxyConfig.connect(server, url);
assertContent("this response comes via a proxy", connection);
RecordedRequest request = server.takeRequest();
- assertEquals("GET http://android.com/foo HTTP/1.1", request.getRequestLine());
- assertContains(request.getHeaders(), "Host: android.com");
+ assertEquals("GET " + urlString + " HTTP/1.1", request.getRequestLine());
+ assertContains(request.getHeaders(), "Host: " + expectedHost);
}
public void testContentDisagreesWithContentLengthHeader() throws IOException {
@@ -2266,8 +2296,13 @@
testUrlToRequestMapping("$", "$", "$");
testUrlToUriMapping("&", "&", "&", "&", "&");
testUrlToRequestMapping("&", "&", "&");
- testUrlToUriMapping("'", "'", "'", "%27", "'");
- testUrlToRequestMapping("'", "'", "%27");
+
+ // http://b/30405333 - upstream OkHttp encodes single quote (') as %27 in query parameters
+ // but this breaks iTunes remote apps: iTunes currently does not accept %27 so we have a
+ // local patch to retain the historic Android behavior of not encoding single quote.
+ testUrlToUriMapping("'", "'", "'", "'", "'");
+ testUrlToRequestMapping("'", "'", "'");
+
testUrlToUriMapping("(", "(", "(", "(", "(");
testUrlToRequestMapping("(", "(", "(");
testUrlToUriMapping(")", ")", ")", ")", ")");
diff --git a/luni/src/test/java/libcore/java/security/PrivilegedActionExceptionTest.java b/luni/src/test/java/libcore/java/security/PrivilegedActionExceptionTest.java
new file mode 100644
index 0000000..0f965e5
--- /dev/null
+++ b/luni/src/test/java/libcore/java/security/PrivilegedActionExceptionTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.security;
+
+import junit.framework.TestCase;
+
+import java.security.PrivilegedActionException;
+
+public class PrivilegedActionExceptionTest extends TestCase {
+
+ /**
+ * PrivilegedActionException's constructor argument may be rethrown by getException() or
+ * getCause().
+ * b/31360928
+ */
+ public void testGetException() {
+ Exception e = new Exception();
+ PrivilegedActionException pae = new PrivilegedActionException(e);
+
+ assertSame(e, pae.getException());
+ assertSame(e, pae.getCause());
+ }
+}
diff --git a/luni/src/test/java/libcore/java/text/DateFormatSymbolsTest.java b/luni/src/test/java/libcore/java/text/DateFormatSymbolsTest.java
index 0c97f34..eb3c8fe 100644
--- a/luni/src/test/java/libcore/java/text/DateFormatSymbolsTest.java
+++ b/luni/src/test/java/libcore/java/text/DateFormatSymbolsTest.java
@@ -161,4 +161,16 @@
}
}
}
+
+ public void test_setZoneStrings_checks_dimensions() throws Exception {
+ DateFormatSymbols dfs = DateFormatSymbols.getInstance();
+ String[][] zoneStrings = dfs.getZoneStrings();
+ zoneStrings[0] = new String[] { "id_only "};
+ try {
+ dfs.setZoneStrings(zoneStrings);
+ fail("No IllegalArgumentException when setting incorrect zoneStrings");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/java/text/DateFormatTest.java b/luni/src/test/java/libcore/java/text/DateFormatTest.java
new file mode 100644
index 0000000..8e215ab
--- /dev/null
+++ b/luni/src/test/java/libcore/java/text/DateFormatTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.java.text;
+
+import junit.framework.TestCase;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+public class DateFormatTest extends TestCase {
+
+ // Regression test for http://b/31762542. If this test fails it implies that changes to
+ // DateFormat.is24Hour will not be effective.
+ public void testIs24Hour_notCached() throws Exception {
+ Boolean originalIs24Hour = DateFormat.is24Hour;
+ try {
+ // These tests hardcode expectations for Locale.US.
+ DateFormat.is24Hour = null; // null == locale default (12 hour for US)
+ checkTimePattern(DateFormat.SHORT, "h:mm a");
+ checkTimePattern(DateFormat.MEDIUM, "h:mm:ss a");
+
+ DateFormat.is24Hour = true; // Explicit 24 hour.
+ checkTimePattern(DateFormat.SHORT, "HH:mm");
+ checkTimePattern(DateFormat.MEDIUM, "HH:mm:ss");
+
+ DateFormat.is24Hour = false; // Explicit 12 hour.
+ checkTimePattern(DateFormat.SHORT, "h:mm a");
+ checkTimePattern(DateFormat.MEDIUM, "h:mm:ss a");
+ } finally {
+ DateFormat.is24Hour = originalIs24Hour;
+ }
+ }
+
+ private static void checkTimePattern(int style, String expectedPattern) {
+ final Locale locale = Locale.US;
+ final Date current = new Date(1468250177000L); // 20160711 15:16:17 GMT
+ DateFormat format = DateFormat.getTimeInstance(style, locale);
+ String actualDateString = format.format(current);
+ SimpleDateFormat sdf = new SimpleDateFormat(expectedPattern, locale);
+ String expectedDateString = sdf.format(current);
+ assertEquals(expectedDateString, actualDateString);
+ }
+}
diff --git a/luni/src/test/java/libcore/java/text/OldBidiTest.java b/luni/src/test/java/libcore/java/text/OldBidiTest.java
index fbf68ea..fe8b6cb 100644
--- a/luni/src/test/java/libcore/java/text/OldBidiTest.java
+++ b/luni/src/test/java/libcore/java/text/OldBidiTest.java
@@ -17,6 +17,7 @@
package libcore.java.text;
+import java.text.AttributedCharacterIterator;
import java.text.Bidi;
import junit.framework.TestCase;
@@ -192,4 +193,16 @@
}
}
+ // http://b/30652865
+ public void testUnicode9EmojisAreLtrNeutral() {
+ String callMeHand = "\uD83E\uDD19"; // U+1F919 in UTF-16
+ String hebrewAndEmoji = "\u05e9\u05dc" + callMeHand + "\u05d5\u05dd";
+ String latinAndEmoji = "Hel" + callMeHand + "lo";
+ Bidi hebrew = new Bidi(hebrewAndEmoji, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
+ assertFalse("Hebrew bidi is mixed: " + hebrew, hebrew.isMixed());
+ assertTrue("Hebrew bidi is not right to left: " + hebrew, hebrew.isRightToLeft());
+ Bidi latin = new Bidi(latinAndEmoji, Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT);
+ assertFalse("Latin bidi is mixed: " + latin, latin.isMixed());
+ assertTrue("latin bidi is not left to right: " + latin, latin.isLeftToRight());
+ }
}
diff --git a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
index fe4e567..43019cc 100644
--- a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
@@ -17,6 +17,7 @@
package libcore.java.text;
import java.text.DateFormat;
+import java.text.DateFormatSymbols;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
@@ -231,6 +232,9 @@
if (d == null) {
fail(pp.toString());
}
+ if (pp.getIndex() != value.length()) {
+ fail("Value " + value + " must be fully consumed: " + pp.toString());
+ }
Calendar c = Calendar.getInstance(tz);
c.setTime(d);
return c;
@@ -472,4 +476,51 @@
df.parse("22 Jul 1977 12:23:45 HST");
assertEquals(UTC, df.getTimeZone());
}
+
+ public void testTimeZoneFormattingRespectsSetZoneStrings() throws ParseException {
+ DateFormatSymbols symbols = DateFormatSymbols.getInstance(Locale.ENGLISH);
+ String[][] zoneStrings = symbols.getZoneStrings();
+ TimeZone tz = TimeZone.getTimeZone(zoneStrings[0][0]);
+ String originalTzName = zoneStrings[0][1];
+ symbols.setZoneStrings(zoneStrings);
+ SimpleDateFormat sdf = new SimpleDateFormat("zzzz", symbols);
+ sdf.setTimeZone(tz);
+
+ // just re-setting the default values
+ assertEquals(originalTzName, sdf.format(new Date(1376927400000L)));
+
+ // providing a custom name
+ zoneStrings[0][1] = "CustomTimeZone";
+ symbols.setZoneStrings(zoneStrings);
+ sdf = new SimpleDateFormat("zzzz", symbols);
+ sdf.setTimeZone(tz);
+ assertEquals("CustomTimeZone", sdf.format(new Date(1376927400000L)));
+
+ // setting the name to null should format as GMT[+-]...
+ zoneStrings[0][1] = null;
+ symbols.setZoneStrings(zoneStrings);
+ sdf = new SimpleDateFormat("zzzz", symbols);
+ sdf.setTimeZone(tz);
+ assertTrue(sdf.format(new Date(1376927400000L)).startsWith("GMT"));
+ }
+
+ // http://b/30323478
+ public void testStandaloneWeekdayParsing() throws Exception {
+ Locale fi = new Locale("fi"); // Finnish has separate standalone weekday names
+ // tiistaina = Tuesday (regular)
+ // tiistai = Tuesday (standalone)
+ assertEquals(Calendar.TUESDAY,
+ parseDateUtc(fi, "cccc yyyy", "tiistai 2000").get(Calendar.DAY_OF_WEEK));
+ assertEquals(Calendar.TUESDAY,
+ parseDateUtc(fi, "EEEE yyyy", "tiistaina 2000").get(Calendar.DAY_OF_WEEK));
+ assertCannotParse(fi, "cccc yyyy", "tiistaina 2000");
+ assertCannotParse(fi, "EEEE yyyy", "tiistai 2000");
+ }
+
+ // http://b/30323478
+ public void testStandaloneWeekdayFormatting() throws Exception {
+ Locale fi = new Locale("fi"); // Finnish has separate standalone weekday names
+ assertEquals("torstai", formatDateUtc(fi, "cccc"));
+ assertEquals("torstaina", formatDateUtc(fi, "EEEE"));
+ }
}
diff --git a/luni/src/test/java/libcore/java/util/TimeZoneTest.java b/luni/src/test/java/libcore/java/util/TimeZoneTest.java
index 5a6fa7f..cb2cd0f 100644
--- a/luni/src/test/java/libcore/java/util/TimeZoneTest.java
+++ b/luni/src/test/java/libcore/java/util/TimeZoneTest.java
@@ -16,13 +16,20 @@
package libcore.java.util;
+import junit.framework.TestCase;
+
import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.Calendar;
+import java.util.Collections;
import java.util.Date;
+import java.util.List;
import java.util.Locale;
import java.util.SimpleTimeZone;
import java.util.TimeZone;
-import junit.framework.TestCase;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.atomic.AtomicInteger;
public class TimeZoneTest extends TestCase {
// http://code.google.com/p/android/issues/detail?id=877
@@ -261,6 +268,31 @@
assertEquals("", failures.toString());
}
+ // http://b/30527513
+ public void testDisplayNamesWithScript() throws Exception {
+ Locale latinLocale = Locale.forLanguageTag("sr-Latn-RS");
+ Locale cyrillicLocale = Locale.forLanguageTag("sr-Cyrl-RS");
+ Locale noScriptLocale = Locale.forLanguageTag("sr-RS");
+ TimeZone tz = TimeZone.getTimeZone("Europe/London");
+
+ final String latinName = "Srednje vreme po Griniču";
+ final String cyrillicName = "Средње време по Гриничу";
+
+ // Check java.util.TimeZone
+ assertEquals(latinName, tz.getDisplayName(latinLocale));
+ assertEquals(cyrillicName, tz.getDisplayName(cyrillicLocale));
+ assertEquals(cyrillicName, tz.getDisplayName(noScriptLocale));
+
+ // Check ICU TimeZoneNames
+ // The one-argument getDisplayName() override uses LONG_GENERIC style which is different
+ // from what java.util.TimeZone uses. Force the LONG style to get equivalent results.
+ final int style = android.icu.util.TimeZone.LONG;
+ android.icu.util.TimeZone utz = android.icu.util.TimeZone.getTimeZone(tz.getID());
+ assertEquals(latinName, utz.getDisplayName(false, style, latinLocale));
+ assertEquals(cyrillicName, utz.getDisplayName(false, style, cyrillicLocale));
+ assertEquals(cyrillicName, utz.getDisplayName(false, style, noScriptLocale));
+ }
+
// http://b/7955614
public void testApia() throws Exception {
TimeZone tz = TimeZone.getTimeZone("Pacific/Apia");
@@ -340,4 +372,107 @@
TimeZone.setDefault(origTz);
}
}
+
+ // http://b/30937209
+ public void testSetDefaultDeadlock() throws InterruptedException, BrokenBarrierException {
+ // Since this tests a deadlock, the test has two fundamental problems:
+ // - it is probabilistic: it's not guaranteed to fail if the problem exists
+ // - if it fails, it will effectively hang the current runtime, as no other thread will
+ // be able to call TimeZone.getDefault()/setDefault() successfully any more.
+
+ // 10 was too low to be reliable, 100 failed more than half the time (on a bullhead).
+ final int iterations = 100;
+ TimeZone otherTimeZone = TimeZone.getTimeZone("Europe/London");
+ AtomicInteger setterCount = new AtomicInteger();
+ CyclicBarrier startBarrier = new CyclicBarrier(2);
+ Thread setter = new Thread(() -> {
+ waitFor(startBarrier);
+ for (int i = 0; i < iterations; i++) {
+ TimeZone.setDefault(otherTimeZone);
+ TimeZone.setDefault(null);
+ setterCount.set(i+1);
+ }
+ });
+ setter.setName("testSetDefaultDeadlock setter");
+
+ AtomicInteger getterCount = new AtomicInteger();
+ Thread getter = new Thread(() -> {
+ waitFor(startBarrier);
+ for (int i = 0; i < iterations; i++) {
+ android.icu.util.TimeZone.getDefault();
+ getterCount.set(i+1);
+ }
+ });
+ getter.setName("testSetDefaultDeadlock getter");
+
+ setter.start();
+ getter.start();
+
+ // 2 seconds is plenty: If successful, we usually complete much faster.
+ setter.join(1000);
+ getter.join(1000);
+ if (setter.isAlive() || getter.isAlive()) {
+ fail("Threads are still alive. Getter iteration count: " + getterCount.get()
+ + ", setter iteration count: " + setterCount.get());
+ }
+ // Guard against unexpected uncaught exceptions.
+ assertEquals("Setter iterations", iterations, setterCount.get());
+ assertEquals("Getter iterations", iterations, getterCount.get());
+ }
+
+ // http://b/30979219
+ public void testSetDefaultRace() throws InterruptedException {
+ // Since this tests a race condition, the test is probabilistic: it's not guaranteed to
+ // fail if the problem exists
+
+ // These iterations are significantly faster than the ones in #testSetDefaultDeadlock
+ final int iterations = 10000;
+ List<Throwable> exceptions = Collections.synchronizedList(new ArrayList<>());
+ Thread.UncaughtExceptionHandler handler = (t, e) -> exceptions.add(e);
+
+ CyclicBarrier startBarrier = new CyclicBarrier(2);
+ Thread clearer = new Thread(() -> {
+ waitFor(startBarrier);
+ for (int i = 0; i < iterations; i++) {
+ // This is not public API but can effectively be invoked via
+ // java.util.TimeZone.setDefault. Call it directly to reduce the amount of code
+ // involved in this test.
+ android.icu.util.TimeZone.clearCachedDefault();
+ }
+ });
+ clearer.setName("testSetDefaultRace clearer");
+ clearer.setUncaughtExceptionHandler(handler);
+
+ Thread getter = new Thread(() -> {
+ waitFor(startBarrier);
+ for (int i = 0; i < iterations; i++) {
+ android.icu.util.TimeZone.getDefault();
+ }
+ });
+ getter.setName("testSetDefaultRace getter");
+ getter.setUncaughtExceptionHandler(handler);
+
+ clearer.start();
+ getter.start();
+
+ // 2 seconds is plenty: If successful, we usually complete much faster.
+ clearer.join(1000);
+ getter.join(1000);
+
+ if (!exceptions.isEmpty()) {
+ Throwable firstException = exceptions.get(0);
+ firstException.printStackTrace();
+ fail("Threads did not succeed successfully: " + firstException);
+ }
+ assertFalse("clearer thread is still alive", clearer.isAlive());
+ assertFalse("getter thread is still alive", getter.isAlive());
+ }
+
+ private static void waitFor(CyclicBarrier barrier) {
+ try {
+ barrier.await();
+ } catch (InterruptedException | BrokenBarrierException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java b/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java
index 02210ac..2175289 100644
--- a/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java
+++ b/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java
@@ -16,7 +16,19 @@
package libcore.java.util.zip;
+import android.system.OsConstants;
+import libcore.io.Libcore;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
import java.io.OutputStream;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
public final class ZipFileTest extends AbstractZipFileTest {
@@ -25,4 +37,52 @@
protected ZipOutputStream createZipOutputStream(OutputStream wrapped) {
return new ZipOutputStream(wrapped);
}
+
+ // http://b/30407219
+ public void testZipFileOffsetNeverChangesAfterInit() throws Exception {
+ final File f = createTemporaryZipFile();
+ writeEntries(createZipOutputStream(new BufferedOutputStream(new FileOutputStream(f))),
+ 2 /* number of entries */, 1024 /* entry size */, true /* setEntrySize */);
+
+ ZipFile zipFile = new ZipFile(f);
+ FileDescriptor fd = new FileDescriptor();
+ fd.setInt$(zipFile.getFileDescriptor());
+
+ long initialOffset = android.system.Os.lseek(fd, 0, OsConstants.SEEK_CUR);
+
+ Enumeration<? extends ZipEntry> entries = zipFile.entries();
+ assertOffset(initialOffset, fd);
+
+ // Get references to the two elements in the file.
+ ZipEntry entry1 = entries.nextElement();
+ ZipEntry entry2 = entries.nextElement();
+ assertFalse(entries.hasMoreElements());
+ assertOffset(initialOffset, fd);
+
+ InputStream is1 = zipFile.getInputStream(entry1);
+ assertOffset(initialOffset, fd);
+ is1.read(new byte[256]);
+ assertOffset(initialOffset, fd);
+ is1.close();
+
+ assertNotNull(zipFile.getEntry(entry2.getName()));
+ assertOffset(initialOffset, fd);
+
+ zipFile.close();
+ }
+
+ private static void assertOffset(long initialOffset, FileDescriptor fd) throws Exception {
+ long currentOffset = android.system.Os.lseek(fd, 0, OsConstants.SEEK_CUR);
+ assertEquals(initialOffset, currentOffset);
+ }
+
+ // b/31077136
+ public void test_FileNotFound() throws Exception {
+ File nonExistentFile = new File("fileThatDefinitelyDoesntExist.zip");
+ assertFalse(nonExistentFile.exists());
+
+ try (ZipFile zipFile = new ZipFile(nonExistentFile, ZipFile.OPEN_READ)) {
+ fail();
+ } catch(FileNotFoundException expected) {}
+ }
}
diff --git a/luni/src/test/java/libcore/javax/crypto/MacTest.java b/luni/src/test/java/libcore/javax/crypto/MacTest.java
index 314a564..b308f02 100644
--- a/luni/src/test/java/libcore/javax/crypto/MacTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/MacTest.java
@@ -59,4 +59,14 @@
Security.removeProvider(mockProvider.getName());
}
}
+
+ /**
+ * Aliases used to be wrong due to a typo.
+ * http://b/31114355
+ */
+ public void testMac_correctAlias() throws Exception {
+ Provider androidOpenSSLProvider = Security.getProvider("AndroidOpenSSL");
+ assertEquals("HmacSHA224", androidOpenSSLProvider.get("Alg.Alias.Mac.1.2.840.113549.2.8"));
+ assertEquals("HmacSHA256", androidOpenSSLProvider.get("Alg.Alias.Mac.1.2.840.113549.2.9"));
+ }
}
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
index d17e32b..5e94b21 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
@@ -80,6 +80,8 @@
import libcore.tlswire.handshake.CipherSuite;
import libcore.tlswire.handshake.ClientHello;
import libcore.tlswire.handshake.CompressionMethod;
+import libcore.tlswire.handshake.EllipticCurve;
+import libcore.tlswire.handshake.EllipticCurvesHelloExtension;
import libcore.tlswire.handshake.HandshakeMessage;
import libcore.tlswire.handshake.HelloExtension;
import libcore.tlswire.handshake.ServerNameHelloExtension;
@@ -1693,6 +1695,31 @@
}, getSSLSocketFactoriesToTest());
}
+ public void test_SSLSocket_ClientHello_supportedCurves() throws Exception {
+ ForEachRunner.runNamed(new ForEachRunner.Callback<SSLSocketFactory>() {
+ @Override
+ public void run(SSLSocketFactory sslSocketFactory) throws Exception {
+ ClientHello clientHello = captureTlsHandshakeClientHello(sslSocketFactory);
+
+ EllipticCurvesHelloExtension ecExtension = (EllipticCurvesHelloExtension)
+ clientHello.findExtensionByType(HelloExtension.TYPE_ELLIPTIC_CURVES);
+ final String[] supportedCurves;
+ if (ecExtension == null) {
+ supportedCurves = new String[0];
+ } else {
+ assertTrue(ecExtension.wellFormed);
+ supportedCurves = new String[ecExtension.supported.size()];
+ for (int i = 0; i < ecExtension.supported.size(); i++) {
+ EllipticCurve curve = ecExtension.supported.get(i);
+ supportedCurves[i] = curve.toString();
+ }
+ }
+
+ StandardNames.assertDefaultEllipticCurves(supportedCurves);
+ }
+ }, getSSLSocketFactoriesToTest());
+ }
+
public void test_SSLSocket_ClientHello_clientProtocolVersion() throws Exception {
ForEachRunner.runNamed(new ForEachRunner.Callback<SSLSocketFactory>() {
@Override
diff --git a/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java b/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
index 4f5d658..5471b1f 100644
--- a/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
+++ b/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
@@ -120,6 +120,30 @@
expectExceptionInDNConstructor("l=\\g0");
}
+ public void testNegativeLen() {
+ try {
+ X500Principal p = new X500Principal(new byte[]{
+ 0x30, // DerValue.tag_Sequence read in DerValue#getSequence
+ 9, // Length of the vector. read in readVector.
+ // DerInputStream.getLength will just return this as 10 & 0x80 == 0
+ -1, // Tag of the first value in the sequencevalue. Convenient so that it
+ // doesn't hold DerIndefLenConverter.isEOC()
+ (byte) 0x80, // Encoding in indefinite form
+ -1, // Second tag to be read by DerIndefLenConverter
+ (byte) 0x84, // Second length byte to be read, 0x80 means long form, 4 bytes
+ (byte) 0xff, // Length to be read by DerIndefLenConverter, -6, will move the
+ // buffer position to the second tag
+ (byte) 0xff,
+ (byte) 0xff,
+ (byte) -6,
+ 0, // Needed as otherwise it's detected that there's nothing after
+ // the length
+ });
+ fail("expected IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
private void expectExceptionInDNConstructor(String dn) {
try {
X500Principal principal = new X500Principal(dn);
diff --git a/luni/src/test/java/libcore/net/MimeUtilsTest.java b/luni/src/test/java/libcore/net/MimeUtilsTest.java
index ff22632..8b34ea2 100644
--- a/luni/src/test/java/libcore/net/MimeUtilsTest.java
+++ b/luni/src/test/java/libcore/net/MimeUtilsTest.java
@@ -18,8 +18,6 @@
import junit.framework.TestCase;
-import libcore.net.MimeUtils;
-
public class MimeUtilsTest extends TestCase {
public void test_15715370() {
assertEquals("audio/flac", MimeUtils.guessMimeTypeFromExtension("flac"));
@@ -52,4 +50,11 @@
public void test_18390752() {
assertEquals("jpg", MimeUtils.guessExtensionFromMimeType("image/jpeg"));
}
+
+ public void test_30793548() {
+ assertEquals("video/3gpp", MimeUtils.guessMimeTypeFromExtension("3gpp"));
+ assertEquals("video/3gpp", MimeUtils.guessMimeTypeFromExtension("3gp"));
+ assertEquals("video/3gpp2", MimeUtils.guessMimeTypeFromExtension("3gpp2"));
+ assertEquals("video/3gpp2", MimeUtils.guessMimeTypeFromExtension("3g2"));
+ }
}
diff --git a/luni/src/test/resources/tests/api/java/io/sameFieldNames.dex b/luni/src/test/resources/tests/api/java/io/sameFieldNames.dex
new file mode 100644
index 0000000..ada4935
--- /dev/null
+++ b/luni/src/test/resources/tests/api/java/io/sameFieldNames.dex
Binary files differ
diff --git a/luni/src/test/resources/tests/api/java/io/sameFieldNames.smali b/luni/src/test/resources/tests/api/java/io/sameFieldNames.smali
new file mode 100644
index 0000000..657b965
--- /dev/null
+++ b/luni/src/test/resources/tests/api/java/io/sameFieldNames.smali
@@ -0,0 +1,17 @@
+# Source for sameFieldNames.dex
+.class public LsameFieldNames;
+.super Ljava/lang/Object;
+.implements Ljava/io/Serializable;
+
+# Test multiple fields with the same name and different types.
+# (Invalid in Java language but valid in bytecode.)
+.field public a:J
+.field public a:I
+.field public a:Ljava/lang/Integer;
+.field public a:Ljava/lang/Long;
+
+.method public constructor <init>()V
+ .registers 2
+ invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ return-void
+.end method
diff --git a/ojluni/src/main/java/com/sun/net/ssl/internal/ssl/Provider.java b/ojluni/src/main/java/com/sun/net/ssl/internal/ssl/Provider.java
deleted file mode 100755
index b1a08ce..0000000
--- a/ojluni/src/main/java/com/sun/net/ssl/internal/ssl/Provider.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package com.sun.net.ssl.internal.ssl;
-
-import sun.security.ssl.SunJSSE;
-
-/**
- * Main class for the SunJSSE provider. The actual code was moved to the
- * class sun.security.ssl.SunJSSE, but for backward compatibility we
- * continue to use this class as the main Provider class.
- */
-public final class Provider extends SunJSSE {
-
- private static final long serialVersionUID = 3231825739635378733L;
-
- // standard constructor
- public Provider() {
- super();
- }
-
- // prefered constructor to enable FIPS mode at runtime
- public Provider(java.security.Provider cryptoProvider) {
- super(cryptoProvider);
- }
-
- // constructor to enable FIPS mode from java.security file
- public Provider(String cryptoProvider) {
- super(cryptoProvider);
- }
-
- // public for now, but we may want to change it or not document it.
- public static synchronized boolean isFIPS() {
- return SunJSSE.isFIPS();
- }
-
- /**
- * Installs the JSSE provider.
- */
- public static synchronized void install() {
- /* nop. Remove this method in the future. */
- }
-
-}
diff --git a/ojluni/src/main/java/java/io/DataInputStream.java b/ojluni/src/main/java/java/io/DataInputStream.java
index 7b24b74..19d4067 100755
--- a/ojluni/src/main/java/java/io/DataInputStream.java
+++ b/ojluni/src/main/java/java/io/DataInputStream.java
@@ -25,6 +25,9 @@
package java.io;
+import java.nio.ByteOrder;
+import libcore.io.Memory;
+
/**
* A data input stream lets an application read primitive Java data
* types from an underlying input stream in a machine-independent
@@ -309,11 +312,10 @@
* @see java.io.FilterInputStream#in
*/
public final short readShort() throws IOException {
- int ch1 = in.read();
- int ch2 = in.read();
- if ((ch1 | ch2) < 0)
- throw new EOFException();
- return (short)((ch1 << 8) + (ch2 << 0));
+ // b/30268192
+ // Android-changed: Use read(byte[], int, int) instead of read().
+ readFully(readBuffer, 0, 2);
+ return Memory.peekShort(readBuffer, 0, ByteOrder.BIG_ENDIAN);
}
/**
@@ -334,11 +336,10 @@
* @see java.io.FilterInputStream#in
*/
public final int readUnsignedShort() throws IOException {
- int ch1 = in.read();
- int ch2 = in.read();
- if ((ch1 | ch2) < 0)
- throw new EOFException();
- return (ch1 << 8) + (ch2 << 0);
+ // b/30268192
+ // Android-changed: Use read(byte[], int, int) instead of read().
+ readFully(readBuffer, 0, 2);
+ return Memory.peekShort(readBuffer, 0, ByteOrder.BIG_ENDIAN) & 0xffff;
}
/**
@@ -359,11 +360,10 @@
* @see java.io.FilterInputStream#in
*/
public final char readChar() throws IOException {
- int ch1 = in.read();
- int ch2 = in.read();
- if ((ch1 | ch2) < 0)
- throw new EOFException();
- return (char)((ch1 << 8) + (ch2 << 0));
+ // b/30268192
+ // Android-changed: Use read(byte[], int, int) instead of read().
+ readFully(readBuffer, 0, 2);
+ return (char)Memory.peekShort(readBuffer, 0, ByteOrder.BIG_ENDIAN);
}
/**
@@ -384,13 +384,10 @@
* @see java.io.FilterInputStream#in
*/
public final int readInt() throws IOException {
- int ch1 = in.read();
- int ch2 = in.read();
- int ch3 = in.read();
- int ch4 = in.read();
- if ((ch1 | ch2 | ch3 | ch4) < 0)
- throw new EOFException();
- return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
+ // b/30268192
+ // Android-changed: Use read(byte[], int, int) instead of read().
+ readFully(readBuffer, 0, 4);
+ return Memory.peekInt(readBuffer, 0, ByteOrder.BIG_ENDIAN);
}
private byte readBuffer[] = new byte[8];
diff --git a/ojluni/src/main/java/java/io/ObjectStreamClass.java b/ojluni/src/main/java/java/io/ObjectStreamClass.java
index a157f4d..ffbde98 100755
--- a/ojluni/src/main/java/java/io/ObjectStreamClass.java
+++ b/ojluni/src/main/java/java/io/ObjectStreamClass.java
@@ -2246,13 +2246,9 @@
ObjectStreamField f = fields[i], m = null;
for (int j = 0; j < localFields.length; j++) {
ObjectStreamField lf = localFields[j];
- if (f.getName().equals(lf.getName())) {
- if ((f.isPrimitive() || lf.isPrimitive()) &&
- f.getTypeCode() != lf.getTypeCode())
- {
- throw new InvalidClassException(localDesc.name,
- "incompatible types for field " + f.getName());
- }
+ // Android-changed: We can have fields with a same name and a different type.
+ if (f.getName().equals(lf.getName()) &&
+ f.getSignature().equals(lf.getSignature())) {
if (lf.getField() != null) {
m = new ObjectStreamField(
lf.getField(), lf.isUnshared(), false);
diff --git a/ojluni/src/main/java/java/lang/Character.java b/ojluni/src/main/java/java/lang/Character.java
index 5b9038a..267d1a7 100755
--- a/ojluni/src/main/java/java/lang/Character.java
+++ b/ojluni/src/main/java/java/lang/Character.java
@@ -6227,6 +6227,15 @@
* @since 1.5
*/
public static int toLowerCase(int codePoint) {
+ if (codePoint >= 'A' && codePoint <= 'Z') {
+ return codePoint + ('a' - 'A');
+ }
+
+ // All ASCII codepoints except the ones above remain unchanged.
+ if (codePoint < 0x80) {
+ return codePoint;
+ }
+
return toLowerCaseImpl(codePoint);
}
@@ -6289,6 +6298,15 @@
* @since 1.5
*/
public static int toUpperCase(int codePoint) {
+ if (codePoint >= 'a' && codePoint <= 'z') {
+ return codePoint - ('a' - 'A');
+ }
+
+ // All ASCII codepoints except the ones above remain unchanged.
+ if (codePoint < 0x80) {
+ return codePoint;
+ }
+
return toUpperCaseImpl(codePoint);
}
diff --git a/ojluni/src/main/java/java/lang/Runtime.java b/ojluni/src/main/java/java/lang/Runtime.java
index 61c2502..5e63dd8 100755
--- a/ojluni/src/main/java/java/lang/Runtime.java
+++ b/ojluni/src/main/java/java/lang/Runtime.java
@@ -868,11 +868,22 @@
*/
@CallerSensitive
public void load(String filename) {
- load0(VMStack.getStackClass2(), filename);
+ load0(VMStack.getStackClass1(), filename);
+ }
+
+ /** Check target sdk, if it's higher than N, we throw an UnsupportedOperationException */
+ private void checkTargetSdkVersionForLoad(String methodName) {
+ final int targetSdkVersion = VMRuntime.getRuntime().getTargetSdkVersion();
+ if (targetSdkVersion > 24) {
+ throw new UnsupportedOperationException(methodName + " is not supported on SDK " +
+ targetSdkVersion);
+ }
}
// Fixes b/25859957 regression. Depending on private methods is bad, mkay.
void load(String absolutePath, ClassLoader loader) {
+ checkTargetSdkVersionForLoad("java.lang.Runtime#load(String, ClassLoader)");
+
java.lang.System.logE("java.lang.Runtime#load(String, ClassLoader)" +
" is private and will be removed in a future Android release");
if (absolutePath == null) {
@@ -951,6 +962,7 @@
* @hide
*/
public void loadLibrary(String libname, ClassLoader classLoader) {
+ checkTargetSdkVersionForLoad("java.lang.Runtime#loadLibrary(String, ClassLoader)");
java.lang.System.logE("java.lang.Runtime#loadLibrary(String, ClassLoader)" +
" is private and will be removed in a future Android release");
loadLibrary0(classLoader, libname);
diff --git a/ojluni/src/main/java/java/net/DatagramSocket.java b/ojluni/src/main/java/java/net/DatagramSocket.java
index 966f30f..13b54b0 100755
--- a/ojluni/src/main/java/java/net/DatagramSocket.java
+++ b/ojluni/src/main/java/java/net/DatagramSocket.java
@@ -142,37 +142,34 @@
if (!isBound())
bind(new InetSocketAddress(0));
- // ----- BEGIN android -----
- connectedAddress = address;
- connectedPort = port;
- // ----- END android -----
-
- // old impls do not support connect/disconnect
- if (oldImpl || (impl instanceof AbstractPlainDatagramSocketImpl &&
- ((AbstractPlainDatagramSocketImpl)impl).nativeConnectDisabled())) {
- connectState = ST_CONNECTED_NO_IMPL;
- } else {
- /* ----- BEGIN android -----
- try {
- getImpl().connect(address, port);
-
- // socket is now connected by the impl
- connectState = ST_CONNECTED;
- } catch (SocketException se) {
- // connection will be emulated by DatagramSocket
+ // Android-changed: This section now throws any SocketException generated by connect()
+ // to enable it to be recorded as the pendingConnectException. It has been enclosed in a
+ // try-finally to ensure connectedAddress and connectedPort are set when the exception
+ // is thrown.
+ try {
+ // old impls do not support connect/disconnect
+ // Android-changed: Added special handling for AbstractPlainDatagramSocketImpl in
+ // the condition below.
+ if (oldImpl || (impl instanceof AbstractPlainDatagramSocketImpl &&
+ ((AbstractPlainDatagramSocketImpl)impl).nativeConnectDisabled())) {
connectState = ST_CONNECTED_NO_IMPL;
- }*/
- getImpl().connect(address, port);
+ } else {
+ try {
+ getImpl().connect(address, port);
- // socket is now connected by the impl
- connectState = ST_CONNECTED;
- // ----- END android -----
+ // socket is now connected by the impl
+ connectState = ST_CONNECTED;
+ } catch (SocketException se) {
+ // connection will be emulated by DatagramSocket
+ connectState = ST_CONNECTED_NO_IMPL;
+ // Android-changed: Propagate the SocketException so connect() can store it.
+ throw se;
+ }
+ }
+ } finally {
+ connectedAddress = address;
+ connectedPort = port;
}
-
- /* ----- BEGIN android -----
- connectedAddress = address;
- connectedPort = port;
- ----- END android ----- */
}
diff --git a/ojluni/src/main/java/java/net/Inet6Address.java b/ojluni/src/main/java/java/net/Inet6Address.java
index 4b353e5..d55fab9 100755
--- a/ojluni/src/main/java/java/net/Inet6Address.java
+++ b/ojluni/src/main/java/java/net/Inet6Address.java
@@ -174,7 +174,7 @@
new Inet6Address("::", new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 0);
/** @hide */
- public static final InetAddress LOOPBACK = new Inet6Address("localhost",
+ public static final InetAddress LOOPBACK = new Inet6Address("ip6-localhost",
new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, 0);
/**
diff --git a/ojluni/src/main/java/java/net/Socket.java b/ojluni/src/main/java/java/net/Socket.java
index 2aa057f..96a7355 100755
--- a/ojluni/src/main/java/java/net/Socket.java
+++ b/ojluni/src/main/java/java/net/Socket.java
@@ -207,9 +207,7 @@
public Socket(String host, int port)
throws UnknownHostException, IOException
{
- this(host != null ? new InetSocketAddress(host, port) :
- new InetSocketAddress(InetAddress.getByName(null), port),
- (SocketAddress) null, true);
+ this(InetAddress.getAllByName(host), port, (SocketAddress) null, true);
}
/**
@@ -240,8 +238,7 @@
* @see SecurityManager#checkConnect
*/
public Socket(InetAddress address, int port) throws IOException {
- this(address != null ? new InetSocketAddress(address, port) : null,
- (SocketAddress) null, true);
+ this(nonNullAddress(address), port, (SocketAddress) null, true);
}
/**
@@ -279,8 +276,7 @@
*/
public Socket(String host, int port, InetAddress localAddr,
int localPort) throws IOException {
- this(host != null ? new InetSocketAddress(host, port) :
- new InetSocketAddress(InetAddress.getByName(null), port),
+ this(InetAddress.getAllByName(host), port,
new InetSocketAddress(localAddr, localPort), true);
}
@@ -318,7 +314,7 @@
*/
public Socket(InetAddress address, int port, InetAddress localAddr,
int localPort) throws IOException {
- this(address != null ? new InetSocketAddress(address, port) : null,
+ this(nonNullAddress(address), port,
new InetSocketAddress(localAddr, localPort), true);
}
@@ -364,9 +360,7 @@
*/
@Deprecated
public Socket(String host, int port, boolean stream) throws IOException {
- this(host != null ? new InetSocketAddress(host, port) :
- new InetSocketAddress(InetAddress.getByName(null), port),
- (SocketAddress) null, stream);
+ this(InetAddress.getAllByName(host), port, (SocketAddress) null, stream);
}
/**
@@ -407,32 +401,57 @@
*/
@Deprecated
public Socket(InetAddress host, int port, boolean stream) throws IOException {
- this(host != null ? new InetSocketAddress(host, port) : null,
- new InetSocketAddress(0), stream);
+ this(nonNullAddress(host), port, new InetSocketAddress(0), stream);
}
- private Socket(SocketAddress address, SocketAddress localAddr,
- boolean stream) throws IOException {
- setImpl();
-
+ private static InetAddress[] nonNullAddress(InetAddress address) {
// backward compatibility
if (address == null)
throw new NullPointerException();
- try {
- createImpl(stream);
- if (localAddr != null)
- bind(localAddr);
- if (address != null)
+ return new InetAddress[] { address };
+ }
+
+ // Android-changed: Socket ctor should try all addresses
+ // b/30007735
+ private Socket(InetAddress[] addresses, int port, SocketAddress localAddr,
+ boolean stream) throws IOException {
+ if (addresses == null || addresses.length == 0) {
+ throw new SocketException("Impossible: empty address list");
+ }
+
+ for (int i = 0; i < addresses.length; i++) {
+ setImpl();
+ try {
+ InetSocketAddress address = new InetSocketAddress(addresses[i], port);
+ createImpl(stream);
+ if (localAddr != null) {
+ bind(localAddr);
+ }
connect(address);
- } catch (IOException e) {
- // Do not call #close, classes that extend this class may do not expect a call
- // to #close coming from the superclass constructor.
- if (impl != null) {
- impl.close();
+ break;
+ } catch (IOException | IllegalArgumentException | SecurityException e) {
+ try {
+ // Android-changed:
+ // Do not call #close, classes that extend this class may do not expect a call
+ // to #close coming from the superclass constructor.
+ impl.close();
+ closed = true;
+ } catch (IOException ce) {
+ e.addSuppressed(ce);
+ }
+
+ // Only stop on the last address.
+ if (i == addresses.length - 1) {
+ throw e;
+ }
}
- closed = true;
- throw e;
+
+ // Discard the connection state and try again.
+ impl = null;
+ created = false;
+ bound = false;
+ closed = false;
}
}
diff --git a/ojluni/src/main/java/java/nio/charset/Charset.java b/ojluni/src/main/java/java/nio/charset/Charset.java
index f85b82b..17e1160 100755
--- a/ojluni/src/main/java/java/nio/charset/Charset.java
+++ b/ojluni/src/main/java/java/nio/charset/Charset.java
@@ -214,10 +214,7 @@
* input sequence are not omitted since the same code is used to represent
* <small>ZERO-WIDTH NON-BREAKING SPACE</small>.
*
- * <p> Every instance of the Java virtual machine has a default charset, which
- * may or may not be one of the standard charsets. The default charset is
- * determined during virtual-machine startup and typically depends upon the
- * locale and charset being used by the underlying operating system. </p>
+ * <p>Android note: The Android platform default is always UTF-8.
*
* <p>The {@link StandardCharsets} class defines constants for each of the
* standard charsets.
@@ -653,9 +650,7 @@
/**
* Returns the default charset of this Java virtual machine.
*
- * <p> The default charset is determined during virtual-machine startup and
- * typically depends upon the locale and charset of the underlying
- * operating system.
+ * <p>Android note: The Android platform default is always UTF-8.
*
* @return A charset object for the default charset
*
diff --git a/ojluni/src/main/java/java/security/PrivilegedActionException.java b/ojluni/src/main/java/java/security/PrivilegedActionException.java
index af89fb5..83d855a 100755
--- a/ojluni/src/main/java/java/security/PrivilegedActionException.java
+++ b/ojluni/src/main/java/java/security/PrivilegedActionException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,11 +27,81 @@
/**
* Legacy security code; do not use.
+ *
+ * This exception is thrown by
+ * {@code doPrivileged(PrivilegedExceptionAction)} and
+ * {@code doPrivileged(PrivilegedExceptionAction,
+ * AccessControlContext context)} to indicate
+ * that the action being performed threw a checked exception. The exception
+ * thrown by the action can be obtained by calling the
+ * {@code getException} method. In effect, an
+ * {@code PrivilegedActionException} is a "wrapper"
+ * for an exception thrown by a privileged action.
+ *
+ * <p>As of release 1.4, this exception has been retrofitted to conform to
+ * the general purpose exception-chaining mechanism. The "exception thrown
+ * by the privileged computation" that is provided at construction time and
+ * accessed via the {@link #getException()} method is now known as the
+ * <i>cause</i>, and may be accessed via the {@link Throwable#getCause()}
+ * method, as well as the aforementioned "legacy method."
+ *
+ * @see PrivilegedExceptionAction
+ * @see AccessController#doPrivileged(PrivilegedExceptionAction)
+ * @see AccessController#doPrivileged(PrivilegedExceptionAction,AccessControlContext)
*/
-
public class PrivilegedActionException extends Exception {
+ // use serialVersionUID from JDK 1.2.2 for interoperability
+ private static final long serialVersionUID = 4724086851538908602L;
- public PrivilegedActionException(Exception exception) { super(exception); }
+ /**
+ * @serial
+ */
+ private Exception exception;
- public Exception getException() { return null; }
+ /**
+ * Constructs a new PrivilegedActionException "wrapping"
+ * the specific Exception.
+ *
+ * @param exception The exception thrown
+ */
+ public PrivilegedActionException(Exception exception) {
+ super((Throwable)null); // Disallow initCause
+ this.exception = exception;
+ }
+
+ /**
+ * Returns the exception thrown by the privileged computation that
+ * resulted in this {@code PrivilegedActionException}.
+ *
+ * <p>This method predates the general-purpose exception chaining facility.
+ * The {@link Throwable#getCause()} method is now the preferred means of
+ * obtaining this information.
+ *
+ * @return the exception thrown by the privileged computation that
+ * resulted in this {@code PrivilegedActionException}.
+ * @see PrivilegedExceptionAction
+ * @see AccessController#doPrivileged(PrivilegedExceptionAction)
+ * @see AccessController#doPrivileged(PrivilegedExceptionAction,
+ * AccessControlContext)
+ */
+ public Exception getException() {
+ return exception;
+ }
+
+ /**
+ * Returns the cause of this exception (the exception thrown by
+ * the privileged computation that resulted in this
+ * {@code PrivilegedActionException}).
+ *
+ * @return the cause of this exception.
+ * @since 1.4
+ */
+ public Throwable getCause() {
+ return exception;
+ }
+
+ public String toString() {
+ String s = getClass().getName();
+ return (exception != null) ? (s + ": " + exception.toString()) : s;
+ }
}
diff --git a/ojluni/src/main/java/java/text/SimpleDateFormat.java b/ojluni/src/main/java/java/text/SimpleDateFormat.java
index b435583..62cbd00 100755
--- a/ojluni/src/main/java/java/text/SimpleDateFormat.java
+++ b/ojluni/src/main/java/java/text/SimpleDateFormat.java
@@ -52,6 +52,8 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import libcore.icu.LocaleData;
+import libcore.icu.TimeZoneNames;
+
import sun.util.calendar.CalendarUtils;
import static java.text.DateFormatSymbols.*;
@@ -500,12 +502,6 @@
private static final String GMT = "GMT";
/**
- * Cache to hold the DateTimePatterns of a Locale.
- */
- private static final ConcurrentMap<Locale, String[]> cachedLocaleData
- = new ConcurrentHashMap<Locale, String[]>(3);
-
- /**
* Cache NumberFormat instances with Locale key.
*/
private static final ConcurrentMap<Locale, NumberFormat> cachedNumberFormatData
@@ -616,33 +612,20 @@
// initialize calendar and related fields
initializeCalendar(loc);
- /* try the cache first */
- String[] dateTimePatterns = cachedLocaleData.get(loc);
- if (dateTimePatterns == null) { /* cache miss */
- LocaleData localeData = LocaleData.get(loc);
- dateTimePatterns = new String[9];
- dateTimePatterns[DateFormat.SHORT + 4] = localeData.getDateFormat(DateFormat.SHORT);
- dateTimePatterns[DateFormat.MEDIUM + 4] = localeData.getDateFormat(DateFormat.MEDIUM);
- dateTimePatterns[DateFormat.LONG + 4] = localeData.getDateFormat(DateFormat.LONG);
- dateTimePatterns[DateFormat.FULL + 4] = localeData.getDateFormat(DateFormat.FULL);
- dateTimePatterns[DateFormat.SHORT] = localeData.getTimeFormat(DateFormat.SHORT);
- dateTimePatterns[DateFormat.MEDIUM] = localeData.getTimeFormat(DateFormat.MEDIUM);
- dateTimePatterns[DateFormat.LONG] = localeData.getTimeFormat(DateFormat.LONG);
- dateTimePatterns[DateFormat.FULL] = localeData.getTimeFormat(DateFormat.FULL);
- dateTimePatterns[8] = "{0} {1}";
- /* update cache */
- cachedLocaleData.putIfAbsent(loc, dateTimePatterns);
- }
formatData = DateFormatSymbols.getInstanceRef(loc);
+ LocaleData localeData = LocaleData.get(loc);
if ((timeStyle >= 0) && (dateStyle >= 0)) {
- Object[] dateTimeArgs = {dateTimePatterns[dateStyle + 4], dateTimePatterns[timeStyle]};
- pattern = MessageFormat.format(dateTimePatterns[8], dateTimeArgs);
+ Object[] dateTimeArgs = {
+ localeData.getDateFormat(dateStyle),
+ localeData.getTimeFormat(timeStyle),
+ };
+ pattern = MessageFormat.format("{0} {1}", dateTimeArgs);
}
else if (timeStyle >= 0) {
- pattern = dateTimePatterns[timeStyle];
+ pattern = localeData.getTimeFormat(timeStyle);
}
else if (dateStyle >= 0) {
- pattern = dateTimePatterns[dateStyle + 4];
+ pattern = localeData.getDateFormat(dateStyle);
}
else {
throw new IllegalArgumentException("No date or time style specified");
@@ -1193,7 +1176,13 @@
TimeZone tz = calendar.getTimeZone();
boolean daylight = (calendar.get(Calendar.DST_OFFSET) != 0);
int tzstyle = count < 4 ? TimeZone.SHORT : TimeZone.LONG;
- String zoneString = tz.getDisplayName(daylight, tzstyle, formatData.locale);
+ String zoneString;
+ if (formatData.isZoneStringsSet) {
+ zoneString = TimeZoneNames.getDisplayName(
+ formatData.getZoneStringsWrapper(), tz.getID(), daylight, tzstyle);
+ } else {
+ zoneString = tz.getDisplayName(daylight, tzstyle, formatData.locale);
+ }
if (zoneString != null) {
buffer.append(zoneString);
} else {
@@ -1966,7 +1955,7 @@
case PATTERN_STANDALONE_DAY_OF_WEEK: // 'c'
{
final int idx = parseWeekday(text, start, field, useDateFormatSymbols,
- false /* standalone */, calb);
+ true /* standalone */, calb);
if (idx > 0) {
return idx;
}
diff --git a/ojluni/src/main/java/java/util/Vector.java b/ojluni/src/main/java/java/util/Vector.java
index b2bc200..0f2dedd 100755
--- a/ojluni/src/main/java/java/util/Vector.java
+++ b/ojluni/src/main/java/java/util/Vector.java
@@ -1238,6 +1238,7 @@
checkForComodification();
Vector.this.add(i, e);
expectedModCount = modCount;
+ limit++;
}
cursor = i + 1;
lastRet = -1;
diff --git a/ojluni/src/main/java/java/util/zip/ZipFile.java b/ojluni/src/main/java/java/util/zip/ZipFile.java
index e6624af..6a5a366 100755
--- a/ojluni/src/main/java/java/util/zip/ZipFile.java
+++ b/ojluni/src/main/java/java/util/zip/ZipFile.java
@@ -31,6 +31,7 @@
import java.io.IOException;
import java.io.EOFException;
import java.io.File;
+import java.io.FileNotFoundException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayDeque;
@@ -203,9 +204,15 @@
Integer.toHexString(mode));
}
- // Android-changed: Error out early if the file is too short.
- if (file.length() < ZipConstants.ENDHDR) {
- throw new ZipException("File too short to be a zip file: " + file.length());
+
+ // Android-changed: Error out early if the file is too short or non-existent.
+ long length = file.length();
+ if (length < ZipConstants.ENDHDR) {
+ if (length == 0 && !file.exists()) {
+ throw new FileNotFoundException("File doesn't exist: " + file);
+ } else {
+ throw new ZipException("File too short to be a zip file: " + file.length());
+ }
}
String name = file.getPath();
@@ -771,6 +778,14 @@
return locsig;
}
+ /** @hide */
+ // @VisibleForTesting
+ public int getFileDescriptor() {
+ return getFileDescriptor(jzfile);
+ }
+
+ private static native int getFileDescriptor(long jzfile);
+
private static native long open(String name, int mode, long lastModified,
boolean usemmap) throws IOException;
private static native int getTotal(long jzfile);
diff --git a/ojluni/src/main/java/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java b/ojluni/src/main/java/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java
deleted file mode 100755
index 05a6174..0000000
--- a/ojluni/src/main/java/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.net.www.protocol.https;
-
-import java.net.URL;
-import java.net.Proxy;
-import java.net.SecureCacheResponse;
-import java.security.Principal;
-import java.io.IOException;
-import java.util.List;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import sun.net.www.http.*;
-import sun.net.www.protocol.http.HttpURLConnection;
-
-/**
- * HTTPS URL connection support.
- * We need this delegate because HttpsURLConnection is a subclass of
- * java.net.HttpURLConnection. We will avoid copying over the code from
- * sun.net.www.protocol.http.HttpURLConnection by having this class
- *
- */
-public abstract class AbstractDelegateHttpsURLConnection extends
- HttpURLConnection {
-
- protected AbstractDelegateHttpsURLConnection(URL url,
- sun.net.www.protocol.http.Handler handler) throws IOException {
- this(url, null, handler);
- }
-
- protected AbstractDelegateHttpsURLConnection(URL url, Proxy p,
- sun.net.www.protocol.http.Handler handler) throws IOException {
- super(url, p, handler);
- }
-
- protected abstract javax.net.ssl.SSLSocketFactory getSSLSocketFactory();
-
- protected abstract javax.net.ssl.HostnameVerifier getHostnameVerifier();
-
- /**
- * No user application is able to call these routines, as no one
- * should ever get access to an instance of
- * DelegateHttpsURLConnection (sun.* or com.*)
- */
-
- /**
- * Create a new HttpClient object, bypassing the cache of
- * HTTP client objects/connections.
- *
- * Note: this method is changed from protected to public because
- * the com.sun.ssl.internal.www.protocol.https handler reuses this
- * class for its actual implemantation
- *
- * @param url the URL being accessed
- */
- public void setNewClient (URL url)
- throws IOException {
- setNewClient (url, false);
- }
-
- /**
- * Obtain a HttpClient object. Use the cached copy if specified.
- *
- * Note: this method is changed from protected to public because
- * the com.sun.ssl.internal.www.protocol.https handler reuses this
- * class for its actual implemantation
- *
- * @param url the URL being accessed
- * @param useCache whether the cached connection should be used
- * if present
- */
- public void setNewClient (URL url, boolean useCache)
- throws IOException {
- http = HttpsClient.New (getSSLSocketFactory(),
- url,
- getHostnameVerifier(),
- useCache, this);
- ((HttpsClient)http).afterConnect();
- }
-
- /**
- * Create a new HttpClient object, set up so that it uses
- * per-instance proxying to the given HTTP proxy. This
- * bypasses the cache of HTTP client objects/connections.
- *
- * Note: this method is changed from protected to public because
- * the com.sun.ssl.internal.www.protocol.https handler reuses this
- * class for its actual implemantation
- *
- * @param url the URL being accessed
- * @param proxyHost the proxy host to use
- * @param proxyPort the proxy port to use
- */
- public void setProxiedClient (URL url, String proxyHost, int proxyPort)
- throws IOException {
- setProxiedClient(url, proxyHost, proxyPort, false);
- }
-
- /**
- * Obtain a HttpClient object, set up so that it uses per-instance
- * proxying to the given HTTP proxy. Use the cached copy of HTTP
- * client objects/connections if specified.
- *
- * Note: this method is changed from protected to public because
- * the com.sun.ssl.internal.www.protocol.https handler reuses this
- * class for its actual implemantation
- *
- * @param url the URL being accessed
- * @param proxyHost the proxy host to use
- * @param proxyPort the proxy port to use
- * @param useCache whether the cached connection should be used
- * if present
- */
- public void setProxiedClient (URL url, String proxyHost, int proxyPort,
- boolean useCache) throws IOException {
- proxiedConnect(url, proxyHost, proxyPort, useCache);
- if (!http.isCachedConnection()) {
- doTunneling();
- }
- ((HttpsClient)http).afterConnect();
- }
-
- protected void proxiedConnect(URL url, String proxyHost, int proxyPort,
- boolean useCache) throws IOException {
- if (connected)
- return;
- http = HttpsClient.New (getSSLSocketFactory(),
- url,
- getHostnameVerifier(),
- proxyHost, proxyPort, useCache, this);
- connected = true;
- }
-
- /**
- * Used by subclass to access "connected" variable.
- */
- public boolean isConnected() {
- return connected;
- }
-
- /**
- * Used by subclass to access "connected" variable.
- */
- public void setConnected(boolean conn) {
- connected = conn;
- }
-
- /**
- * Implements the HTTP protocol handler's "connect" method,
- * establishing an SSL connection to the server as necessary.
- */
- public void connect() throws IOException {
- if (connected)
- return;
- plainConnect();
- if (cachedResponse != null) {
- // using cached response
- return;
- }
- if (!http.isCachedConnection() && http.needsTunneling()) {
- doTunneling();
- }
- ((HttpsClient)http).afterConnect();
- }
-
- // will try to use cached HttpsClient
- protected HttpClient getNewHttpClient(URL url, Proxy p, int connectTimeout)
- throws IOException {
- return HttpsClient.New(getSSLSocketFactory(), url,
- getHostnameVerifier(), p, true, connectTimeout,
- this);
- }
-
- // will open new connection
- protected HttpClient getNewHttpClient(URL url, Proxy p, int connectTimeout,
- boolean useCache)
- throws IOException {
- return HttpsClient.New(getSSLSocketFactory(), url,
- getHostnameVerifier(), p,
- useCache, connectTimeout, this);
- }
-
- /**
- * Returns the cipher suite in use on this connection.
- */
- public String getCipherSuite () {
- if (cachedResponse != null) {
- return ((SecureCacheResponse)cachedResponse).getCipherSuite();
- }
- if (http == null) {
- throw new IllegalStateException("connection not yet open");
- } else {
- return ((HttpsClient)http).getCipherSuite ();
- }
- }
-
- /**
- * Returns the certificate chain the client sent to the
- * server, or null if the client did not authenticate.
- */
- public java.security.cert.Certificate[] getLocalCertificates() {
- if (cachedResponse != null) {
- List l = ((SecureCacheResponse)cachedResponse).getLocalCertificateChain();
- if (l == null) {
- return null;
- } else {
- return (java.security.cert.Certificate[])l.toArray();
- }
- }
- if (http == null) {
- throw new IllegalStateException("connection not yet open");
- } else {
- return (((HttpsClient)http).getLocalCertificates ());
- }
- }
-
- /**
- * Returns the server's certificate chain, or throws
- * SSLPeerUnverified Exception if
- * the server did not authenticate.
- */
- public java.security.cert.Certificate[] getServerCertificates()
- throws SSLPeerUnverifiedException {
- if (cachedResponse != null) {
- List l = ((SecureCacheResponse)cachedResponse).getServerCertificateChain();
- if (l == null) {
- return null;
- } else {
- return (java.security.cert.Certificate[])l.toArray();
- }
- }
-
- if (http == null) {
- throw new IllegalStateException("connection not yet open");
- } else {
- return (((HttpsClient)http).getServerCertificates ());
- }
- }
-
- /**
- * Returns the server's X.509 certificate chain, or null if
- * the server did not authenticate.
- */
- public javax.security.cert.X509Certificate[] getServerCertificateChain()
- throws SSLPeerUnverifiedException {
- if (cachedResponse != null) {
- throw new UnsupportedOperationException("this method is not supported when using cache");
- }
- if (http == null) {
- throw new IllegalStateException("connection not yet open");
- } else {
- return ((HttpsClient)http).getServerCertificateChain ();
- }
- }
-
- /**
- * Returns the server's principal, or throws SSLPeerUnverifiedException
- * if the server did not authenticate.
- */
- Principal getPeerPrincipal()
- throws SSLPeerUnverifiedException
- {
- if (cachedResponse != null) {
- return ((SecureCacheResponse)cachedResponse).getPeerPrincipal();
- }
-
- if (http == null) {
- throw new IllegalStateException("connection not yet open");
- } else {
- return (((HttpsClient)http).getPeerPrincipal());
- }
- }
-
- /**
- * Returns the principal the client sent to the
- * server, or null if the client did not authenticate.
- */
- Principal getLocalPrincipal()
- {
- if (cachedResponse != null) {
- return ((SecureCacheResponse)cachedResponse).getLocalPrincipal();
- }
-
- if (http == null) {
- throw new IllegalStateException("connection not yet open");
- } else {
- return (((HttpsClient)http).getLocalPrincipal());
- }
- }
-
-}
diff --git a/ojluni/src/main/java/sun/net/www/protocol/https/DelegateHttpsURLConnection.java b/ojluni/src/main/java/sun/net/www/protocol/https/DelegateHttpsURLConnection.java
deleted file mode 100755
index b6ff7b4..0000000
--- a/ojluni/src/main/java/sun/net/www/protocol/https/DelegateHttpsURLConnection.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.net.www.protocol.https;
-
-import java.net.URL;
-import java.net.Proxy;
-import java.io.IOException;
-
-/**
- * This class was introduced to provide an additional level of
- * abstraction between javax.net.ssl.HttpURLConnection and
- * com.sun.net.ssl.HttpURLConnection objects. <p>
- *
- * javax.net.ssl.HttpURLConnection is used in the new sun.net version
- * of protocol implementation (this one)
- * com.sun.net.ssl.HttpURLConnection is used in the com.sun version.
- *
- */
-public class DelegateHttpsURLConnection extends AbstractDelegateHttpsURLConnection {
-
- // we need a reference to the HttpsURLConnection to get
- // the properties set there
- // we also need it to be public so that it can be referenced
- // from sun.net.www.protocol.http.HttpURLConnection
- // this is for ResponseCache.put(URI, URLConnection)
- // second parameter needs to be cast to javax.net.ssl.HttpsURLConnection
- // instead of AbstractDelegateHttpsURLConnection
- public javax.net.ssl.HttpsURLConnection httpsURLConnection;
-
- DelegateHttpsURLConnection(URL url,
- sun.net.www.protocol.http.Handler handler,
- javax.net.ssl.HttpsURLConnection httpsURLConnection)
- throws IOException {
- this(url, null, handler, httpsURLConnection);
- }
-
- DelegateHttpsURLConnection(URL url, Proxy p,
- sun.net.www.protocol.http.Handler handler,
- javax.net.ssl.HttpsURLConnection httpsURLConnection)
- throws IOException {
- super(url, p, handler);
- this.httpsURLConnection = httpsURLConnection;
- }
-
- protected javax.net.ssl.SSLSocketFactory getSSLSocketFactory() {
- return httpsURLConnection.getSSLSocketFactory();
- }
-
- protected javax.net.ssl.HostnameVerifier getHostnameVerifier() {
- return httpsURLConnection.getHostnameVerifier();
- }
-
- /*
- * Called by layered delegator's finalize() method to handle closing
- * the underlying object.
- */
- protected void dispose() throws Throwable {
- super.finalize();
- }
-}
diff --git a/ojluni/src/main/java/sun/net/www/protocol/https/Handler.java b/ojluni/src/main/java/sun/net/www/protocol/https/Handler.java
deleted file mode 100755
index d2be7fd..0000000
--- a/ojluni/src/main/java/sun/net/www/protocol/https/Handler.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2001, 2003, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*-
- * HTTP stream opener
- */
-
-package sun.net.www.protocol.https;
-
-import java.io.IOException;
-import java.net.URL;
-import java.net.Proxy;
-
-/** open an http input stream given a URL */
-public class Handler extends sun.net.www.protocol.http.Handler {
- protected String proxy;
- protected int proxyPort;
-
- protected int getDefaultPort() {
- return 443;
- }
-
- public Handler () {
- proxy = null;
- proxyPort = -1;
- }
-
- public Handler (String proxy, int port) {
- this.proxy = proxy;
- this.proxyPort = port;
- }
-
- protected java.net.URLConnection openConnection(URL u)
- throws IOException {
- return openConnection(u, (Proxy)null);
- }
-
- protected java.net.URLConnection openConnection(URL u, Proxy p)
- throws IOException {
- return new HttpsURLConnectionImpl(u, p, this);
- }
-}
diff --git a/ojluni/src/main/java/sun/net/www/protocol/https/HttpsClient.java b/ojluni/src/main/java/sun/net/www/protocol/https/HttpsClient.java
deleted file mode 100755
index 91a5329..0000000
--- a/ojluni/src/main/java/sun/net/www/protocol/https/HttpsClient.java
+++ /dev/null
@@ -1,795 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.net.www.protocol.https;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.io.PrintStream;
-import java.io.BufferedOutputStream;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.SocketException;
-import java.net.URL;
-import java.net.UnknownHostException;
-import java.net.InetSocketAddress;
-import java.net.Proxy;
-import java.security.Principal;
-import java.security.cert.*;
-import java.util.StringTokenizer;
-import java.util.Vector;
-import java.security.AccessController;
-
-import javax.security.auth.x500.X500Principal;
-
-import javax.net.ssl.*;
-import sun.net.www.http.HttpClient;
-import sun.net.www.protocol.http.HttpURLConnection;
-import sun.security.action.*;
-
-import sun.security.util.HostnameChecker;
-import sun.security.ssl.SSLSocketImpl;
-
-import sun.util.logging.PlatformLogger;
-import static sun.net.www.protocol.http.HttpURLConnection.TunnelState.*;
-
-
-/**
- * This class provides HTTPS client URL support, building on the standard
- * "sun.net.www" HTTP protocol handler. HTTPS is the same protocol as HTTP,
- * but differs in the transport layer which it uses: <UL>
- *
- * <LI>There's a <em>Secure Sockets Layer</em> between TCP
- * and the HTTP protocol code.
- *
- * <LI>It uses a different default TCP port.
- *
- * <LI>It doesn't use application level proxies, which can see and
- * manipulate HTTP user level data, compromising privacy. It uses
- * low level tunneling instead, which hides HTTP protocol and data
- * from all third parties. (Traffic analysis is still possible).
- *
- * <LI>It does basic server authentication, to protect
- * against "URL spoofing" attacks. This involves deciding
- * whether the X.509 certificate chain identifying the server
- * is trusted, and verifying that the name of the server is
- * found in the certificate. (The application may enable an
- * anonymous SSL cipher suite, and such checks are not done
- * for anonymous ciphers.)
- *
- * <LI>It exposes key SSL session attributes, specifically the
- * cipher suite in use and the server's X509 certificates, to
- * application software which knows about this protocol handler.
- *
- * </UL>
- *
- * <P> System properties used include: <UL>
- *
- * <LI><em>https.proxyHost</em> ... the host supporting SSL
- * tunneling using the conventional CONNECT syntax
- *
- * <LI><em>https.proxyPort</em> ... port to use on proxyHost
- *
- * <LI><em>https.cipherSuites</em> ... comma separated list of
- * SSL cipher suite names to enable.
- *
- * <LI><em>http.nonProxyHosts</em> ...
- *
- * </UL>
- *
- * @author David Brownell
- * @author Bill Foote
- */
-
-// final for export control reasons (access to APIs); remove with care
-final class HttpsClient extends HttpClient
- implements HandshakeCompletedListener
-{
- // STATIC STATE and ACCESSORS THERETO
-
- // HTTPS uses a different default port number than HTTP.
- private static final int httpsPortNumber = 443;
-
- // default HostnameVerifier class canonical name
- private static final String defaultHVCanonicalName =
- "javax.net.ssl.DefaultHostnameVerifier";
-
- /** Returns the default HTTPS port (443) */
- @Override
- protected int getDefaultPort() { return httpsPortNumber; }
-
- private HostnameVerifier hv;
- private SSLSocketFactory sslSocketFactory;
-
- // HttpClient.proxyDisabled will always be false, because we don't
- // use an application-level HTTP proxy. We might tunnel through
- // our http proxy, though.
-
-
- // INSTANCE DATA
-
- // last negotiated SSL session
- private SSLSession session;
-
- private String [] getCipherSuites() {
- //
- // If ciphers are assigned, sort them into an array.
- //
- String ciphers [];
- String cipherString = AccessController.doPrivileged(
- new GetPropertyAction("https.cipherSuites"));
-
- if (cipherString == null || "".equals(cipherString)) {
- ciphers = null;
- } else {
- StringTokenizer tokenizer;
- Vector<String> v = new Vector<String>();
-
- tokenizer = new StringTokenizer(cipherString, ",");
- while (tokenizer.hasMoreTokens())
- v.addElement(tokenizer.nextToken());
- ciphers = new String [v.size()];
- for (int i = 0; i < ciphers.length; i++)
- ciphers [i] = v.elementAt(i);
- }
- return ciphers;
- }
-
- private String [] getProtocols() {
- //
- // If protocols are assigned, sort them into an array.
- //
- String protocols [];
- String protocolString = AccessController.doPrivileged(
- new GetPropertyAction("https.protocols"));
-
- if (protocolString == null || "".equals(protocolString)) {
- protocols = null;
- } else {
- StringTokenizer tokenizer;
- Vector<String> v = new Vector<String>();
-
- tokenizer = new StringTokenizer(protocolString, ",");
- while (tokenizer.hasMoreTokens())
- v.addElement(tokenizer.nextToken());
- protocols = new String [v.size()];
- for (int i = 0; i < protocols.length; i++) {
- protocols [i] = v.elementAt(i);
- }
- }
- return protocols;
- }
-
- private String getUserAgent() {
- String userAgent = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("https.agent"));
- if (userAgent == null || userAgent.length() == 0) {
- userAgent = "JSSE";
- }
- return userAgent;
- }
-
- // should remove once HttpClient.newHttpProxy is putback
- private static Proxy newHttpProxy(String proxyHost, int proxyPort) {
- InetSocketAddress saddr = null;
- final String phost = proxyHost;
- final int pport = proxyPort < 0 ? httpsPortNumber : proxyPort;
- try {
- saddr = java.security.AccessController.doPrivileged(new
- java.security.PrivilegedExceptionAction<InetSocketAddress>() {
- public InetSocketAddress run() {
- return new InetSocketAddress(phost, pport);
- }});
- } catch (java.security.PrivilegedActionException pae) {
- }
- return new Proxy(Proxy.Type.HTTP, saddr);
- }
-
- // CONSTRUCTOR, FACTORY
-
-
- /**
- * Create an HTTPS client URL. Traffic will be tunneled through any
- * intermediate nodes rather than proxied, so that confidentiality
- * of data exchanged can be preserved. However, note that all the
- * anonymous SSL flavors are subject to "person-in-the-middle"
- * attacks against confidentiality. If you enable use of those
- * flavors, you may be giving up the protection you get through
- * SSL tunneling.
- *
- * Use New to get new HttpsClient. This constructor is meant to be
- * used only by New method. New properly checks for URL spoofing.
- *
- * @param URL https URL with which a connection must be established
- */
- private HttpsClient(SSLSocketFactory sf, URL url)
- throws IOException
- {
- // HttpClient-level proxying is always disabled,
- // because we override doConnect to do tunneling instead.
- this(sf, url, (String)null, -1);
- }
-
- /**
- * Create an HTTPS client URL. Traffic will be tunneled through
- * the specified proxy server.
- */
- HttpsClient(SSLSocketFactory sf, URL url, String proxyHost, int proxyPort)
- throws IOException {
- this(sf, url, proxyHost, proxyPort, -1);
- }
-
- /**
- * Create an HTTPS client URL. Traffic will be tunneled through
- * the specified proxy server, with a connect timeout
- */
- HttpsClient(SSLSocketFactory sf, URL url, String proxyHost, int proxyPort,
- int connectTimeout)
- throws IOException {
- this(sf, url,
- (proxyHost == null? null:
- HttpsClient.newHttpProxy(proxyHost, proxyPort)),
- connectTimeout);
- }
-
- /**
- * Same as previous constructor except using a Proxy
- */
- HttpsClient(SSLSocketFactory sf, URL url, Proxy proxy,
- int connectTimeout)
- throws IOException {
- this.proxy = proxy;
- setSSLSocketFactory(sf);
- this.proxyDisabled = true;
-
- this.host = url.getHost();
- this.url = url;
- port = url.getPort();
- if (port == -1) {
- port = getDefaultPort();
- }
- setConnectTimeout(connectTimeout);
- openServer();
- }
-
-
- // This code largely ripped off from HttpClient.New, and
- // it uses the same keepalive cache.
-
- static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
- HttpURLConnection httpuc)
- throws IOException {
- return HttpsClient.New(sf, url, hv, true, httpuc);
- }
-
- /** See HttpClient for the model for this method. */
- static HttpClient New(SSLSocketFactory sf, URL url,
- HostnameVerifier hv, boolean useCache,
- HttpURLConnection httpuc) throws IOException {
- return HttpsClient.New(sf, url, hv, (String)null, -1, useCache, httpuc);
- }
-
- /**
- * Get a HTTPS client to the URL. Traffic will be tunneled through
- * the specified proxy server.
- */
- static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
- String proxyHost, int proxyPort,
- HttpURLConnection httpuc) throws IOException {
- return HttpsClient.New(sf, url, hv, proxyHost, proxyPort, true, httpuc);
- }
-
- static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
- String proxyHost, int proxyPort, boolean useCache,
- HttpURLConnection httpuc)
- throws IOException {
- return HttpsClient.New(sf, url, hv, proxyHost, proxyPort, useCache, -1,
- httpuc);
- }
-
- static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
- String proxyHost, int proxyPort, boolean useCache,
- int connectTimeout, HttpURLConnection httpuc)
- throws IOException {
-
- return HttpsClient.New(sf, url, hv,
- (proxyHost == null? null :
- HttpsClient.newHttpProxy(proxyHost, proxyPort)),
- useCache, connectTimeout, httpuc);
- }
-
- static HttpClient New(SSLSocketFactory sf, URL url, HostnameVerifier hv,
- Proxy p, boolean useCache,
- int connectTimeout, HttpURLConnection httpuc)
- throws IOException
- {
- if (p == null) {
- p = Proxy.NO_PROXY;
- }
- HttpsClient ret = null;
- if (useCache) {
- /* see if one's already around */
- ret = (HttpsClient) kac.get(url, sf);
- if (ret != null && httpuc != null &&
- httpuc.streaming() &&
- httpuc.getRequestMethod() == "POST") {
- if (!ret.available())
- ret = null;
- }
-
- if (ret != null) {
- if ((ret.proxy != null && ret.proxy.equals(p)) ||
- (ret.proxy == null && p == null)) {
- synchronized (ret) {
- ret.cachedHttpClient = true;
- assert ret.inCache;
- ret.inCache = false;
- if (httpuc != null && ret.needsTunneling())
- httpuc.setTunnelState(TUNNELING);
- PlatformLogger logger = HttpURLConnection.getHttpLogger();
- if (logger.isLoggable(PlatformLogger.FINEST)) {
- logger.finest("KeepAlive stream retrieved from the cache, " + ret);
- }
- }
- } else {
- // We cannot return this connection to the cache as it's
- // KeepAliveTimeout will get reset. We simply close the connection.
- // This should be fine as it is very rare that a connection
- // to the same host will not use the same proxy.
- synchronized(ret) {
- ret.inCache = false;
- ret.closeServer();
- }
- ret = null;
- }
- }
- }
- if (ret == null) {
- ret = new HttpsClient(sf, url, p, connectTimeout);
- } else {
- SecurityManager security = System.getSecurityManager();
- if (security != null) {
- if (ret.proxy == Proxy.NO_PROXY || ret.proxy == null) {
- security.checkConnect(InetAddress.getByName(url.getHost()).getHostAddress(), url.getPort());
- } else {
- security.checkConnect(url.getHost(), url.getPort());
- }
- }
- ret.url = url;
- }
- ret.setHostnameVerifier(hv);
-
- return ret;
- }
-
- // METHODS
- void setHostnameVerifier(HostnameVerifier hv) {
- this.hv = hv;
- }
-
- void setSSLSocketFactory(SSLSocketFactory sf) {
- sslSocketFactory = sf;
- }
-
- SSLSocketFactory getSSLSocketFactory() {
- return sslSocketFactory;
- }
-
- /**
- * The following method, createSocket, is defined in NetworkClient
- * and overridden here so that the socket facroty is used to create
- * new sockets.
- */
- @Override
- protected Socket createSocket() throws IOException {
- try {
- return sslSocketFactory.createSocket();
- } catch (SocketException se) {
- //
- // bug 6771432
- // javax.net.SocketFactory throws a SocketException with an
- // UnsupportedOperationException as its cause to indicate that
- // unconnected sockets have not been implemented.
- //
- Throwable t = se.getCause();
- if (t != null && t instanceof UnsupportedOperationException) {
- return super.createSocket();
- } else {
- throw se;
- }
- }
- }
-
-
- @Override
- public boolean needsTunneling() {
- return (proxy != null && proxy.type() != Proxy.Type.DIRECT
- && proxy.type() != Proxy.Type.SOCKS);
- }
-
- @Override
- public void afterConnect() throws IOException, UnknownHostException {
- if (!isCachedConnection()) {
- SSLSocket s = null;
- SSLSocketFactory factory = sslSocketFactory;
- try {
- if (!(serverSocket instanceof SSLSocket)) {
- s = (SSLSocket)factory.createSocket(serverSocket,
- host, port, true);
- } else {
- s = (SSLSocket)serverSocket;
- if (s instanceof SSLSocketImpl) {
- ((SSLSocketImpl)s).setHost(host);
- }
- }
- } catch (IOException ex) {
- // If we fail to connect through the tunnel, try it
- // locally, as a last resort. If this doesn't work,
- // throw the original exception.
- try {
- s = (SSLSocket)factory.createSocket(host, port);
- } catch (IOException ignored) {
- throw ex;
- }
- }
-
- //
- // Force handshaking, so that we get any authentication.
- // Register a handshake callback so our session state tracks any
- // later session renegotiations.
- //
- String [] protocols = getProtocols();
- String [] ciphers = getCipherSuites();
- if (protocols != null) {
- s.setEnabledProtocols(protocols);
- }
- if (ciphers != null) {
- s.setEnabledCipherSuites(ciphers);
- }
- s.addHandshakeCompletedListener(this);
-
- // We have two hostname verification approaches. One is in
- // SSL/TLS socket layer, where the algorithm is configured with
- // SSLParameters.setEndpointIdentificationAlgorithm(), and the
- // hostname verification is done by X509ExtendedTrustManager when
- // the algorithm is "HTTPS". The other one is in HTTPS layer,
- // where the algorithm is customized by
- // HttpsURLConnection.setHostnameVerifier(), and the hostname
- // verification is done by HostnameVerifier when the default
- // rules for hostname verification fail.
- //
- // The relationship between two hostname verification approaches
- // likes the following:
- //
- // | EIA algorithm
- // +----------------------------------------------
- // | null | HTTPS | LDAP/other |
- // -------------------------------------------------------------
- // | |1 |2 |3 |
- // HNV | default | Set HTTPS EIA | use EIA | HTTPS |
- // |--------------------------------------------------------
- // | non - |4 |5 |6 |
- // | default | HTTPS/HNV | use EIA | HTTPS/HNV |
- // -------------------------------------------------------------
- //
- // Abbreviation:
- // EIA: the endpoint identification algorithm in SSL/TLS
- // socket layer
- // HNV: the hostname verification object in HTTPS layer
- // Notes:
- // case 1. default HNV and EIA is null
- // Set EIA as HTTPS, hostname check done in SSL/TLS
- // layer.
- // case 2. default HNV and EIA is HTTPS
- // Use existing EIA, hostname check done in SSL/TLS
- // layer.
- // case 3. default HNV and EIA is other than HTTPS
- // Use existing EIA, EIA check done in SSL/TLS
- // layer, then do HTTPS check in HTTPS layer.
- // case 4. non-default HNV and EIA is null
- // No EIA, no EIA check done in SSL/TLS layer, then do
- // HTTPS check in HTTPS layer using HNV as override.
- // case 5. non-default HNV and EIA is HTTPS
- // Use existing EIA, hostname check done in SSL/TLS
- // layer. No HNV override possible. We will review this
- // decision and may update the architecture for JDK 7.
- // case 6. non-default HNV and EIA is other than HTTPS
- // Use existing EIA, EIA check done in SSL/TLS layer,
- // then do HTTPS check in HTTPS layer as override.
- boolean needToCheckSpoofing = true;
- String identification =
- s.getSSLParameters().getEndpointIdentificationAlgorithm();
- if (identification != null && identification.length() != 0) {
- if (identification.equalsIgnoreCase("HTTPS")) {
- // Do not check server identity again out of SSLSocket,
- // the endpoint will be identified during TLS handshaking
- // in SSLSocket.
- needToCheckSpoofing = false;
- } // else, we don't understand the identification algorithm,
- // need to check URL spoofing here.
- } else {
- boolean isDefaultHostnameVerifier = false;
-
- // We prefer to let the SSLSocket do the spoof checks, but if
- // the application has specified a HostnameVerifier (HNV),
- // we will always use that.
- if (hv != null) {
- String canonicalName = hv.getClass().getCanonicalName();
- if (canonicalName != null &&
- canonicalName.equalsIgnoreCase(defaultHVCanonicalName)) {
- isDefaultHostnameVerifier = true;
- }
- } else {
- // Unlikely to happen! As the behavior is the same as the
- // default hostname verifier, so we prefer to let the
- // SSLSocket do the spoof checks.
- isDefaultHostnameVerifier = true;
- }
-
- if (isDefaultHostnameVerifier) {
- // If the HNV is the default from HttpsURLConnection, we
- // will do the spoof checks in SSLSocket.
- SSLParameters paramaters = s.getSSLParameters();
- paramaters.setEndpointIdentificationAlgorithm("HTTPS");
- s.setSSLParameters(paramaters);
-
- needToCheckSpoofing = false;
- }
- }
-
- s.startHandshake();
- session = s.getSession();
- // change the serverSocket and serverOutput
- serverSocket = s;
- try {
- serverOutput = new PrintStream(
- new BufferedOutputStream(serverSocket.getOutputStream()),
- false, encoding);
- } catch (UnsupportedEncodingException e) {
- throw new InternalError(encoding+" encoding not found");
- }
-
- // check URL spoofing if it has not been checked under handshaking
- if (needToCheckSpoofing) {
- checkURLSpoofing(hv);
- }
- } else {
- // if we are reusing a cached https session,
- // we don't need to do handshaking etc. But we do need to
- // set the ssl session
- session = ((SSLSocket)serverSocket).getSession();
- }
- }
-
- // Server identity checking is done according to RFC 2818: HTTP over TLS
- // Section 3.1 Server Identity
- private void checkURLSpoofing(HostnameVerifier hostnameVerifier)
- throws IOException {
- //
- // Get authenticated server name, if any
- //
- String host = url.getHost();
-
- // if IPv6 strip off the "[]"
- if (host != null && host.startsWith("[") && host.endsWith("]")) {
- host = host.substring(1, host.length()-1);
- }
-
- Certificate[] peerCerts = null;
- String cipher = session.getCipherSuite();
- try {
- HostnameChecker checker = HostnameChecker.getInstance(
- HostnameChecker.TYPE_TLS);
-
- // Use ciphersuite to determine whether Kerberos is present.
- if (cipher.startsWith("TLS_KRB5")) {
- if (!HostnameChecker.match(host, getPeerPrincipal())) {
- throw new SSLPeerUnverifiedException("Hostname checker" +
- " failed for Kerberos");
- }
- } else { // X.509
-
- // get the subject's certificate
- peerCerts = session.getPeerCertificates();
-
- X509Certificate peerCert;
- if (peerCerts[0] instanceof
- java.security.cert.X509Certificate) {
- peerCert = (java.security.cert.X509Certificate)peerCerts[0];
- } else {
- throw new SSLPeerUnverifiedException("");
- }
- checker.match(host, peerCert);
- }
-
- // if it doesn't throw an exception, we passed. Return.
- return;
-
- } catch (SSLPeerUnverifiedException e) {
-
- //
- // client explicitly changed default policy and enabled
- // anonymous ciphers; we can't check the standard policy
- //
- // ignore
- } catch (java.security.cert.CertificateException cpe) {
- // ignore
- }
-
- if ((cipher != null) && (cipher.indexOf("_anon_") != -1)) {
- return;
- } else if ((hostnameVerifier != null) &&
- (hostnameVerifier.verify(host, session))) {
- return;
- }
-
- serverSocket.close();
- session.invalidate();
-
- throw new IOException("HTTPS hostname wrong: should be <"
- + url.getHost() + ">");
- }
-
- @Override
- protected void putInKeepAliveCache() {
- if (inCache) {
- assert false : "Duplicate put to keep alive cache";
- return;
- }
- inCache = true;
- kac.put(url, sslSocketFactory, this);
- }
-
- /*
- * Close an idle connection to this URL (if it exists in the cache).
- */
- @Override
- public void closeIdleConnection() {
- HttpClient http = (HttpClient) kac.get(url, sslSocketFactory);
- if (http != null) {
- http.closeServer();
- }
- }
-
- /**
- * Returns the cipher suite in use on this connection.
- */
- String getCipherSuite() {
- return session.getCipherSuite();
- }
-
- /**
- * Returns the certificate chain the client sent to the
- * server, or null if the client did not authenticate.
- */
- public java.security.cert.Certificate [] getLocalCertificates() {
- return session.getLocalCertificates();
- }
-
- /**
- * Returns the certificate chain with which the server
- * authenticated itself, or throw a SSLPeerUnverifiedException
- * if the server did not authenticate.
- */
- java.security.cert.Certificate [] getServerCertificates()
- throws SSLPeerUnverifiedException
- {
- return session.getPeerCertificates();
- }
-
- /**
- * Returns the X.509 certificate chain with which the server
- * authenticated itself, or null if the server did not authenticate.
- */
- javax.security.cert.X509Certificate [] getServerCertificateChain()
- throws SSLPeerUnverifiedException
- {
- return session.getPeerCertificateChain();
- }
-
- /**
- * Returns the principal with which the server authenticated
- * itself, or throw a SSLPeerUnverifiedException if the
- * server did not authenticate.
- */
- Principal getPeerPrincipal()
- throws SSLPeerUnverifiedException
- {
- Principal principal;
- try {
- principal = session.getPeerPrincipal();
- } catch (AbstractMethodError e) {
- // if the provider does not support it, fallback to peer certs.
- // return the X500Principal of the end-entity cert.
- java.security.cert.Certificate[] certs =
- session.getPeerCertificates();
- principal = (X500Principal)
- ((X509Certificate)certs[0]).getSubjectX500Principal();
- }
- return principal;
- }
-
- /**
- * Returns the principal the client sent to the
- * server, or null if the client did not authenticate.
- */
- Principal getLocalPrincipal()
- {
- Principal principal;
- try {
- principal = session.getLocalPrincipal();
- } catch (AbstractMethodError e) {
- principal = null;
- // if the provider does not support it, fallback to local certs.
- // return the X500Principal of the end-entity cert.
- java.security.cert.Certificate[] certs =
- session.getLocalCertificates();
- if (certs != null) {
- principal = (X500Principal)
- ((X509Certificate)certs[0]).getSubjectX500Principal();
- }
- }
- return principal;
- }
-
- /**
- * This method implements the SSL HandshakeCompleted callback,
- * remembering the resulting session so that it may be queried
- * for the current cipher suite and peer certificates. Servers
- * sometimes re-initiate handshaking, so the session in use on
- * a given connection may change. When sessions change, so may
- * peer identities and cipher suites.
- */
- public void handshakeCompleted(HandshakeCompletedEvent event)
- {
- session = event.getSession();
- }
-
- /**
- * @return the proxy host being used for this client, or null
- * if we're not going through a proxy
- */
- @Override
- public String getProxyHostUsed() {
- if (!needsTunneling()) {
- return null;
- } else {
- return super.getProxyHostUsed();
- }
- }
-
- /**
- * @return the proxy port being used for this client. Meaningless
- * if getProxyHostUsed() gives null.
- */
- @Override
- public int getProxyPortUsed() {
- return (proxy == null || proxy.type() == Proxy.Type.DIRECT ||
- proxy.type() == Proxy.Type.SOCKS)? -1:
- ((InetSocketAddress)proxy.address()).getPort();
- }
-}
diff --git a/ojluni/src/main/java/sun/net/www/protocol/https/HttpsURLConnectionImpl.java b/ojluni/src/main/java/sun/net/www/protocol/https/HttpsURLConnectionImpl.java
deleted file mode 100755
index 832854c..0000000
--- a/ojluni/src/main/java/sun/net/www/protocol/https/HttpsURLConnectionImpl.java
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/*
- * NOTE: This class lives in the package sun.net.www.protocol.https.
- * There is a copy in com.sun.net.ssl.internal.www.protocol.https for JSSE
- * 1.0.2 compatibility. It is 100% identical except the package and extends
- * lines. Any changes should be made to be class in sun.net.* and then copied
- * to com.sun.net.*.
- */
-
-// For both copies of the file, uncomment one line and comment the other
-package sun.net.www.protocol.https;
-// package com.sun.net.ssl.internal.www.protocol.https;
-
-import java.net.URL;
-import java.net.Proxy;
-import java.net.ProtocolException;
-import java.io.*;
-import javax.net.ssl.*;
-import java.security.Permission;
-import java.security.Principal;
-import java.util.Map;
-import java.util.List;
-import sun.net.www.http.HttpClient;
-
-/**
- * A class to represent an HTTP connection to a remote object.
- *
- * Ideally, this class should subclass and inherit the http handler
- * implementation, but it can't do so because that class have the
- * wrong Java Type. Thus it uses the delegate (aka, the
- * Adapter/Wrapper design pattern) to reuse code from the http
- * handler.
- *
- * Since it would use a delegate to access
- * sun.net.www.protocol.http.HttpURLConnection functionalities, it
- * needs to implement all public methods in it's super class and all
- * the way to Object.
- *
- */
-
-// For both copies of the file, uncomment one line and comment the
-// other. The differences between the two copies are introduced for
-// plugin, and it is marked as such.
-public class HttpsURLConnectionImpl
- extends javax.net.ssl.HttpsURLConnection {
-// public class HttpsURLConnectionOldImpl
-// extends com.sun.net.ssl.HttpsURLConnection {
-
- // NOTE: made protected for plugin so that subclass can set it.
- protected DelegateHttpsURLConnection delegate;
-
-// For both copies of the file, uncomment one line and comment the other
- HttpsURLConnectionImpl(URL u, Handler handler) throws IOException {
-// HttpsURLConnectionOldImpl(URL u, Handler handler) throws IOException {
- this(u, null, handler);
- }
-
-// For both copies of the file, uncomment one line and comment the other
- HttpsURLConnectionImpl(URL u, Proxy p, Handler handler) throws IOException {
-// HttpsURLConnectionOldImpl(URL u, Proxy p, Handler handler) throws IOException {
- super(u);
- delegate = new DelegateHttpsURLConnection(url, p, handler, this);
- }
-
- // NOTE: introduced for plugin
- // subclass needs to overwrite this to set delegate to
- // the appropriate delegatee
- protected HttpsURLConnectionImpl(URL u) throws IOException {
- super(u);
- }
-
- /**
- * Create a new HttpClient object, bypassing the cache of
- * HTTP client objects/connections.
- *
- * @param url the URL being accessed
- */
- protected void setNewClient(URL url) throws IOException {
- delegate.setNewClient(url, false);
- }
-
- /**
- * Obtain a HttpClient object. Use the cached copy if specified.
- *
- * @param url the URL being accessed
- * @param useCache whether the cached connection should be used
- * if present
- */
- protected void setNewClient(URL url, boolean useCache)
- throws IOException {
- delegate.setNewClient(url, useCache);
- }
-
- /**
- * Create a new HttpClient object, set up so that it uses
- * per-instance proxying to the given HTTP proxy. This
- * bypasses the cache of HTTP client objects/connections.
- *
- * @param url the URL being accessed
- * @param proxyHost the proxy host to use
- * @param proxyPort the proxy port to use
- */
- protected void setProxiedClient(URL url, String proxyHost, int proxyPort)
- throws IOException {
- delegate.setProxiedClient(url, proxyHost, proxyPort);
- }
-
- /**
- * Obtain a HttpClient object, set up so that it uses per-instance
- * proxying to the given HTTP proxy. Use the cached copy of HTTP
- * client objects/connections if specified.
- *
- * @param url the URL being accessed
- * @param proxyHost the proxy host to use
- * @param proxyPort the proxy port to use
- * @param useCache whether the cached connection should be used
- * if present
- */
- protected void setProxiedClient(URL url, String proxyHost, int proxyPort,
- boolean useCache) throws IOException {
- delegate.setProxiedClient(url, proxyHost, proxyPort, useCache);
- }
-
- /**
- * Implements the HTTP protocol handler's "connect" method,
- * establishing an SSL connection to the server as necessary.
- */
- public void connect() throws IOException {
- delegate.connect();
- }
-
- /**
- * Used by subclass to access "connected" variable. Since we are
- * delegating the actual implementation to "delegate", we need to
- * delegate the access of "connected" as well.
- */
- protected boolean isConnected() {
- return delegate.isConnected();
- }
-
- /**
- * Used by subclass to access "connected" variable. Since we are
- * delegating the actual implementation to "delegate", we need to
- * delegate the access of "connected" as well.
- */
- protected void setConnected(boolean conn) {
- delegate.setConnected(conn);
- }
-
- /**
- * Returns the cipher suite in use on this connection.
- */
- public String getCipherSuite() {
- return delegate.getCipherSuite();
- }
-
- /**
- * Returns the certificate chain the client sent to the
- * server, or null if the client did not authenticate.
- */
- public java.security.cert.Certificate []
- getLocalCertificates() {
- return delegate.getLocalCertificates();
- }
-
- /**
- * Returns the server's certificate chain, or throws
- * SSLPeerUnverified Exception if
- * the server did not authenticate.
- */
- public java.security.cert.Certificate []
- getServerCertificates() throws SSLPeerUnverifiedException {
- return delegate.getServerCertificates();
- }
-
- /**
- * Returns the server's X.509 certificate chain, or null if
- * the server did not authenticate.
- *
- * NOTE: This method is not necessary for the version of this class
- * implementing javax.net.ssl.HttpsURLConnection, but provided for
- * compatibility with the com.sun.net.ssl.HttpsURLConnection version.
- */
- public javax.security.cert.X509Certificate[] getServerCertificateChain() {
- try {
- return delegate.getServerCertificateChain();
- } catch (SSLPeerUnverifiedException e) {
- // this method does not throw an exception as declared in
- // com.sun.net.ssl.HttpsURLConnection.
- // Return null for compatibility.
- return null;
- }
- }
-
- /**
- * Returns the principal with which the server authenticated itself,
- * or throw a SSLPeerUnverifiedException if the server did not authenticate.
- */
- public Principal getPeerPrincipal()
- throws SSLPeerUnverifiedException
- {
- return delegate.getPeerPrincipal();
- }
-
- /**
- * Returns the principal the client sent to the
- * server, or null if the client did not authenticate.
- */
- public Principal getLocalPrincipal()
- {
- return delegate.getLocalPrincipal();
- }
-
- /*
- * Allowable input/output sequences:
- * [interpreted as POST/PUT]
- * - get output, [write output,] get input, [read input]
- * - get output, [write output]
- * [interpreted as GET]
- * - get input, [read input]
- * Disallowed:
- * - get input, [read input,] get output, [write output]
- */
-
- public synchronized OutputStream getOutputStream() throws IOException {
- return delegate.getOutputStream();
- }
-
- public synchronized InputStream getInputStream() throws IOException {
- return delegate.getInputStream();
- }
-
- public InputStream getErrorStream() {
- return delegate.getErrorStream();
- }
-
- /**
- * Disconnect from the server.
- */
- public void disconnect() {
- delegate.disconnect();
- }
-
- public boolean usingProxy() {
- return delegate.usingProxy();
- }
-
- /**
- * Returns an unmodifiable Map of the header fields.
- * The Map keys are Strings that represent the
- * response-header field names. Each Map value is an
- * unmodifiable List of Strings that represents
- * the corresponding field values.
- *
- * @return a Map of header fields
- * @since 1.4
- */
- public Map<String,List<String>> getHeaderFields() {
- return delegate.getHeaderFields();
- }
-
- /**
- * Gets a header field by name. Returns null if not known.
- * @param name the name of the header field
- */
- public String getHeaderField(String name) {
- return delegate.getHeaderField(name);
- }
-
- /**
- * Gets a header field by index. Returns null if not known.
- * @param n the index of the header field
- */
- public String getHeaderField(int n) {
- return delegate.getHeaderField(n);
- }
-
- /**
- * Gets a header field by index. Returns null if not known.
- * @param n the index of the header field
- */
- public String getHeaderFieldKey(int n) {
- return delegate.getHeaderFieldKey(n);
- }
-
- /**
- * Sets request property. If a property with the key already
- * exists, overwrite its value with the new value.
- * @param value the value to be set
- */
- public void setRequestProperty(String key, String value) {
- delegate.setRequestProperty(key, value);
- }
-
- /**
- * Adds a general request property specified by a
- * key-value pair. This method will not overwrite
- * existing values associated with the same key.
- *
- * @param key the keyword by which the request is known
- * (e.g., "<code>accept</code>").
- * @param value the value associated with it.
- * @see #getRequestProperties(java.lang.String)
- * @since 1.4
- */
- public void addRequestProperty(String key, String value) {
- delegate.addRequestProperty(key, value);
- }
-
- /**
- * Overwrite super class method
- */
- public int getResponseCode() throws IOException {
- return delegate.getResponseCode();
- }
-
- public String getRequestProperty(String key) {
- return delegate.getRequestProperty(key);
- }
-
- /**
- * Returns an unmodifiable Map of general request
- * properties for this connection. The Map keys
- * are Strings that represent the request-header
- * field names. Each Map value is a unmodifiable List
- * of Strings that represents the corresponding
- * field values.
- *
- * @return a Map of the general request properties for this connection.
- * @throws IllegalStateException if already connected
- * @since 1.4
- */
- public Map<String,List<String>> getRequestProperties() {
- return delegate.getRequestProperties();
- }
-
- /*
- * We support JDK 1.2.x so we can't count on these from JDK 1.3.
- * We override and supply our own version.
- */
- public void setInstanceFollowRedirects(boolean shouldFollow) {
- delegate.setInstanceFollowRedirects(shouldFollow);
- }
-
- public boolean getInstanceFollowRedirects() {
- return delegate.getInstanceFollowRedirects();
- }
-
- public void setRequestMethod(String method) throws ProtocolException {
- delegate.setRequestMethod(method);
- }
-
- public String getRequestMethod() {
- return delegate.getRequestMethod();
- }
-
- public String getResponseMessage() throws IOException {
- return delegate.getResponseMessage();
- }
-
- public long getHeaderFieldDate(String name, long Default) {
- return delegate.getHeaderFieldDate(name, Default);
- }
-
- public Permission getPermission() throws IOException {
- return delegate.getPermission();
- }
-
- public URL getURL() {
- return delegate.getURL();
- }
-
- public int getContentLength() {
- return delegate.getContentLength();
- }
-
- public long getContentLengthLong() {
- return delegate.getContentLengthLong();
- }
-
- public String getContentType() {
- return delegate.getContentType();
- }
-
- public String getContentEncoding() {
- return delegate.getContentEncoding();
- }
-
- public long getExpiration() {
- return delegate.getExpiration();
- }
-
- public long getDate() {
- return delegate.getDate();
- }
-
- public long getLastModified() {
- return delegate.getLastModified();
- }
-
- public int getHeaderFieldInt(String name, int Default) {
- return delegate.getHeaderFieldInt(name, Default);
- }
-
- public long getHeaderFieldLong(String name, long Default) {
- return delegate.getHeaderFieldLong(name, Default);
- }
-
- public Object getContent() throws IOException {
- return delegate.getContent();
- }
-
- public Object getContent(Class[] classes) throws IOException {
- return delegate.getContent(classes);
- }
-
- public String toString() {
- return delegate.toString();
- }
-
- public void setDoInput(boolean doinput) {
- delegate.setDoInput(doinput);
- }
-
- public boolean getDoInput() {
- return delegate.getDoInput();
- }
-
- public void setDoOutput(boolean dooutput) {
- delegate.setDoOutput(dooutput);
- }
-
- public boolean getDoOutput() {
- return delegate.getDoOutput();
- }
-
- public void setAllowUserInteraction(boolean allowuserinteraction) {
- delegate.setAllowUserInteraction(allowuserinteraction);
- }
-
- public boolean getAllowUserInteraction() {
- return delegate.getAllowUserInteraction();
- }
-
- public void setUseCaches(boolean usecaches) {
- delegate.setUseCaches(usecaches);
- }
-
- public boolean getUseCaches() {
- return delegate.getUseCaches();
- }
-
- public void setIfModifiedSince(long ifmodifiedsince) {
- delegate.setIfModifiedSince(ifmodifiedsince);
- }
-
- public long getIfModifiedSince() {
- return delegate.getIfModifiedSince();
- }
-
- public boolean getDefaultUseCaches() {
- return delegate.getDefaultUseCaches();
- }
-
- public void setDefaultUseCaches(boolean defaultusecaches) {
- delegate.setDefaultUseCaches(defaultusecaches);
- }
-
- /*
- * finalize (dispose) the delegated object. Otherwise
- * sun.net.www.protocol.http.HttpURLConnection's finalize()
- * would have to be made public.
- */
- protected void finalize() throws Throwable {
- delegate.dispose();
- }
-
- public boolean equals(Object obj) {
- return delegate.equals(obj);
- }
-
- public int hashCode() {
- return delegate.hashCode();
- }
-
- public void setConnectTimeout(int timeout) {
- delegate.setConnectTimeout(timeout);
- }
-
- public int getConnectTimeout() {
- return delegate.getConnectTimeout();
- }
-
- public void setReadTimeout(int timeout) {
- delegate.setReadTimeout(timeout);
- }
-
- public int getReadTimeout() {
- return delegate.getReadTimeout();
- }
-
- public void setFixedLengthStreamingMode (int contentLength) {
- delegate.setFixedLengthStreamingMode(contentLength);
- }
-
- public void setFixedLengthStreamingMode(long contentLength) {
- delegate.setFixedLengthStreamingMode(contentLength);
- }
-
- public void setChunkedStreamingMode (int chunklen) {
- delegate.setChunkedStreamingMode(chunklen);
- }
-}
diff --git a/ojluni/src/main/java/sun/security/pkcs/PKCS7.java b/ojluni/src/main/java/sun/security/pkcs/PKCS7.java
index 4929c01..5fb23ea 100755
--- a/ojluni/src/main/java/sun/security/pkcs/PKCS7.java
+++ b/ojluni/src/main/java/sun/security/pkcs/PKCS7.java
@@ -31,11 +31,17 @@
import java.util.*;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.CertificateParsingException;
import java.security.cert.X509CRL;
import java.security.cert.CRLException;
import java.security.cert.CertificateFactory;
import java.security.*;
+import javax.security.auth.x500.X500Principal;
+
import sun.security.util.*;
import sun.security.x509.AlgorithmId;
import sun.security.x509.CertificateIssuerName;
@@ -201,7 +207,7 @@
private void parseNetscapeCertChain(DerValue val)
throws ParsingException, IOException {
DerInputStream dis = new DerInputStream(val.toByteArray());
- DerValue[] contents = dis.getSequence(2);
+ DerValue[] contents = dis.getSequence(2, true);
certificates = new X509Certificate[contents.length];
CertificateFactory certfac = null;
@@ -214,13 +220,14 @@
for (int i=0; i < contents.length; i++) {
ByteArrayInputStream bais = null;
try {
+ byte[] original = contents[i].getOriginalEncodedForm();
if (certfac == null)
- certificates[i] = new X509CertImpl(contents[i]);
+ certificates[i] = new X509CertImpl(contents[i], original);
else {
- byte[] encoded = contents[i].toByteArray();
- bais = new ByteArrayInputStream(encoded);
- certificates[i] =
- (X509Certificate)certfac.generateCertificate(bais);
+ bais = new ByteArrayInputStream(original);
+ certificates[i] = new VerbatimX509Certificate(
+ (X509Certificate)certfac.generateCertificate(bais),
+ original);
bais.close();
bais = null;
}
@@ -279,7 +286,7 @@
* (certificates are OPTIONAL)
*/
if ((byte)(dis.peekByte()) == (byte)0xA0) {
- DerValue[] certVals = dis.getSet(2, true);
+ DerValue[] certVals = dis.getSet(2, true, true);
len = certVals.length;
certificates = new X509Certificate[len];
@@ -292,13 +299,14 @@
// We only parse the normal certificate. Other types of
// CertificateChoices ignored.
if (tag == DerValue.tag_Sequence) {
+ byte[] original = certVals[i].getOriginalEncodedForm();
if (certfac == null) {
- certificates[count] = new X509CertImpl(certVals[i]);
+ certificates[count] = new X509CertImpl(certVals[i], original);
} else {
- byte[] encoded = certVals[i].toByteArray();
- bais = new ByteArrayInputStream(encoded);
- certificates[count] =
- (X509Certificate)certfac.generateCertificate(bais);
+ bais = new ByteArrayInputStream(original);
+ certificates[count] = new VerbatimX509Certificate(
+ (X509Certificate)certfac.generateCertificate(bais),
+ original);
bais.close();
bais = null;
}
@@ -401,20 +409,21 @@
} catch (CertificateException ce) {
// do nothing
}
- DerValue[] certVals = dis.getSet(2);
+ DerValue[] certVals = dis.getSet(2, false, true);
len = certVals.length;
certificates = new X509Certificate[len];
for (int i = 0; i < len; i++) {
ByteArrayInputStream bais = null;
try {
+ byte[] original = certVals[i].getOriginalEncodedForm();
if (certfac == null)
- certificates[i] = new X509CertImpl(certVals[i]);
+ certificates[i] = new X509CertImpl(certVals[i], original);
else {
- byte[] encoded = certVals[i].toByteArray();
- bais = new ByteArrayInputStream(encoded);
- certificates[i] =
- (X509Certificate)certfac.generateCertificate(bais);
+ bais = new ByteArrayInputStream(original);
+ certificates[i] = new VerbatimX509Certificate(
+ (X509Certificate)certfac.generateCertificate(bais),
+ original);
bais.close();
bais = null;
}
@@ -762,4 +771,196 @@
public boolean isOldStyle() {
return this.oldStyle;
}
+
+ /**
+ * For legacy reasons we need to return exactly the original encoded certificate bytes, instead
+ * of letting the underlying implementation have a shot at re-encoding the data.
+ */
+ private static class VerbatimX509Certificate extends WrappedX509Certificate {
+ private byte[] encodedVerbatim;
+
+ public VerbatimX509Certificate(X509Certificate wrapped, byte[] encodedVerbatim) {
+ super(wrapped);
+ this.encodedVerbatim = encodedVerbatim;
+ }
+
+ @Override
+ public byte[] getEncoded() throws CertificateEncodingException {
+ return encodedVerbatim;
+ }
+ }
+
+ private static class WrappedX509Certificate extends X509Certificate {
+ private final X509Certificate wrapped;
+
+ public WrappedX509Certificate(X509Certificate wrapped) {
+ this.wrapped = wrapped;
+ }
+
+ @Override
+ public Set<String> getCriticalExtensionOIDs() {
+ return wrapped.getCriticalExtensionOIDs();
+ }
+
+ @Override
+ public byte[] getExtensionValue(String oid) {
+ return wrapped.getExtensionValue(oid);
+ }
+
+ @Override
+ public Set<String> getNonCriticalExtensionOIDs() {
+ return wrapped.getNonCriticalExtensionOIDs();
+ }
+
+ @Override
+ public boolean hasUnsupportedCriticalExtension() {
+ return wrapped.hasUnsupportedCriticalExtension();
+ }
+
+ @Override
+ public void checkValidity()
+ throws CertificateExpiredException, CertificateNotYetValidException {
+ wrapped.checkValidity();
+ }
+
+ @Override
+ public void checkValidity(Date date)
+ throws CertificateExpiredException, CertificateNotYetValidException {
+ wrapped.checkValidity(date);
+ }
+
+ @Override
+ public int getVersion() {
+ return wrapped.getVersion();
+ }
+
+ @Override
+ public BigInteger getSerialNumber() {
+ return wrapped.getSerialNumber();
+ }
+
+ @Override
+ public Principal getIssuerDN() {
+ return wrapped.getIssuerDN();
+ }
+
+ @Override
+ public Principal getSubjectDN() {
+ return wrapped.getSubjectDN();
+ }
+
+ @Override
+ public Date getNotBefore() {
+ return wrapped.getNotBefore();
+ }
+
+ @Override
+ public Date getNotAfter() {
+ return wrapped.getNotAfter();
+ }
+
+ @Override
+ public byte[] getTBSCertificate() throws CertificateEncodingException {
+ return wrapped.getTBSCertificate();
+ }
+
+ @Override
+ public byte[] getSignature() {
+ return wrapped.getSignature();
+ }
+
+ @Override
+ public String getSigAlgName() {
+ return wrapped.getSigAlgName();
+ }
+
+ @Override
+ public String getSigAlgOID() {
+ return wrapped.getSigAlgOID();
+ }
+
+ @Override
+ public byte[] getSigAlgParams() {
+ return wrapped.getSigAlgParams();
+ }
+
+ @Override
+ public boolean[] getIssuerUniqueID() {
+ return wrapped.getIssuerUniqueID();
+ }
+
+ @Override
+ public boolean[] getSubjectUniqueID() {
+ return wrapped.getSubjectUniqueID();
+ }
+
+ @Override
+ public boolean[] getKeyUsage() {
+ return wrapped.getKeyUsage();
+ }
+
+ @Override
+ public int getBasicConstraints() {
+ return wrapped.getBasicConstraints();
+ }
+
+ @Override
+ public byte[] getEncoded() throws CertificateEncodingException {
+ return wrapped.getEncoded();
+ }
+
+ @Override
+ public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException,
+ InvalidKeyException, NoSuchProviderException, SignatureException {
+ wrapped.verify(key);
+ }
+
+ @Override
+ public void verify(PublicKey key, String sigProvider)
+ throws CertificateException, NoSuchAlgorithmException, InvalidKeyException,
+ NoSuchProviderException, SignatureException {
+ wrapped.verify(key, sigProvider);
+ }
+
+ @Override
+ public String toString() {
+ return wrapped.toString();
+ }
+
+ @Override
+ public PublicKey getPublicKey() {
+ return wrapped.getPublicKey();
+ }
+
+ @Override
+ public List<String> getExtendedKeyUsage() throws CertificateParsingException {
+ return wrapped.getExtendedKeyUsage();
+ }
+
+ @Override
+ public Collection<List<?>> getIssuerAlternativeNames() throws CertificateParsingException {
+ return wrapped.getIssuerAlternativeNames();
+ }
+
+ @Override
+ public X500Principal getIssuerX500Principal() {
+ return wrapped.getIssuerX500Principal();
+ }
+
+ @Override
+ public Collection<List<?>> getSubjectAlternativeNames() throws CertificateParsingException {
+ return wrapped.getSubjectAlternativeNames();
+ }
+
+ @Override
+ public X500Principal getSubjectX500Principal() {
+ return wrapped.getSubjectX500Principal();
+ }
+
+ @Override
+ public void verify(PublicKey key, Provider sigProvider) throws CertificateException,
+ NoSuchAlgorithmException, InvalidKeyException, SignatureException {
+ wrapped.verify(key, sigProvider);
+ }
+ }
}
diff --git a/ojluni/src/main/java/sun/security/ssl/Alerts.java b/ojluni/src/main/java/sun/security/ssl/Alerts.java
deleted file mode 100755
index 672d9b7..0000000
--- a/ojluni/src/main/java/sun/security/ssl/Alerts.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import javax.net.ssl.*;
-
-/*
- * A simple class to congregate alerts, their definitions, and common
- * support methods.
- */
-
-final class Alerts {
-
- /*
- * Alerts are always a fixed two byte format (level/description).
- */
-
- // warnings and fatal errors are package private facilities/constants
-
- // Alert levels (enum AlertLevel)
- static final byte alert_warning = 1;
- static final byte alert_fatal = 2;
-
- /*
- * Alert descriptions (enum AlertDescription)
- *
- * We may not use them all in our processing, but if someone
- * sends us one, we can at least convert it to a string for the
- * user.
- */
- static final byte alert_close_notify = 0;
- static final byte alert_unexpected_message = 10;
- static final byte alert_bad_record_mac = 20;
- static final byte alert_decryption_failed = 21;
- static final byte alert_record_overflow = 22;
- static final byte alert_decompression_failure = 30;
- static final byte alert_handshake_failure = 40;
- static final byte alert_no_certificate = 41;
- static final byte alert_bad_certificate = 42;
- static final byte alert_unsupported_certificate = 43;
- static final byte alert_certificate_revoked = 44;
- static final byte alert_certificate_expired = 45;
- static final byte alert_certificate_unknown = 46;
- static final byte alert_illegal_parameter = 47;
- static final byte alert_unknown_ca = 48;
- static final byte alert_access_denied = 49;
- static final byte alert_decode_error = 50;
- static final byte alert_decrypt_error = 51;
- static final byte alert_export_restriction = 60;
- static final byte alert_protocol_version = 70;
- static final byte alert_insufficient_security = 71;
- static final byte alert_internal_error = 80;
- static final byte alert_user_canceled = 90;
- static final byte alert_no_renegotiation = 100;
-
- // from RFC 3546 (TLS Extensions)
- static final byte alert_unsupported_extension = 110;
- static final byte alert_certificate_unobtainable = 111;
- static final byte alert_unrecognized_name = 112;
- static final byte alert_bad_certificate_status_response = 113;
- static final byte alert_bad_certificate_hash_value = 114;
-
- static String alertDescription(byte code) {
- switch (code) {
-
- case alert_close_notify:
- return "close_notify";
- case alert_unexpected_message:
- return "unexpected_message";
- case alert_bad_record_mac:
- return "bad_record_mac";
- case alert_decryption_failed:
- return "decryption_failed";
- case alert_record_overflow:
- return "record_overflow";
- case alert_decompression_failure:
- return "decompression_failure";
- case alert_handshake_failure:
- return "handshake_failure";
- case alert_no_certificate:
- return "no_certificate";
- case alert_bad_certificate:
- return "bad_certificate";
- case alert_unsupported_certificate:
- return "unsupported_certificate";
- case alert_certificate_revoked:
- return "certificate_revoked";
- case alert_certificate_expired:
- return "certificate_expired";
- case alert_certificate_unknown:
- return "certificate_unknown";
- case alert_illegal_parameter:
- return "illegal_parameter";
- case alert_unknown_ca:
- return "unknown_ca";
- case alert_access_denied:
- return "access_denied";
- case alert_decode_error:
- return "decode_error";
- case alert_decrypt_error:
- return "decrypt_error";
- case alert_export_restriction:
- return "export_restriction";
- case alert_protocol_version:
- return "protocol_version";
- case alert_insufficient_security:
- return "insufficient_security";
- case alert_internal_error:
- return "internal_error";
- case alert_user_canceled:
- return "user_canceled";
- case alert_no_renegotiation:
- return "no_renegotiation";
- case alert_unsupported_extension:
- return "unsupported_extension";
- case alert_certificate_unobtainable:
- return "certificate_unobtainable";
- case alert_unrecognized_name:
- return "unrecognized_name";
- case alert_bad_certificate_status_response:
- return "bad_certificate_status_response";
- case alert_bad_certificate_hash_value:
- return "bad_certificate_hash_value";
-
- default:
- return "<UNKNOWN ALERT: " + (code & 0x0ff) + ">";
- }
- }
-
- static SSLException getSSLException(byte description, String reason) {
- return getSSLException(description, null, reason);
- }
-
- /*
- * Try to be a little more specific in our choice of
- * exceptions to throw.
- */
- static SSLException getSSLException(byte description, Throwable cause,
- String reason) {
-
- SSLException e;
- // the SSLException classes do not have a no-args constructor
- // make up a message if there is none
- if (reason == null) {
- if (cause != null) {
- reason = cause.toString();
- } else {
- reason = "";
- }
- }
- switch (description) {
- case alert_handshake_failure:
- case alert_no_certificate:
- case alert_bad_certificate:
- case alert_unsupported_certificate:
- case alert_certificate_revoked:
- case alert_certificate_expired:
- case alert_certificate_unknown:
- case alert_unknown_ca:
- case alert_access_denied:
- case alert_decrypt_error:
- case alert_export_restriction:
- case alert_insufficient_security:
- case alert_unsupported_extension:
- case alert_certificate_unobtainable:
- case alert_unrecognized_name:
- case alert_bad_certificate_status_response:
- case alert_bad_certificate_hash_value:
- e = new SSLHandshakeException(reason);
- break;
-
- case alert_close_notify:
- case alert_unexpected_message:
- case alert_bad_record_mac:
- case alert_decryption_failed:
- case alert_record_overflow:
- case alert_decompression_failure:
- case alert_illegal_parameter:
- case alert_decode_error:
- case alert_protocol_version:
- case alert_internal_error:
- case alert_user_canceled:
- case alert_no_renegotiation:
- default:
- e = new SSLException(reason);
- break;
- }
-
- if (cause != null) {
- e.initCause(cause);
- }
- return e;
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/AppInputStream.java b/ojluni/src/main/java/sun/security/ssl/AppInputStream.java
deleted file mode 100755
index 6c47978..0000000
--- a/ojluni/src/main/java/sun/security/ssl/AppInputStream.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-
-/**
- * InputStream for application data as returned by SSLSocket.getInputStream().
- * It uses an InputRecord as internal buffer that is refilled on demand
- * whenever it runs out of data.
- *
- * @author David Brownell
- */
-class AppInputStream extends InputStream {
-
- // static dummy array we use to implement skip()
- private final static byte[] SKIP_ARRAY = new byte[1024];
-
- private SSLSocketImpl c;
- InputRecord r;
-
- // One element array used to implement the single byte read() method
- private final byte[] oneByte = new byte[1];
-
- AppInputStream(SSLSocketImpl conn) {
- r = new InputRecord();
- c = conn;
- }
-
- /**
- * Return the minimum number of bytes that can be read without blocking.
- * Currently not synchronized.
- */
- public int available() throws IOException {
- if (c.checkEOF() || (r.isAppDataValid() == false)) {
- return 0;
- }
- return r.available();
- }
-
- /**
- * Read a single byte, returning -1 on non-fault EOF status.
- */
- public synchronized int read() throws IOException {
- int n = read(oneByte, 0, 1);
- if (n <= 0) { // EOF
- return -1;
- }
- return oneByte[0] & 0xff;
- }
-
- /**
- * Read up to "len" bytes into this buffer, starting at "off".
- * If the layer above needs more data, it asks for more, so we
- * are responsible only for blocking to fill at most one buffer,
- * and returning "-1" on non-fault EOF status.
- */
- public synchronized int read(byte b[], int off, int len)
- throws IOException {
- if (b == null) {
- throw new NullPointerException();
- } else if (off < 0 || len < 0 || len > b.length - off) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return 0;
- }
-
- if (c.checkEOF()) {
- return -1;
- }
- try {
- /*
- * Read data if needed ... notice that the connection guarantees
- * that handshake, alert, and change cipher spec data streams are
- * handled as they arrive, so we never see them here.
- */
- while (r.available() == 0) {
- c.readDataRecord(r);
- if (c.checkEOF()) {
- return -1;
- }
- }
-
- int howmany = Math.min(len, r.available());
- howmany = r.read(b, off, howmany);
- return howmany;
- } catch (Exception e) {
- // shutdown and rethrow (wrapped) exception as appropriate
- c.handleException(e);
- // dummy for compiler
- return -1;
- }
- }
-
-
- /**
- * Skip n bytes. This implementation is somewhat less efficient
- * than possible, but not badly so (redundant copy). We reuse
- * the read() code to keep things simpler. Note that SKIP_ARRAY
- * is static and may garbled by concurrent use, but we are not interested
- * in the data anyway.
- */
- public synchronized long skip(long n) throws IOException {
- long skipped = 0;
- while (n > 0) {
- int len = (int)Math.min(n, SKIP_ARRAY.length);
- int r = read(SKIP_ARRAY, 0, len);
- if (r <= 0) {
- break;
- }
- n -= r;
- skipped += r;
- }
- return skipped;
- }
-
- /*
- * Socket close is already synchronized, no need to block here.
- */
- public void close() throws IOException {
- c.close();
- }
-
- // inherit default mark/reset behavior (throw Exceptions) from InputStream
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/AppOutputStream.java b/ojluni/src/main/java/sun/security/ssl/AppOutputStream.java
deleted file mode 100755
index 5082bec..0000000
--- a/ojluni/src/main/java/sun/security/ssl/AppOutputStream.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.OutputStream;
-import java.io.IOException;
-
-/*
- * Output stream for application data. This is the kind of stream
- * that's handed out via SSLSocket.getOutputStream(). It's all the application
- * ever sees.
- *
- * Once the initial handshake has completed, application data may be
- * interleaved with handshake data. That is handled internally and remains
- * transparent to the application.
- *
- * @author David Brownell
- */
-class AppOutputStream extends OutputStream {
-
- private SSLSocketImpl c;
- OutputRecord r;
-
- // One element array used to implement the write(byte) method
- private final byte[] oneByte = new byte[1];
-
- AppOutputStream(SSLSocketImpl conn) {
- r = new OutputRecord(Record.ct_application_data);
- c = conn;
- }
-
- /**
- * Write the data out, NOW.
- */
- synchronized public void write(byte b[], int off, int len)
- throws IOException {
- if (b == null) {
- throw new NullPointerException();
- } else if (off < 0 || len < 0 || len > b.length - off) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return;
- }
-
- // check if the Socket is invalid (error or closed)
- c.checkWrite();
-
- /*
- * By default, we counter chosen plaintext issues on CBC mode
- * ciphersuites in SSLv3/TLS1.0 by sending one byte of application
- * data in the first record of every payload, and the rest in
- * subsequent record(s). Note that the issues have been solved in
- * TLS 1.1 or later.
- *
- * It is not necessary to split the very first application record of
- * a freshly negotiated TLS session, as there is no previous
- * application data to guess. To improve compatibility, we will not
- * split such records.
- *
- * This avoids issues in the outbound direction. For a full fix,
- * the peer must have similar protections.
- */
- boolean isFirstRecordOfThePayload = true;
-
- // Always flush at the end of each application level record.
- // This lets application synchronize read and write streams
- // however they like; if we buffered here, they couldn't.
- try {
- do {
- boolean holdRecord = false;
- int howmuch;
- if (isFirstRecordOfThePayload && c.needToSplitPayload()) {
- howmuch = Math.min(0x01, r.availableDataBytes());
- /*
- * Nagle's algorithm (TCP_NODELAY) was coming into
- * play here when writing short (split) packets.
- * Signal to the OutputRecord code to internally
- * buffer this small packet until the next outbound
- * packet (of any type) is written.
- */
- if ((len != 1) && (howmuch == 1)) {
- holdRecord = true;
- }
- } else {
- howmuch = Math.min(len, r.availableDataBytes());
- }
-
- if (isFirstRecordOfThePayload && howmuch != 0) {
- isFirstRecordOfThePayload = false;
- }
-
- // NOTE: *must* call c.writeRecord() even for howmuch == 0
- if (howmuch > 0) {
- r.write(b, off, howmuch);
- off += howmuch;
- len -= howmuch;
- }
- c.writeRecord(r, holdRecord);
- c.checkWrite();
- } while (len > 0);
- } catch (Exception e) {
- // shutdown and rethrow (wrapped) exception as appropriate
- c.handleException(e);
- }
- }
-
- /**
- * Write one byte now.
- */
- synchronized public void write(int i) throws IOException {
- oneByte[0] = (byte)i;
- write(oneByte, 0, 1);
- }
-
- /*
- * Socket close is already synchronized, no need to block here.
- */
- public void close() throws IOException {
- c.close();
- }
-
- // inherit no-op flush()
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/BaseSSLSocketImpl.java b/ojluni/src/main/java/sun/security/ssl/BaseSSLSocketImpl.java
deleted file mode 100755
index ef7503b..0000000
--- a/ojluni/src/main/java/sun/security/ssl/BaseSSLSocketImpl.java
+++ /dev/null
@@ -1,544 +0,0 @@
-/*
- * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.nio.channels.SocketChannel;
-import java.net.*;
-
-import javax.net.ssl.*;
-
-/**
- * Abstract base class for SSLSocketImpl. Its purpose is to house code with
- * no SSL related logic (or no logic at all). This makes SSLSocketImpl shorter
- * and easier to read. It contains a few constants and static methods plus
- * overridden java.net.Socket methods.
- *
- * Methods are defined final to ensure that they are not accidentally
- * overridden in SSLSocketImpl.
- *
- * @see javax.net.ssl.SSLSocket
- * @see SSLSocketImpl
- *
- */
-abstract class BaseSSLSocketImpl extends SSLSocket {
-
- /*
- * Normally "self" is "this" ... but not when this connection is
- * layered over a preexisting socket. If we're using an existing
- * socket, we delegate some actions to it. Else, we delegate
- * instead to "super". This is important to ensure that we don't
- * recurse infinitely ... e.g. close() calling itself, or doing
- * I/O in terms of our own streams.
- */
- final Socket self;
-
- BaseSSLSocketImpl() {
- super();
- this.self = this;
- }
-
- BaseSSLSocketImpl(Socket socket) {
- super();
- this.self = socket;
- }
-
- //
- // CONSTANTS AND STATIC METHODS
- //
-
- /**
- * TLS requires that a close_notify warning alert is sent before the
- * connection is closed in order to avoid truncation attacks. Some
- * implementations (MS IIS and others) don't do that. The property
- * below controls whether we accept that or treat it as an error.
- *
- * The default is "false", i.e. tolerate the broken behavior.
- */
- private final static String PROP_NAME =
- "com.sun.net.ssl.requireCloseNotify";
-
- final static boolean requireCloseNotify =
- Debug.getBooleanProperty(PROP_NAME, false);
-
- //
- // MISC SOCKET METHODS
- //
-
- /**
- * Returns the unique {@link java.nio.SocketChannel SocketChannel} object
- * associated with this socket, if any.
- * @see java.net.Socket#getChannel
- */
- public final SocketChannel getChannel() {
- if (self == this) {
- return super.getChannel();
- } else {
- return self.getChannel();
- }
- }
-
- /**
- * Binds the address to the socket.
- * @see java.net.Socket#bind
- */
- public void bind(SocketAddress bindpoint) throws IOException {
- /*
- * Bind to this socket
- */
- if (self == this) {
- super.bind(bindpoint);
- } else {
- // If we're binding on a layered socket...
- throw new IOException(
- "Underlying socket should already be connected");
- }
- }
-
- /**
- * Returns the address of the endpoint this socket is connected to
- * @see java.net.Socket#getLocalSocketAddress
- */
- public SocketAddress getLocalSocketAddress() {
- if (self == this) {
- return super.getLocalSocketAddress();
- } else {
- return self.getLocalSocketAddress();
- }
- }
-
- /**
- * Returns the address of the endpoint this socket is connected to
- * @see java.net.Socket#getRemoteSocketAddress
- */
- public SocketAddress getRemoteSocketAddress() {
- if (self == this) {
- return super.getRemoteSocketAddress();
- } else {
- return self.getRemoteSocketAddress();
- }
- }
-
- /**
- * Connects this socket to the server.
- *
- * This method is either called on an unconnected SSLSocketImpl by the
- * application, or it is called in the constructor of a regular
- * SSLSocketImpl. If we are layering on top on another socket, then
- * this method should not be called, because we assume that the
- * underlying socket is already connected by the time it is passed to
- * us.
- *
- * @param endpoint the <code>SocketAddress</code>
- * @throws IOException if an error occurs during the connection
- */
- public final void connect(SocketAddress endpoint) throws IOException {
- connect(endpoint, 0);
- }
-
- /**
- * Returns the connection state of the socket.
- * @see java.net.Socket#isConnected
- */
- public final boolean isConnected() {
- if (self == this) {
- return super.isConnected();
- } else {
- return self.isConnected();
- }
- }
-
- /**
- * Returns the binding state of the socket.
- * @see java.net.Socket#isBound
- */
- public final boolean isBound() {
- if (self == this) {
- return super.isBound();
- } else {
- return self.isBound();
- }
- }
-
- //
- // CLOSE RELATED METHODS
- //
-
- /**
- * The semantics of shutdownInput is not supported in TLS 1.0
- * spec. Thus when the method is called on an SSL socket, an
- * UnsupportedOperationException will be thrown.
- *
- * @throws UnsupportedOperationException
- */
- public final void shutdownInput() throws IOException {
- throw new UnsupportedOperationException("The method shutdownInput()" +
- " is not supported in SSLSocket");
- }
-
- /**
- * The semantics of shutdownOutput is not supported in TLS 1.0
- * spec. Thus when the method is called on an SSL socket, an
- * UnsupportedOperationException will be thrown.
- *
- * @throws UnsupportedOperationException
- */
- public final void shutdownOutput() throws IOException {
- throw new UnsupportedOperationException("The method shutdownOutput()" +
- " is not supported in SSLSocket");
-
- }
-
- /**
- * Returns the input state of the socket
- * @see java.net.Socket#isInputShutdown
- */
- public final boolean isInputShutdown() {
- if (self == this) {
- return super.isInputShutdown();
- } else {
- return self.isInputShutdown();
- }
- }
-
- /**
- * Returns the output state of the socket
- * @see java.net.Socket#isOutputShutdown
- */
- public final boolean isOutputShutdown() {
- if (self == this) {
- return super.isOutputShutdown();
- } else {
- return self.isOutputShutdown();
- }
- }
-
- /**
- * Ensures that the SSL connection is closed down as cleanly
- * as possible, in case the application forgets to do so.
- * This allows SSL connections to be implicitly reclaimed,
- * rather than forcing them to be explicitly reclaimed at
- * the penalty of prematurly killing SSL sessions.
- */
- protected final void finalize() throws Throwable {
- try {
- close();
- } catch (IOException e1) {
- try {
- if (self == this) {
- super.close();
- }
- } catch (IOException e2) {
- // ignore
- }
- } finally {
- // We called close on the underlying socket above to
- // make doubly sure all resources got released. We
- // don't finalize self in the case of overlain sockets,
- // that's a different object which the GC will finalize
- // separately.
-
- super.finalize();
- }
- }
-
- //
- // GET ADDRESS METHODS
- //
-
- /**
- * Returns the address of the remote peer for this connection.
- */
- public final InetAddress getInetAddress() {
- if (self == this) {
- return super.getInetAddress();
- } else {
- return self.getInetAddress();
- }
- }
-
- /**
- * Gets the local address to which the socket is bound.
- *
- * @return the local address to which the socket is bound.
- * @since JDK1.1
- */
- public final InetAddress getLocalAddress() {
- if (self == this) {
- return super.getLocalAddress();
- } else {
- return self.getLocalAddress();
- }
- }
-
- /**
- * Returns the number of the remote port that this connection uses.
- */
- public final int getPort() {
- if (self == this) {
- return super.getPort();
- } else {
- return self.getPort();
- }
- }
-
- /**
- * Returns the number of the local port that this connection uses.
- */
- public final int getLocalPort() {
- if (self == this) {
- return super.getLocalPort();
- } else {
- return self.getLocalPort();
- }
- }
-
- //
- // SOCKET OPTION METHODS
- //
-
- /**
- * Enables or disables the Nagle optimization.
- * @see java.net.Socket#setTcpNoDelay
- */
- public final void setTcpNoDelay(boolean value) throws SocketException {
- if (self == this) {
- super.setTcpNoDelay(value);
- } else {
- self.setTcpNoDelay(value);
- }
- }
-
- /**
- * Returns true if the Nagle optimization is disabled. This
- * relates to low-level buffering of TCP traffic, delaying the
- * traffic to promote better throughput.
- *
- * @see java.net.Socket#getTcpNoDelay
- */
- public final boolean getTcpNoDelay() throws SocketException {
- if (self == this) {
- return super.getTcpNoDelay();
- } else {
- return self.getTcpNoDelay();
- }
- }
-
- /**
- * Assigns the socket's linger timeout.
- * @see java.net.Socket#setSoLinger
- */
- public final void setSoLinger(boolean flag, int linger)
- throws SocketException {
- if (self == this) {
- super.setSoLinger(flag, linger);
- } else {
- self.setSoLinger(flag, linger);
- }
- }
-
- /**
- * Returns the socket's linger timeout.
- * @see java.net.Socket#getSoLinger
- */
- public final int getSoLinger() throws SocketException {
- if (self == this) {
- return super.getSoLinger();
- } else {
- return self.getSoLinger();
- }
- }
-
- /**
- * Send one byte of urgent data on the socket.
- * @see java.net.Socket#sendUrgentData
- * At this point, there seems to be no specific requirement to support
- * this for an SSLSocket. An implementation can be provided if a need
- * arises in future.
- */
- public final void sendUrgentData(int data) throws SocketException {
- throw new SocketException("This method is not supported "
- + "by SSLSockets");
- }
-
- /**
- * Enable/disable OOBINLINE (receipt of TCP urgent data) By default, this
- * option is disabled and TCP urgent data received on a socket is silently
- * discarded.
- * @see java.net.Socket#setOOBInline
- * Setting OOBInline does not have any effect on SSLSocket,
- * since currently we don't support sending urgent data.
- */
- public final void setOOBInline(boolean on) throws SocketException {
- throw new SocketException("This method is ineffective, since"
- + " sending urgent data is not supported by SSLSockets");
- }
-
- /**
- * Tests if OOBINLINE is enabled.
- * @see java.net.Socket#getOOBInline
- */
- public final boolean getOOBInline() throws SocketException {
- throw new SocketException("This method is ineffective, since"
- + " sending urgent data is not supported by SSLSockets");
- }
-
- /**
- * Returns the socket timeout.
- * @see java.net.Socket#getSoTimeout
- */
- public final int getSoTimeout() throws SocketException {
- if (self == this) {
- return super.getSoTimeout();
- } else {
- return self.getSoTimeout();
- }
- }
-
- public final void setSendBufferSize(int size) throws SocketException {
- if (self == this) {
- super.setSendBufferSize(size);
- } else {
- self.setSendBufferSize(size);
- }
- }
-
- public final int getSendBufferSize() throws SocketException {
- if (self == this) {
- return super.getSendBufferSize();
- } else {
- return self.getSendBufferSize();
- }
- }
-
- public final void setReceiveBufferSize(int size) throws SocketException {
- if (self == this) {
- super.setReceiveBufferSize(size);
- } else {
- self.setReceiveBufferSize(size);
- }
- }
-
- public final int getReceiveBufferSize() throws SocketException {
- if (self == this) {
- return super.getReceiveBufferSize();
- } else {
- return self.getReceiveBufferSize();
- }
- }
-
- /**
- * Enable/disable SO_KEEPALIVE.
- * @see java.net.Socket#setKeepAlive
- */
- public final void setKeepAlive(boolean on) throws SocketException {
- if (self == this) {
- super.setKeepAlive(on);
- } else {
- self.setKeepAlive(on);
- }
- }
-
- /**
- * Tests if SO_KEEPALIVE is enabled.
- * @see java.net.Socket#getKeepAlive
- */
- public final boolean getKeepAlive() throws SocketException {
- if (self == this) {
- return super.getKeepAlive();
- } else {
- return self.getKeepAlive();
- }
- }
-
- /**
- * Sets traffic class or type-of-service octet in the IP header for
- * packets sent from this Socket.
- * @see java.net.Socket#setTrafficClass
- */
- public final void setTrafficClass(int tc) throws SocketException {
- if (self == this) {
- super.setTrafficClass(tc);
- } else {
- self.setTrafficClass(tc);
- }
- }
-
- /**
- * Gets traffic class or type-of-service in the IP header for packets
- * sent from this Socket.
- * @see java.net.Socket#getTrafficClass
- */
- public final int getTrafficClass() throws SocketException {
- if (self == this) {
- return super.getTrafficClass();
- } else {
- return self.getTrafficClass();
- }
- }
-
- /**
- * Enable/disable SO_REUSEADDR.
- * @see java.net.Socket#setReuseAddress
- */
- public final void setReuseAddress(boolean on) throws SocketException {
- if (self == this) {
- super.setReuseAddress(on);
- } else {
- self.setReuseAddress(on);
- }
- }
-
- /**
- * Tests if SO_REUSEADDR is enabled.
- * @see java.net.Socket#getReuseAddress
- */
- public final boolean getReuseAddress() throws SocketException {
- if (self == this) {
- return super.getReuseAddress();
- } else {
- return self.getReuseAddress();
- }
- }
-
- /**
- * Sets performance preferences for this socket.
- *
- * @see java.net.Socket#setPerformancePreferences(int, int, int)
- */
- public void setPerformancePreferences(int connectionTime,
- int latency, int bandwidth) {
- if (self == this) {
- super.setPerformancePreferences(
- connectionTime, latency, bandwidth);
- } else {
- self.setPerformancePreferences(
- connectionTime, latency, bandwidth);
- }
- }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/ByteBufferInputStream.java b/ojluni/src/main/java/sun/security/ssl/ByteBufferInputStream.java
deleted file mode 100755
index 7191621..0000000
--- a/ojluni/src/main/java/sun/security/ssl/ByteBufferInputStream.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.nio.*;
-
-/**
- * A simple InputStream which uses ByteBuffers as it's backing store.
- * <P>
- * The only IOException should come if the InputStream has been closed.
- * All other IOException should not occur because all the data is local.
- * Data reads on an exhausted ByteBuffer returns a -1.
- *
- * @author Brad Wetmore
- */
-class ByteBufferInputStream extends InputStream {
-
- ByteBuffer bb;
-
- ByteBufferInputStream(ByteBuffer bb) {
- this.bb = bb;
- }
-
- /**
- * Returns a byte from the ByteBuffer.
- *
- * Increments position().
- */
- public int read() throws IOException {
-
- if (bb == null) {
- throw new IOException("read on a closed InputStream");
- }
-
- if (bb.remaining() == 0) {
- return -1;
- }
- return bb.get();
- }
-
- /**
- * Returns a byte array from the ByteBuffer.
- *
- * Increments position().
- */
- public int read(byte b[]) throws IOException {
-
- if (bb == null) {
- throw new IOException("read on a closed InputStream");
- }
-
- return read(b, 0, b.length);
- }
-
- /**
- * Returns a byte array from the ByteBuffer.
- *
- * Increments position().
- */
- public int read(byte b[], int off, int len) throws IOException {
-
- if (bb == null) {
- throw new IOException("read on a closed InputStream");
- }
-
- if (b == null) {
- throw new NullPointerException();
- } else if (off < 0 || len < 0 || len > b.length - off) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return 0;
- }
-
- int length = Math.min(bb.remaining(), len);
- if (length == 0) {
- return -1;
- }
-
- bb.get(b, off, length);
- return length;
- }
-
- /**
- * Skips over and discards <code>n</code> bytes of data from this input
- * stream.
- */
- public long skip(long n) throws IOException {
-
- if (bb == null) {
- throw new IOException("skip on a closed InputStream");
- }
-
- if (n <= 0) {
- return 0;
- }
-
- /*
- * ByteBuffers have at most an int, so lose the upper bits.
- * The contract allows this.
- */
- int nInt = (int) n;
- int skip = Math.min(bb.remaining(), nInt);
-
- bb.position(bb.position() + skip);
-
- return nInt;
- }
-
- /**
- * Returns the number of bytes that can be read (or skipped over)
- * from this input stream without blocking by the next caller of a
- * method for this input stream.
- */
- public int available() throws IOException {
-
- if (bb == null) {
- throw new IOException("available on a closed InputStream");
- }
-
- return bb.remaining();
- }
-
- /**
- * Closes this input stream and releases any system resources associated
- * with the stream.
- *
- * @exception IOException if an I/O error occurs.
- */
- public void close() throws IOException {
- bb = null;
- }
-
- /**
- * Marks the current position in this input stream.
- */
- public synchronized void mark(int readlimit) {}
-
- /**
- * Repositions this stream to the position at the time the
- * <code>mark</code> method was last called on this input stream.
- */
- public synchronized void reset() throws IOException {
- throw new IOException("mark/reset not supported");
- }
-
- /**
- * Tests if this input stream supports the <code>mark</code> and
- * <code>reset</code> methods.
- */
- public boolean markSupported() {
- return false;
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/CipherBox.java b/ojluni/src/main/java/sun/security/ssl/CipherBox.java
deleted file mode 100755
index 4dfbadd..0000000
--- a/ojluni/src/main/java/sun/security/ssl/CipherBox.java
+++ /dev/null
@@ -1,824 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.util.Hashtable;
-
-import java.security.*;
-import javax.crypto.*;
-import javax.crypto.spec.SecretKeySpec;
-import javax.crypto.spec.IvParameterSpec;
-
-import java.nio.*;
-
-import sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.*;
-
-import sun.misc.HexDumpEncoder;
-
-
-/**
- * This class handles bulk data enciphering/deciphering for each SSLv3
- * message. This provides data confidentiality. Stream ciphers (such
- * as RC4) don't need to do padding; block ciphers (e.g. DES) need it.
- *
- * Individual instances are obtained by calling the static method
- * newCipherBox(), which should only be invoked by BulkCipher.newCipher().
- *
- * In RFC 2246, with bock ciphers in CBC mode, the Initialization
- * Vector (IV) for the first record is generated with the other keys
- * and secrets when the security parameters are set. The IV for
- * subsequent records is the last ciphertext block from the previous
- * record.
- *
- * In RFC 4346, the implicit Initialization Vector (IV) is replaced
- * with an explicit IV to protect against CBC attacks. RFC 4346
- * recommends two algorithms used to generated the per-record IV.
- * The implementation uses the algorithm (2)(b), as described at
- * section 6.2.3.2 of RFC 4346.
- *
- * The usage of IV in CBC block cipher can be illustrated in
- * the following diagrams.
- *
- * (random)
- * R P1 IV C1
- * | | | |
- * SIV---+ |-----+ |-... |----- |------
- * | | | | | | | |
- * +----+ | +----+ | +----+ | +----+ |
- * | Ek | | + Ek + | | Dk | | | Dk | |
- * +----+ | +----+ | +----+ | +----+ |
- * | | | | | | | |
- * |----| |----| SIV--+ |----| |-...
- * | | | |
- * IV C1 R P1
- * (discard)
- *
- * CBC Encryption CBC Decryption
- *
- * NOTE that any ciphering involved in key exchange (e.g. with RSA) is
- * handled separately.
- *
- * @author David Brownell
- * @author Andreas Sterbenz
- */
-final class CipherBox {
-
- // A CipherBox that implements the identity operation
- final static CipherBox NULL = new CipherBox();
-
- /* Class and subclass dynamic debugging support */
- private static final Debug debug = Debug.getInstance("ssl");
-
- // the protocol version this cipher conforms to
- private final ProtocolVersion protocolVersion;
-
- // cipher object
- private final Cipher cipher;
-
- /**
- * Cipher blocksize, 0 for stream ciphers
- */
- private int blockSize;
-
- /**
- * secure random
- */
- private SecureRandom random;
-
- /**
- * Is the cipher of CBC mode?
- */
- private final boolean isCBCMode;
-
- /**
- * Fixed masks of various block size, as the initial decryption IVs
- * for TLS 1.1 or later.
- *
- * For performance, we do not use random IVs. As the initial decryption
- * IVs will be discarded by TLS decryption processes, so the fixed masks
- * do not hurt cryptographic strength.
- */
- private static Hashtable<Integer, IvParameterSpec> masks;
-
- /**
- * NULL cipherbox. Identity operation, no encryption.
- */
- private CipherBox() {
- this.protocolVersion = ProtocolVersion.DEFAULT;
- this.cipher = null;
- this.isCBCMode = false;
- }
-
- /**
- * Construct a new CipherBox using the cipher transformation.
- *
- * @exception NoSuchAlgorithmException if no appropriate JCE Cipher
- * implementation could be found.
- */
- private CipherBox(ProtocolVersion protocolVersion, BulkCipher bulkCipher,
- SecretKey key, IvParameterSpec iv, SecureRandom random,
- boolean encrypt) throws NoSuchAlgorithmException {
- try {
- this.protocolVersion = protocolVersion;
- this.cipher = JsseJce.getCipher(bulkCipher.transformation);
- int mode = encrypt ? Cipher.ENCRYPT_MODE : Cipher.DECRYPT_MODE;
-
- if (random == null) {
- random = JsseJce.getSecureRandom();
- }
- this.random = random;
- this.isCBCMode = bulkCipher.isCBCMode;
-
- /*
- * RFC 4346 recommends two algorithms used to generated the
- * per-record IV. The implementation uses the algorithm (2)(b),
- * as described at section 6.2.3.2 of RFC 4346.
- *
- * As we don't care about the initial IV value for TLS 1.1 or
- * later, so if the "iv" parameter is null, we use the default
- * value generated by Cipher.init() for encryption, and a fixed
- * mask for decryption.
- */
- if (iv == null && bulkCipher.ivSize != 0 &&
- mode == Cipher.DECRYPT_MODE &&
- protocolVersion.v >= ProtocolVersion.TLS11.v) {
- iv = getFixedMask(bulkCipher.ivSize);
- }
-
- cipher.init(mode, key, iv, random);
-
- // Do not call getBlockSize until after init()
- // otherwise we would disrupt JCE delayed provider selection
- blockSize = cipher.getBlockSize();
- // some providers implement getBlockSize() incorrectly
- if (blockSize == 1) {
- blockSize = 0;
- }
- } catch (NoSuchAlgorithmException e) {
- throw e;
- } catch (Exception e) {
- throw new NoSuchAlgorithmException
- ("Could not create cipher " + bulkCipher, e);
- } catch (ExceptionInInitializerError e) {
- throw new NoSuchAlgorithmException
- ("Could not create cipher " + bulkCipher, e);
- }
- }
-
- /*
- * Factory method to obtain a new CipherBox object.
- */
- static CipherBox newCipherBox(ProtocolVersion version, BulkCipher cipher,
- SecretKey key, IvParameterSpec iv, SecureRandom random,
- boolean encrypt) throws NoSuchAlgorithmException {
- if (cipher.allowed == false) {
- throw new NoSuchAlgorithmException("Unsupported cipher " + cipher);
- }
-
- if (cipher == B_NULL) {
- return NULL;
- } else {
- return new CipherBox(version, cipher, key, iv, random, encrypt);
- }
- }
-
- /*
- * Get a fixed mask, as the initial decryption IVs for TLS 1.1 or later.
- */
- private static IvParameterSpec getFixedMask(int ivSize) {
- if (masks == null) {
- masks = new Hashtable<Integer, IvParameterSpec>(5);
- }
-
- IvParameterSpec iv = masks.get(ivSize);
- if (iv == null) {
- iv = new IvParameterSpec(new byte[ivSize]);
- masks.put(ivSize, iv);
- }
-
- return iv;
- }
-
- /*
- * Encrypts a block of data, returning the size of the
- * resulting block.
- */
- int encrypt(byte[] buf, int offset, int len) {
- if (cipher == null) {
- return len;
- }
-
- try {
- if (blockSize != 0) {
- // TLSv1.1 needs a IV block
- if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
- // generate a random number
- byte[] prefix = new byte[blockSize];
- random.nextBytes(prefix);
-
- // move forward the plaintext
- System.arraycopy(buf, offset,
- buf, offset + prefix.length, len);
-
- // prefix the plaintext
- System.arraycopy(prefix, 0,
- buf, offset, prefix.length);
-
- len += prefix.length;
- }
-
- len = addPadding(buf, offset, len, blockSize);
- }
- if (debug != null && Debug.isOn("plaintext")) {
- try {
- HexDumpEncoder hd = new HexDumpEncoder();
-
- System.out.println(
- "Padded plaintext before ENCRYPTION: len = "
- + len);
- hd.encodeBuffer(
- new ByteArrayInputStream(buf, offset, len),
- System.out);
- } catch (IOException e) { }
- }
- int newLen = cipher.update(buf, offset, len, buf, offset);
- if (newLen != len) {
- // catch BouncyCastle buffering error
- throw new RuntimeException("Cipher buffering error " +
- "in JCE provider " + cipher.getProvider().getName());
- }
- return newLen;
- } catch (ShortBufferException e) {
- throw new ArrayIndexOutOfBoundsException(e.toString());
- }
- }
-
- /*
- * Encrypts a ByteBuffer block of data, returning the size of the
- * resulting block.
- *
- * The byte buffers position and limit initially define the amount
- * to encrypt. On return, the position and limit are
- * set to last position padded/encrypted. The limit may have changed
- * because of the added padding bytes.
- */
- int encrypt(ByteBuffer bb) {
-
- int len = bb.remaining();
-
- if (cipher == null) {
- bb.position(bb.limit());
- return len;
- }
-
- try {
- int pos = bb.position();
-
- if (blockSize != 0) {
- // TLSv1.1 needs a IV block
- if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
- // generate a random number
- byte[] prefix = new byte[blockSize];
- random.nextBytes(prefix);
-
- // move forward the plaintext
- byte[] buf = null;
- int limit = bb.limit();
- if (bb.hasArray()) {
- int arrayOffset = bb.arrayOffset();
- buf = bb.array();
- System.arraycopy(buf, arrayOffset + pos,
- buf, arrayOffset + pos + prefix.length,
- limit - pos);
- bb.limit(limit + prefix.length);
- } else {
- buf = new byte[limit - pos];
- bb.get(buf, 0, limit - pos);
- bb.position(pos + prefix.length);
- bb.limit(limit + prefix.length);
- bb.put(buf);
- }
- bb.position(pos);
-
- // prefix the plaintext
- bb.put(prefix);
- bb.position(pos);
- }
-
- // addPadding adjusts pos/limit
- len = addPadding(bb, blockSize);
- bb.position(pos);
- }
- if (debug != null && Debug.isOn("plaintext")) {
- try {
- HexDumpEncoder hd = new HexDumpEncoder();
-
- System.out.println(
- "Padded plaintext before ENCRYPTION: len = "
- + len);
- hd.encodeBuffer(bb, System.out);
-
- } catch (IOException e) { }
- /*
- * reset back to beginning
- */
- bb.position(pos);
- }
-
- /*
- * Encrypt "in-place". This does not add its own padding.
- */
- ByteBuffer dup = bb.duplicate();
- int newLen = cipher.update(dup, bb);
-
- if (bb.position() != dup.position()) {
- throw new RuntimeException("bytebuffer padding error");
- }
-
- if (newLen != len) {
- // catch BouncyCastle buffering error
- throw new RuntimeException("Cipher buffering error " +
- "in JCE provider " + cipher.getProvider().getName());
- }
- return newLen;
- } catch (ShortBufferException e) {
- RuntimeException exc = new RuntimeException(e.toString());
- exc.initCause(e);
- throw exc;
- }
- }
-
-
- /*
- * Decrypts a block of data, returning the size of the
- * resulting block if padding was required.
- *
- * For SSLv3 and TLSv1.0, with block ciphers in CBC mode the
- * Initialization Vector (IV) for the first record is generated by
- * the handshake protocol, the IV for subsequent records is the
- * last ciphertext block from the previous record.
- *
- * From TLSv1.1, the implicit IV is replaced with an explicit IV to
- * protect against CBC attacks.
- *
- * Differentiating between bad_record_mac and decryption_failed alerts
- * may permit certain attacks against CBC mode. It is preferable to
- * uniformly use the bad_record_mac alert to hide the specific type of
- * the error.
- */
- int decrypt(byte[] buf, int offset, int len,
- int tagLen) throws BadPaddingException {
- if (cipher == null) {
- return len;
- }
-
- try {
- int newLen = cipher.update(buf, offset, len, buf, offset);
- if (newLen != len) {
- // catch BouncyCastle buffering error
- throw new RuntimeException("Cipher buffering error " +
- "in JCE provider " + cipher.getProvider().getName());
- }
- if (debug != null && Debug.isOn("plaintext")) {
- try {
- HexDumpEncoder hd = new HexDumpEncoder();
-
- System.out.println(
- "Padded plaintext after DECRYPTION: len = "
- + newLen);
- hd.encodeBuffer(
- new ByteArrayInputStream(buf, offset, newLen),
- System.out);
- } catch (IOException e) { }
- }
-
- if (blockSize != 0) {
- newLen = removePadding(
- buf, offset, newLen, tagLen, blockSize, protocolVersion);
-
- if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
- if (newLen < blockSize) {
- throw new BadPaddingException("invalid explicit IV");
- }
-
- // discards the first cipher block, the IV component.
- System.arraycopy(buf, offset + blockSize,
- buf, offset, newLen - blockSize);
-
- newLen -= blockSize;
- }
- }
- return newLen;
- } catch (ShortBufferException e) {
- throw new ArrayIndexOutOfBoundsException(e.toString());
- }
- }
-
-
- /*
- * Decrypts a block of data, returning the size of the
- * resulting block if padding was required. position and limit
- * point to the end of the decrypted/depadded data. The initial
- * limit and new limit may be different, given we may
- * have stripped off some padding bytes.
- *
- * @see decrypt(byte[], int, int)
- */
- int decrypt(ByteBuffer bb, int tagLen) throws BadPaddingException {
-
- int len = bb.remaining();
-
- if (cipher == null) {
- bb.position(bb.limit());
- return len;
- }
-
- try {
- /*
- * Decrypt "in-place".
- */
- int pos = bb.position();
- ByteBuffer dup = bb.duplicate();
- int newLen = cipher.update(dup, bb);
- if (newLen != len) {
- // catch BouncyCastle buffering error
- throw new RuntimeException("Cipher buffering error " +
- "in JCE provider " + cipher.getProvider().getName());
- }
-
- if (debug != null && Debug.isOn("plaintext")) {
- try {
- HexDumpEncoder hd = new HexDumpEncoder();
-
- System.out.println(
- "Padded plaintext after DECRYPTION: len = "
- + newLen);
-
- hd.encodeBuffer(
- (ByteBuffer)bb.duplicate().position(pos), System.out);
- } catch (IOException e) { }
- }
-
- /*
- * Remove the block padding.
- */
- if (blockSize != 0) {
- bb.position(pos);
- newLen = removePadding(
- bb, tagLen, blockSize, protocolVersion);
-
- if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
- if (newLen < blockSize) {
- throw new BadPaddingException("invalid explicit IV");
- }
-
- // discards the first cipher block, the IV component.
- byte[] buf = null;
- int limit = bb.limit();
- if (bb.hasArray()) {
- int arrayOffset = bb.arrayOffset();
- buf = bb.array();
- System.arraycopy(buf, arrayOffset + pos + blockSize,
- buf, arrayOffset + pos, limit - pos - blockSize);
- bb.limit(limit - blockSize);
- } else {
- buf = new byte[limit - pos - blockSize];
- bb.position(pos + blockSize);
- bb.get(buf);
- bb.position(pos);
- bb.put(buf);
- bb.limit(limit - blockSize);
- }
-
- // reset the position to the end of the decrypted data
- limit = bb.limit();
- bb.position(limit);
- }
- }
- return newLen;
- } catch (ShortBufferException e) {
- RuntimeException exc = new RuntimeException(e.toString());
- exc.initCause(e);
- throw exc;
- }
- }
-
- private static int addPadding(byte[] buf, int offset, int len,
- int blockSize) {
- int newlen = len + 1;
- byte pad;
- int i;
-
- if ((newlen % blockSize) != 0) {
- newlen += blockSize - 1;
- newlen -= newlen % blockSize;
- }
- pad = (byte) (newlen - len);
-
- if (buf.length < (newlen + offset)) {
- throw new IllegalArgumentException("no space to pad buffer");
- }
-
- /*
- * TLS version of the padding works for both SSLv3 and TLSv1
- */
- for (i = 0, offset += len; i < pad; i++) {
- buf [offset++] = (byte) (pad - 1);
- }
- return newlen;
- }
-
- /*
- * Apply the padding to the buffer.
- *
- * Limit is advanced to the new buffer length.
- * Position is equal to limit.
- */
- private static int addPadding(ByteBuffer bb, int blockSize) {
-
- int len = bb.remaining();
- int offset = bb.position();
-
- int newlen = len + 1;
- byte pad;
- int i;
-
- if ((newlen % blockSize) != 0) {
- newlen += blockSize - 1;
- newlen -= newlen % blockSize;
- }
- pad = (byte) (newlen - len);
-
- /*
- * Update the limit to what will be padded.
- */
- bb.limit(newlen + offset);
-
- /*
- * TLS version of the padding works for both SSLv3 and TLSv1
- */
- for (i = 0, offset += len; i < pad; i++) {
- bb.put(offset++, (byte) (pad - 1));
- }
-
- bb.position(offset);
- bb.limit(offset);
-
- return newlen;
- }
-
- /*
- * A constant-time check of the padding.
- *
- * NOTE that we are checking both the padding and the padLen bytes here.
- *
- * The caller MUST ensure that the len parameter is a positive number.
- */
- private static int[] checkPadding(
- byte[] buf, int offset, int len, byte pad) {
-
- if (len <= 0) {
- throw new RuntimeException("padding len must be positive");
- }
-
- // An array of hits is used to prevent Hotspot optimization for
- // the purpose of a constant-time check.
- int[] results = {0, 0}; // {missed #, matched #}
- for (int i = 0; i <= 256;) {
- for (int j = 0; j < len && i <= 256; j++, i++) { // j <= i
- if (buf[offset + j] != pad) {
- results[0]++; // mismatched padding data
- } else {
- results[1]++; // matched padding data
- }
- }
- }
-
- return results;
- }
-
- /*
- * A constant-time check of the padding.
- *
- * NOTE that we are checking both the padding and the padLen bytes here.
- *
- * The caller MUST ensure that the bb parameter has remaining.
- */
- private static int[] checkPadding(ByteBuffer bb, byte pad) {
-
- if (!bb.hasRemaining()) {
- throw new RuntimeException("hasRemaining() must be positive");
- }
-
- // An array of hits is used to prevent Hotspot optimization for
- // the purpose of a constant-time check.
- int[] results = {0, 0}; // {missed #, matched #}
- bb.mark();
- for (int i = 0; i <= 256; bb.reset()) {
- for (; bb.hasRemaining() && i <= 256; i++) {
- if (bb.get() != pad) {
- results[0]++; // mismatched padding data
- } else {
- results[1]++; // matched padding data
- }
- }
- }
-
- return results;
- }
-
- /*
- * Typical TLS padding format for a 64 bit block cipher is as follows:
- * xx xx xx xx xx xx xx 00
- * xx xx xx xx xx xx 01 01
- * ...
- * xx 06 06 06 06 06 06 06
- * 07 07 07 07 07 07 07 07
- * TLS also allows any amount of padding from 1 and 256 bytes as long
- * as it makes the data a multiple of the block size
- */
- private static int removePadding(byte[] buf, int offset, int len,
- int tagLen, int blockSize,
- ProtocolVersion protocolVersion) throws BadPaddingException {
-
- // last byte is length byte (i.e. actual padding length - 1)
- int padOffset = offset + len - 1;
- int padLen = buf[padOffset] & 0xFF;
-
- int newLen = len - (padLen + 1);
- if ((newLen - tagLen) < 0) {
- // If the buffer is not long enough to contain the padding plus
- // a MAC tag, do a dummy constant-time padding check.
- //
- // Note that it is a dummy check, so we won't care about what is
- // the actual padding data.
- checkPadding(buf, offset, len, (byte)(padLen & 0xFF));
-
- throw new BadPaddingException("Invalid Padding length: " + padLen);
- }
-
- // The padding data should be filled with the padding length value.
- int[] results = checkPadding(buf, offset + newLen,
- padLen + 1, (byte)(padLen & 0xFF));
- if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
- if (results[0] != 0) { // padding data has invalid bytes
- throw new BadPaddingException("Invalid TLS padding data");
- }
- } else { // SSLv3
- // SSLv3 requires 0 <= length byte < block size
- // some implementations do 1 <= length byte <= block size,
- // so accept that as well
- // v3 does not require any particular value for the other bytes
- if (padLen > blockSize) {
- throw new BadPaddingException("Invalid SSLv3 padding");
- }
- }
- return newLen;
- }
-
- /*
- * Position/limit is equal the removed padding.
- */
- private static int removePadding(ByteBuffer bb,
- int tagLen, int blockSize,
- ProtocolVersion protocolVersion) throws BadPaddingException {
-
- int len = bb.remaining();
- int offset = bb.position();
-
- // last byte is length byte (i.e. actual padding length - 1)
- int padOffset = offset + len - 1;
- int padLen = bb.get(padOffset) & 0xFF;
-
- int newLen = len - (padLen + 1);
- if ((newLen - tagLen) < 0) {
- // If the buffer is not long enough to contain the padding plus
- // a MAC tag, do a dummy constant-time padding check.
- //
- // Note that it is a dummy check, so we won't care about what is
- // the actual padding data.
- checkPadding(bb.duplicate(), (byte)(padLen & 0xFF));
-
- throw new BadPaddingException("Invalid Padding length: " + padLen);
- }
-
- // The padding data should be filled with the padding length value.
- int[] results = checkPadding(
- (ByteBuffer)bb.duplicate().position(offset + newLen),
- (byte)(padLen & 0xFF));
- if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
- if (results[0] != 0) { // padding data has invalid bytes
- throw new BadPaddingException("Invalid TLS padding data");
- }
- } else { // SSLv3
- // SSLv3 requires 0 <= length byte < block size
- // some implementations do 1 <= length byte <= block size,
- // so accept that as well
- // v3 does not require any particular value for the other bytes
- if (padLen > blockSize) {
- throw new BadPaddingException("Invalid SSLv3 padding");
- }
- }
-
- /*
- * Reset buffer limit to remove padding.
- */
- bb.position(offset + newLen);
- bb.limit(offset + newLen);
-
- return newLen;
- }
-
- /*
- * Dispose of any intermediate state in the underlying cipher.
- * For PKCS11 ciphers, this will release any attached sessions, and
- * thus make finalization faster.
- */
- void dispose() {
- try {
- if (cipher != null) {
- // ignore return value.
- cipher.doFinal();
- }
- } catch (GeneralSecurityException e) {
- // swallow for now.
- }
- }
-
- /*
- * Does the cipher use CBC mode?
- *
- * @return true if the cipher use CBC mode, false otherwise.
- */
- boolean isCBCMode() {
- return isCBCMode;
- }
-
- /**
- * Is the cipher null?
- *
- * @return true if the cipher is null, false otherwise.
- */
- boolean isNullCipher() {
- return cipher == null;
- }
-
- /**
- * Sanity check the length of a fragment before decryption.
- *
- * In CBC mode, check that the fragment length is one or multiple times
- * of the block size of the cipher suite, and is at least one (one is the
- * smallest size of padding in CBC mode) bigger than the tag size of the
- * MAC algorithm except the explicit IV size for TLS 1.1 or later.
- *
- * In non-CBC mode, check that the fragment length is not less than the
- * tag size of the MAC algorithm.
- *
- * @return true if the length of a fragment matches above requirements
- */
- boolean sanityCheck(int tagLen, int fragmentLen) {
- if (!isCBCMode) {
- return fragmentLen >= tagLen;
- }
-
- if ((fragmentLen % blockSize) == 0) {
- int minimal = tagLen + 1;
- minimal = (minimal >= blockSize) ? minimal : blockSize;
- if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
- minimal += blockSize; // plus the size of the explicit IV
- }
-
- return (fragmentLen >= minimal);
- }
-
- return false;
- }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/CipherSuite.java b/ojluni/src/main/java/sun/security/ssl/CipherSuite.java
deleted file mode 100755
index 3bf67fa..0000000
--- a/ojluni/src/main/java/sun/security/ssl/CipherSuite.java
+++ /dev/null
@@ -1,1292 +0,0 @@
-/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.util.*;
-
-import java.security.NoSuchAlgorithmException;
-import java.security.InvalidKeyException;
-import java.security.SecureRandom;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-
-import sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.KeyExchange.*;
-import static sun.security.ssl.CipherSuite.PRF.*;
-import static sun.security.ssl.JsseJce.*;
-
-/**
- * An SSL/TLS CipherSuite. Constants for the standard key exchange, cipher,
- * and mac algorithms are also defined in this class.
- *
- * The CipherSuite class and the inner classes defined in this file roughly
- * follow the type safe enum pattern described in Effective Java. This means:
- *
- * . instances are immutable, classes are final
- *
- * . there is a unique instance of every value, i.e. there are never two
- * instances representing the same CipherSuite, etc. This means equality
- * tests can be performed using == instead of equals() (although that works
- * as well). [A minor exception are *unsupported* CipherSuites read from a
- * handshake message, but this is usually irrelevant]
- *
- * . instances are obtained using the static valueOf() factory methods.
- *
- * . properties are defined as final variables and made available as
- * package private variables without method accessors
- *
- * . if the member variable allowed is false, the given algorithm is either
- * unavailable or disabled at compile time
- *
- */
-final class CipherSuite implements Comparable {
-
- // minimum priority for supported CipherSuites
- final static int SUPPORTED_SUITES_PRIORITY = 1;
-
- // minimum priority for default enabled CipherSuites
- final static int DEFAULT_SUITES_PRIORITY = 300;
-
- // Flag indicating if CipherSuite availability can change dynamically.
- // This is the case when we rely on a JCE cipher implementation that
- // may not be available in the installed JCE providers.
- // It is true because we might not have an ECC implementation.
- final static boolean DYNAMIC_AVAILABILITY = true;
-
- private final static boolean ALLOW_ECC = Debug.getBooleanProperty
- ("com.sun.net.ssl.enableECC", true);
-
- // Map Integer(id) -> CipherSuite
- // contains all known CipherSuites
- private final static Map<Integer,CipherSuite> idMap;
-
- // Map String(name) -> CipherSuite
- // contains only supported CipherSuites (i.e. allowed == true)
- private final static Map<String,CipherSuite> nameMap;
-
- // Protocol defined CipherSuite name, e.g. SSL_RSA_WITH_RC4_128_MD5
- // we use TLS_* only for new CipherSuites, still SSL_* for old ones
- final String name;
-
- // id in 16 bit MSB format, i.e. 0x0004 for SSL_RSA_WITH_RC4_128_MD5
- final int id;
-
- // priority for the internal default preference order. the higher the
- // better. Each supported CipherSuite *must* have a unique priority.
- // Ciphersuites with priority >= DEFAULT_SUITES_PRIORITY are enabled
- // by default
- final int priority;
-
- // key exchange, bulk cipher, mac and prf algorithms. See those
- // classes below.
- final KeyExchange keyExchange;
- final BulkCipher cipher;
- final MacAlg macAlg;
- final PRF prfAlg;
-
- // whether a CipherSuite qualifies as exportable under 512/40 bit rules.
- // TLS 1.1+ (RFC 4346) must not negotiate to these suites.
- final boolean exportable;
-
- // true iff implemented and enabled at compile time
- final boolean allowed;
-
- // obsoleted since protocol version
- final int obsoleted;
-
- // supported since protocol version
- final int supported;
-
- /**
- * Constructor for implemented CipherSuites.
- */
- private CipherSuite(String name, int id, int priority,
- KeyExchange keyExchange, BulkCipher cipher,
- boolean allowed, int obsoleted, int supported, PRF prfAlg) {
- this.name = name;
- this.id = id;
- this.priority = priority;
- this.keyExchange = keyExchange;
- this.cipher = cipher;
- this.exportable = cipher.exportable;
- if (name.endsWith("_MD5")) {
- macAlg = M_MD5;
- } else if (name.endsWith("_SHA")) {
- macAlg = M_SHA;
- } else if (name.endsWith("_SHA256")) {
- macAlg = M_SHA256;
- } else if (name.endsWith("_SHA384")) {
- macAlg = M_SHA384;
- } else if (name.endsWith("_NULL")) {
- macAlg = M_NULL;
- } else if (name.endsWith("_SCSV")) {
- macAlg = M_NULL;
- } else {
- throw new IllegalArgumentException
- ("Unknown MAC algorithm for ciphersuite " + name);
- }
-
- allowed &= keyExchange.allowed;
- allowed &= cipher.allowed;
- this.allowed = allowed;
- this.obsoleted = obsoleted;
- this.supported = supported;
- this.prfAlg = prfAlg;
- }
-
- /**
- * Constructor for unimplemented CipherSuites.
- */
- private CipherSuite(String name, int id) {
- this.name = name;
- this.id = id;
- this.allowed = false;
-
- this.priority = 0;
- this.keyExchange = null;
- this.cipher = null;
- this.macAlg = null;
- this.exportable = false;
- this.obsoleted = ProtocolVersion.LIMIT_MAX_VALUE;
- this.supported = ProtocolVersion.LIMIT_MIN_VALUE;
- this.prfAlg = P_NONE;
- }
-
- /**
- * Return whether this CipherSuite is available for use. A
- * CipherSuite may be unavailable even if it is supported
- * (i.e. allowed == true) if the required JCE cipher is not installed.
- * In some configuration, this situation may change over time, call
- * CipherSuiteList.clearAvailableCache() before this method to obtain
- * the most current status.
- */
- boolean isAvailable() {
- return allowed && keyExchange.isAvailable() && cipher.isAvailable();
- }
-
- boolean isNegotiable() {
- return this != C_SCSV && isAvailable();
- }
-
- /**
- * Compares CipherSuites based on their priority. Has the effect of
- * sorting CipherSuites when put in a sorted collection, which is
- * used by CipherSuiteList. Follows standard Comparable contract.
- *
- * Note that for unsupported CipherSuites parsed from a handshake
- * message we violate the equals() contract.
- */
- public int compareTo(Object o) {
- return ((CipherSuite)o).priority - priority;
- }
-
- /**
- * Returns this.name.
- */
- public String toString() {
- return name;
- }
-
- /**
- * Return a CipherSuite for the given name. The returned CipherSuite
- * is supported by this implementation but may not actually be
- * currently useable. See isAvailable().
- *
- * @exception IllegalArgumentException if the CipherSuite is unknown or
- * unsupported.
- */
- static CipherSuite valueOf(String s) {
- if (s == null) {
- throw new IllegalArgumentException("Name must not be null");
- }
-
- CipherSuite c = nameMap.get(s);
- if ((c == null) || (c.allowed == false)) {
- throw new IllegalArgumentException("Unsupported ciphersuite " + s);
- }
-
- return c;
- }
-
- /**
- * Return a CipherSuite with the given ID. A temporary object is
- * constructed if the ID is unknown. Use isAvailable() to verify that
- * the CipherSuite can actually be used.
- */
- static CipherSuite valueOf(int id1, int id2) {
- id1 &= 0xff;
- id2 &= 0xff;
- int id = (id1 << 8) | id2;
- CipherSuite c = idMap.get(id);
- if (c == null) {
- String h1 = Integer.toString(id1, 16);
- String h2 = Integer.toString(id2, 16);
- c = new CipherSuite("Unknown 0x" + h1 + ":0x" + h2, id);
- }
- return c;
- }
-
- // for use by CipherSuiteList only
- static Collection<CipherSuite> allowedCipherSuites() {
- return nameMap.values();
- }
-
- /*
- * Use this method when all of the values need to be specified.
- * This is primarily used when defining a new ciphersuite for
- * TLS 1.2+ that doesn't use the "default" PRF.
- */
- private static void add(String name, int id, int priority,
- KeyExchange keyExchange, BulkCipher cipher,
- boolean allowed, int obsoleted, int supported, PRF prf) {
-
- CipherSuite c = new CipherSuite(name, id, priority, keyExchange,
- cipher, allowed, obsoleted, supported, prf);
- if (idMap.put(id, c) != null) {
- throw new RuntimeException("Duplicate ciphersuite definition: "
- + id + ", " + name);
- }
- if (c.allowed) {
- if (nameMap.put(name, c) != null) {
- throw new RuntimeException("Duplicate ciphersuite definition: "
- + id + ", " + name);
- }
- }
- }
-
- /*
- * Use this method when there is no lower protocol limit where this
- * suite can be used, and the PRF is P_SHA256. That is, the
- * existing ciphersuites. From RFC 5246:
- *
- * All cipher suites in this document use P_SHA256.
- */
- private static void add(String name, int id, int priority,
- KeyExchange keyExchange, BulkCipher cipher,
- boolean allowed, int obsoleted) {
- // If this is an obsoleted suite, then don't let the TLS 1.2
- // protocol have a valid PRF value.
- PRF prf = P_SHA256;
- if (obsoleted < ProtocolVersion.TLS12.v) {
- prf = P_NONE;
- }
-
- add(name, id, priority, keyExchange, cipher, allowed, obsoleted,
- ProtocolVersion.LIMIT_MIN_VALUE, prf);
- }
-
- /*
- * Use this method when there is no upper protocol limit. That is,
- * suites which have not been obsoleted.
- */
- private static void add(String name, int id, int priority,
- KeyExchange keyExchange, BulkCipher cipher, boolean allowed) {
- add(name, id, priority, keyExchange,
- cipher, allowed, ProtocolVersion.LIMIT_MAX_VALUE);
- }
-
- /*
- * Use this method to define an unimplemented suite. This provides
- * a number<->name mapping that can be used for debugging.
- */
- private static void add(String name, int id) {
- CipherSuite c = new CipherSuite(name, id);
- if (idMap.put(id, c) != null) {
- throw new RuntimeException("Duplicate ciphersuite definition: "
- + id + ", " + name);
- }
- }
-
- /**
- * An SSL/TLS key exchange algorithm.
- */
- static enum KeyExchange {
-
- // key exchange algorithms
- K_NULL ("NULL", false),
- K_RSA ("RSA", true),
- K_RSA_EXPORT ("RSA_EXPORT", true),
- K_DH_RSA ("DH_RSA", false),
- K_DH_DSS ("DH_DSS", false),
- K_DHE_DSS ("DHE_DSS", true),
- K_DHE_RSA ("DHE_RSA", true),
- K_DH_ANON ("DH_anon", true),
-
- K_ECDH_ECDSA ("ECDH_ECDSA", ALLOW_ECC),
- K_ECDH_RSA ("ECDH_RSA", ALLOW_ECC),
- K_ECDHE_ECDSA("ECDHE_ECDSA", ALLOW_ECC),
- K_ECDHE_RSA ("ECDHE_RSA", ALLOW_ECC),
- K_ECDH_ANON ("ECDH_anon", ALLOW_ECC),
-
- // Kerberos cipher suites
- K_KRB5 ("KRB5", true),
- K_KRB5_EXPORT("KRB5_EXPORT", true),
-
- // renegotiation protection request signaling cipher suite
- K_SCSV ("SCSV", true);
-
- // name of the key exchange algorithm, e.g. DHE_DSS
- final String name;
- final boolean allowed;
- private final boolean alwaysAvailable;
-
- KeyExchange(String name, boolean allowed) {
- this.name = name;
- this.allowed = allowed;
- this.alwaysAvailable = allowed &&
- (!name.startsWith("EC")) && (!name.startsWith("KRB"));
- }
-
- boolean isAvailable() {
- if (alwaysAvailable) {
- return true;
- }
-
- if (name.startsWith("EC")) {
- return (allowed && JsseJce.isEcAvailable());
- } else if (name.startsWith("KRB")) {
- return (allowed && JsseJce.isKerberosAvailable());
- } else {
- return allowed;
- }
- }
-
- public String toString() {
- return name;
- }
- }
-
- /**
- * An SSL/TLS bulk cipher algorithm. One instance per combination of
- * cipher and key length.
- *
- * Also contains a factory method to obtain in initialized CipherBox
- * for this algorithm.
- */
- final static class BulkCipher {
-
- // Map BulkCipher -> Boolean(available)
- private final static Map<BulkCipher,Boolean> availableCache =
- new HashMap<>(8);
-
- // descriptive name including key size, e.g. AES/128
- final String description;
-
- // JCE cipher transformation string, e.g. AES/CBC/NoPadding
- final String transformation;
-
- // algorithm name, e.g. AES
- final String algorithm;
-
- // supported and compile time enabled. Also see isAvailable()
- final boolean allowed;
-
- // number of bytes of entropy in the key
- final int keySize;
-
- // length of the actual cipher key in bytes.
- // for non-exportable ciphers, this is the same as keySize
- final int expandedKeySize;
-
- // size of the IV (also block size)
- final int ivSize;
-
- // exportable under 512/40 bit rules
- final boolean exportable;
-
- // Is the cipher algorithm of Cipher Block Chaining (CBC) mode?
- final boolean isCBCMode;
-
- BulkCipher(String transformation, int keySize,
- int expandedKeySize, int ivSize, boolean allowed) {
- this.transformation = transformation;
- String[] splits = transformation.split("/");
- this.algorithm = splits[0];
- this.isCBCMode =
- splits.length <= 1 ? false : "CBC".equalsIgnoreCase(splits[1]);
- this.description = this.algorithm + "/" + (keySize << 3);
- this.keySize = keySize;
- this.ivSize = ivSize;
- this.allowed = allowed;
-
- this.expandedKeySize = expandedKeySize;
- this.exportable = true;
- }
-
- BulkCipher(String transformation, int keySize,
- int ivSize, boolean allowed) {
- this.transformation = transformation;
- String[] splits = transformation.split("/");
- this.algorithm = splits[0];
- this.isCBCMode =
- splits.length <= 1 ? false : "CBC".equalsIgnoreCase(splits[1]);
- this.description = this.algorithm + "/" + (keySize << 3);
- this.keySize = keySize;
- this.ivSize = ivSize;
- this.allowed = allowed;
-
- this.expandedKeySize = keySize;
- this.exportable = false;
- }
-
- /**
- * Return an initialized CipherBox for this BulkCipher.
- * IV must be null for stream ciphers.
- *
- * @exception NoSuchAlgorithmException if anything goes wrong
- */
- CipherBox newCipher(ProtocolVersion version, SecretKey key,
- IvParameterSpec iv, SecureRandom random,
- boolean encrypt) throws NoSuchAlgorithmException {
- return CipherBox.newCipherBox(version, this,
- key, iv, random, encrypt);
- }
-
- /**
- * Test if this bulk cipher is available. For use by CipherSuite.
- *
- * Currently all supported ciphers except AES are always available
- * via the JSSE internal implementations. We also assume AES/128
- * is always available since it is shipped with the SunJCE provider.
- * However, AES/256 is unavailable when the default JCE policy
- * jurisdiction files are installed because of key length restrictions.
- */
- boolean isAvailable() {
- if (allowed == false) {
- return false;
- }
- if (this == B_AES_256) {
- return isAvailable(this);
- }
-
- // always available
- return true;
- }
-
- // for use by CipherSuiteList.clearAvailableCache();
- static synchronized void clearAvailableCache() {
- if (DYNAMIC_AVAILABILITY) {
- availableCache.clear();
- }
- }
-
- private static synchronized boolean isAvailable(BulkCipher cipher) {
- Boolean b = availableCache.get(cipher);
- if (b == null) {
- try {
- SecretKey key = new SecretKeySpec
- (new byte[cipher.expandedKeySize], cipher.algorithm);
- IvParameterSpec iv =
- new IvParameterSpec(new byte[cipher.ivSize]);
- cipher.newCipher(ProtocolVersion.DEFAULT,
- key, iv, null, true);
- b = Boolean.TRUE;
- } catch (NoSuchAlgorithmException e) {
- b = Boolean.FALSE;
- }
- availableCache.put(cipher, b);
- }
- return b.booleanValue();
- }
-
- public String toString() {
- return description;
- }
- }
-
- /**
- * An SSL/TLS key MAC algorithm.
- *
- * Also contains a factory method to obtain an initialized MAC
- * for this algorithm.
- */
- final static class MacAlg {
-
- // descriptive name, e.g. MD5
- final String name;
-
- // size of the MAC value (and MAC key) in bytes
- final int size;
-
- // block size of the underlying hash algorithm
- final int hashBlockSize;
-
- // minimal padding size of the underlying hash algorithm
- final int minimalPaddingSize;
-
- MacAlg(String name, int size,
- int hashBlockSize, int minimalPaddingSize) {
- this.name = name;
- this.size = size;
- this.hashBlockSize = hashBlockSize;
- this.minimalPaddingSize = minimalPaddingSize;
- }
-
- /**
- * Return an initialized MAC for this MacAlg. ProtocolVersion
- * must either be SSL30 (SSLv3 custom MAC) or TLS10 (std. HMAC).
- *
- * @exception NoSuchAlgorithmException if anything goes wrong
- */
- MAC newMac(ProtocolVersion protocolVersion, SecretKey secret)
- throws NoSuchAlgorithmException, InvalidKeyException {
- return new MAC(this, protocolVersion, secret);
- }
-
- public String toString() {
- return name;
- }
- }
-
- // export strength ciphers
- final static BulkCipher B_NULL =
- new BulkCipher("NULL", 0, 0, 0, true);
- final static BulkCipher B_RC4_40 =
- new BulkCipher(CIPHER_RC4, 5, 16, 0, true);
- final static BulkCipher B_RC2_40 =
- new BulkCipher("RC2", 5, 16, 8, false);
- final static BulkCipher B_DES_40 =
- new BulkCipher(CIPHER_DES, 5, 8, 8, true);
-
- // domestic strength ciphers
- final static BulkCipher B_RC4_128 =
- new BulkCipher(CIPHER_RC4, 16, 0, true);
- final static BulkCipher B_DES =
- new BulkCipher(CIPHER_DES, 8, 8, true);
- final static BulkCipher B_3DES =
- new BulkCipher(CIPHER_3DES, 24, 8, true);
- final static BulkCipher B_IDEA =
- new BulkCipher("IDEA", 16, 8, false);
- final static BulkCipher B_AES_128 =
- new BulkCipher(CIPHER_AES, 16, 16, true);
- final static BulkCipher B_AES_256 =
- new BulkCipher(CIPHER_AES, 32, 16, true);
-
- // MACs
- final static MacAlg M_NULL = new MacAlg("NULL", 0, 0, 0);
- final static MacAlg M_MD5 = new MacAlg("MD5", 16, 64, 9);
- final static MacAlg M_SHA = new MacAlg("SHA", 20, 64, 9);
- final static MacAlg M_SHA256 = new MacAlg("SHA256", 32, 64, 9);
- final static MacAlg M_SHA384 = new MacAlg("SHA384", 48, 128, 17);
-
- /**
- * PRFs (PseudoRandom Function) from TLS specifications.
- *
- * TLS 1.1- uses a single MD5/SHA1-based PRF algorithm for generating
- * the necessary material.
- *
- * In TLS 1.2+, all existing/known CipherSuites use SHA256, however
- * new Ciphersuites (e.g. RFC 5288) can define specific PRF hash
- * algorithms.
- */
- static enum PRF {
-
- // PRF algorithms
- P_NONE( "NONE", 0, 0),
- P_SHA256("SHA-256", 32, 64),
- P_SHA384("SHA-384", 48, 128),
- P_SHA512("SHA-512", 64, 128); // not currently used.
-
- // PRF characteristics
- private final String prfHashAlg;
- private final int prfHashLength;
- private final int prfBlockSize;
-
- PRF(String prfHashAlg, int prfHashLength, int prfBlockSize) {
- this.prfHashAlg = prfHashAlg;
- this.prfHashLength = prfHashLength;
- this.prfBlockSize = prfBlockSize;
- }
-
- String getPRFHashAlg() {
- return prfHashAlg;
- }
-
- int getPRFHashLength() {
- return prfHashLength;
- }
-
- int getPRFBlockSize() {
- return prfBlockSize;
- }
- }
-
- static {
- idMap = new HashMap<Integer,CipherSuite>();
- nameMap = new HashMap<String,CipherSuite>();
-
- final boolean F = false;
- final boolean T = true;
- // N: ciphersuites only allowed if we are not in FIPS mode
- final boolean N = (SunJSSE.isFIPS() == false);
-
- /*
- * TLS Cipher Suite Registry, as of August 2010.
- *
- * http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
- *
- * Range Registration Procedures Notes
- * 000-191 Standards Action Refers to value of first byte
- * 192-254 Specification Required Refers to value of first byte
- * 255 Reserved for Private Use Refers to value of first byte
- *
- * Value Description Reference
- * 0x00,0x00 TLS_NULL_WITH_NULL_NULL [RFC5246]
- * 0x00,0x01 TLS_RSA_WITH_NULL_MD5 [RFC5246]
- * 0x00,0x02 TLS_RSA_WITH_NULL_SHA [RFC5246]
- * 0x00,0x03 TLS_RSA_EXPORT_WITH_RC4_40_MD5 [RFC4346]
- * 0x00,0x04 TLS_RSA_WITH_RC4_128_MD5 [RFC5246]
- * 0x00,0x05 TLS_RSA_WITH_RC4_128_SHA [RFC5246]
- * 0x00,0x06 TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 [RFC4346]
- * 0x00,0x07 TLS_RSA_WITH_IDEA_CBC_SHA [RFC5469]
- * 0x00,0x08 TLS_RSA_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
- * 0x00,0x09 TLS_RSA_WITH_DES_CBC_SHA [RFC5469]
- * 0x00,0x0A TLS_RSA_WITH_3DES_EDE_CBC_SHA [RFC5246]
- * 0x00,0x0B TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
- * 0x00,0x0C TLS_DH_DSS_WITH_DES_CBC_SHA [RFC5469]
- * 0x00,0x0D TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA [RFC5246]
- * 0x00,0x0E TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
- * 0x00,0x0F TLS_DH_RSA_WITH_DES_CBC_SHA [RFC5469]
- * 0x00,0x10 TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA [RFC5246]
- * 0x00,0x11 TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
- * 0x00,0x12 TLS_DHE_DSS_WITH_DES_CBC_SHA [RFC5469]
- * 0x00,0x13 TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA [RFC5246]
- * 0x00,0x14 TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
- * 0x00,0x15 TLS_DHE_RSA_WITH_DES_CBC_SHA [RFC5469]
- * 0x00,0x16 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA [RFC5246]
- * 0x00,0x17 TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 [RFC4346]
- * 0x00,0x18 TLS_DH_anon_WITH_RC4_128_MD5 [RFC5246]
- * 0x00,0x19 TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA [RFC4346]
- * 0x00,0x1A TLS_DH_anon_WITH_DES_CBC_SHA [RFC5469]
- * 0x00,0x1B TLS_DH_anon_WITH_3DES_EDE_CBC_SHA [RFC5246]
- * 0x00,0x1C-1D Reserved to avoid conflicts with SSLv3 [RFC5246]
- * 0x00,0x1E TLS_KRB5_WITH_DES_CBC_SHA [RFC2712]
- * 0x00,0x1F TLS_KRB5_WITH_3DES_EDE_CBC_SHA [RFC2712]
- * 0x00,0x20 TLS_KRB5_WITH_RC4_128_SHA [RFC2712]
- * 0x00,0x21 TLS_KRB5_WITH_IDEA_CBC_SHA [RFC2712]
- * 0x00,0x22 TLS_KRB5_WITH_DES_CBC_MD5 [RFC2712]
- * 0x00,0x23 TLS_KRB5_WITH_3DES_EDE_CBC_MD5 [RFC2712]
- * 0x00,0x24 TLS_KRB5_WITH_RC4_128_MD5 [RFC2712]
- * 0x00,0x25 TLS_KRB5_WITH_IDEA_CBC_MD5 [RFC2712]
- * 0x00,0x26 TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA [RFC2712]
- * 0x00,0x27 TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA [RFC2712]
- * 0x00,0x28 TLS_KRB5_EXPORT_WITH_RC4_40_SHA [RFC2712]
- * 0x00,0x29 TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 [RFC2712]
- * 0x00,0x2A TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 [RFC2712]
- * 0x00,0x2B TLS_KRB5_EXPORT_WITH_RC4_40_MD5 [RFC2712]
- * 0x00,0x2C TLS_PSK_WITH_NULL_SHA [RFC4785]
- * 0x00,0x2D TLS_DHE_PSK_WITH_NULL_SHA [RFC4785]
- * 0x00,0x2E TLS_RSA_PSK_WITH_NULL_SHA [RFC4785]
- * 0x00,0x2F TLS_RSA_WITH_AES_128_CBC_SHA [RFC5246]
- * 0x00,0x30 TLS_DH_DSS_WITH_AES_128_CBC_SHA [RFC5246]
- * 0x00,0x31 TLS_DH_RSA_WITH_AES_128_CBC_SHA [RFC5246]
- * 0x00,0x32 TLS_DHE_DSS_WITH_AES_128_CBC_SHA [RFC5246]
- * 0x00,0x33 TLS_DHE_RSA_WITH_AES_128_CBC_SHA [RFC5246]
- * 0x00,0x34 TLS_DH_anon_WITH_AES_128_CBC_SHA [RFC5246]
- * 0x00,0x35 TLS_RSA_WITH_AES_256_CBC_SHA [RFC5246]
- * 0x00,0x36 TLS_DH_DSS_WITH_AES_256_CBC_SHA [RFC5246]
- * 0x00,0x37 TLS_DH_RSA_WITH_AES_256_CBC_SHA [RFC5246]
- * 0x00,0x38 TLS_DHE_DSS_WITH_AES_256_CBC_SHA [RFC5246]
- * 0x00,0x39 TLS_DHE_RSA_WITH_AES_256_CBC_SHA [RFC5246]
- * 0x00,0x3A TLS_DH_anon_WITH_AES_256_CBC_SHA [RFC5246]
- * 0x00,0x3B TLS_RSA_WITH_NULL_SHA256 [RFC5246]
- * 0x00,0x3C TLS_RSA_WITH_AES_128_CBC_SHA256 [RFC5246]
- * 0x00,0x3D TLS_RSA_WITH_AES_256_CBC_SHA256 [RFC5246]
- * 0x00,0x3E TLS_DH_DSS_WITH_AES_128_CBC_SHA256 [RFC5246]
- * 0x00,0x3F TLS_DH_RSA_WITH_AES_128_CBC_SHA256 [RFC5246]
- * 0x00,0x40 TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 [RFC5246]
- * 0x00,0x41 TLS_RSA_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
- * 0x00,0x42 TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
- * 0x00,0x43 TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
- * 0x00,0x44 TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
- * 0x00,0x45 TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
- * 0x00,0x46 TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA [RFC5932]
- * 0x00,0x47-4F Reserved to avoid conflicts with
- * deployed implementations [Pasi_Eronen]
- * 0x00,0x50-58 Reserved to avoid conflicts [Pasi Eronen]
- * 0x00,0x59-5C Reserved to avoid conflicts with
- * deployed implementations [Pasi_Eronen]
- * 0x00,0x5D-5F Unassigned
- * 0x00,0x60-66 Reserved to avoid conflicts with widely
- * deployed implementations [Pasi_Eronen]
- * 0x00,0x67 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 [RFC5246]
- * 0x00,0x68 TLS_DH_DSS_WITH_AES_256_CBC_SHA256 [RFC5246]
- * 0x00,0x69 TLS_DH_RSA_WITH_AES_256_CBC_SHA256 [RFC5246]
- * 0x00,0x6A TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 [RFC5246]
- * 0x00,0x6B TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 [RFC5246]
- * 0x00,0x6C TLS_DH_anon_WITH_AES_128_CBC_SHA256 [RFC5246]
- * 0x00,0x6D TLS_DH_anon_WITH_AES_256_CBC_SHA256 [RFC5246]
- * 0x00,0x6E-83 Unassigned
- * 0x00,0x84 TLS_RSA_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
- * 0x00,0x85 TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
- * 0x00,0x86 TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
- * 0x00,0x87 TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
- * 0x00,0x88 TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
- * 0x00,0x89 TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA [RFC5932]
- * 0x00,0x8A TLS_PSK_WITH_RC4_128_SHA [RFC4279]
- * 0x00,0x8B TLS_PSK_WITH_3DES_EDE_CBC_SHA [RFC4279]
- * 0x00,0x8C TLS_PSK_WITH_AES_128_CBC_SHA [RFC4279]
- * 0x00,0x8D TLS_PSK_WITH_AES_256_CBC_SHA [RFC4279]
- * 0x00,0x8E TLS_DHE_PSK_WITH_RC4_128_SHA [RFC4279]
- * 0x00,0x8F TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA [RFC4279]
- * 0x00,0x90 TLS_DHE_PSK_WITH_AES_128_CBC_SHA [RFC4279]
- * 0x00,0x91 TLS_DHE_PSK_WITH_AES_256_CBC_SHA [RFC4279]
- * 0x00,0x92 TLS_RSA_PSK_WITH_RC4_128_SHA [RFC4279]
- * 0x00,0x93 TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA [RFC4279]
- * 0x00,0x94 TLS_RSA_PSK_WITH_AES_128_CBC_SHA [RFC4279]
- * 0x00,0x95 TLS_RSA_PSK_WITH_AES_256_CBC_SHA [RFC4279]
- * 0x00,0x96 TLS_RSA_WITH_SEED_CBC_SHA [RFC4162]
- * 0x00,0x97 TLS_DH_DSS_WITH_SEED_CBC_SHA [RFC4162]
- * 0x00,0x98 TLS_DH_RSA_WITH_SEED_CBC_SHA [RFC4162]
- * 0x00,0x99 TLS_DHE_DSS_WITH_SEED_CBC_SHA [RFC4162]
- * 0x00,0x9A TLS_DHE_RSA_WITH_SEED_CBC_SHA [RFC4162]
- * 0x00,0x9B TLS_DH_anon_WITH_SEED_CBC_SHA [RFC4162]
- * 0x00,0x9C TLS_RSA_WITH_AES_128_GCM_SHA256 [RFC5288]
- * 0x00,0x9D TLS_RSA_WITH_AES_256_GCM_SHA384 [RFC5288]
- * 0x00,0x9E TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 [RFC5288]
- * 0x00,0x9F TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 [RFC5288]
- * 0x00,0xA0 TLS_DH_RSA_WITH_AES_128_GCM_SHA256 [RFC5288]
- * 0x00,0xA1 TLS_DH_RSA_WITH_AES_256_GCM_SHA384 [RFC5288]
- * 0x00,0xA2 TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 [RFC5288]
- * 0x00,0xA3 TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 [RFC5288]
- * 0x00,0xA4 TLS_DH_DSS_WITH_AES_128_GCM_SHA256 [RFC5288]
- * 0x00,0xA5 TLS_DH_DSS_WITH_AES_256_GCM_SHA384 [RFC5288]
- * 0x00,0xA6 TLS_DH_anon_WITH_AES_128_GCM_SHA256 [RFC5288]
- * 0x00,0xA7 TLS_DH_anon_WITH_AES_256_GCM_SHA384 [RFC5288]
- * 0x00,0xA8 TLS_PSK_WITH_AES_128_GCM_SHA256 [RFC5487]
- * 0x00,0xA9 TLS_PSK_WITH_AES_256_GCM_SHA384 [RFC5487]
- * 0x00,0xAA TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 [RFC5487]
- * 0x00,0xAB TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 [RFC5487]
- * 0x00,0xAC TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 [RFC5487]
- * 0x00,0xAD TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 [RFC5487]
- * 0x00,0xAE TLS_PSK_WITH_AES_128_CBC_SHA256 [RFC5487]
- * 0x00,0xAF TLS_PSK_WITH_AES_256_CBC_SHA384 [RFC5487]
- * 0x00,0xB0 TLS_PSK_WITH_NULL_SHA256 [RFC5487]
- * 0x00,0xB1 TLS_PSK_WITH_NULL_SHA384 [RFC5487]
- * 0x00,0xB2 TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 [RFC5487]
- * 0x00,0xB3 TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 [RFC5487]
- * 0x00,0xB4 TLS_DHE_PSK_WITH_NULL_SHA256 [RFC5487]
- * 0x00,0xB5 TLS_DHE_PSK_WITH_NULL_SHA384 [RFC5487]
- * 0x00,0xB6 TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 [RFC5487]
- * 0x00,0xB7 TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 [RFC5487]
- * 0x00,0xB8 TLS_RSA_PSK_WITH_NULL_SHA256 [RFC5487]
- * 0x00,0xB9 TLS_RSA_PSK_WITH_NULL_SHA384 [RFC5487]
- * 0x00,0xBA TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
- * 0x00,0xBB TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
- * 0x00,0xBC TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
- * 0x00,0xBD TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
- * 0x00,0xBE TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
- * 0x00,0xBF TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 [RFC5932]
- * 0x00,0xC0 TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
- * 0x00,0xC1 TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
- * 0x00,0xC2 TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
- * 0x00,0xC3 TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
- * 0x00,0xC4 TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
- * 0x00,0xC5 TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 [RFC5932]
- * 0x00,0xC6-FE Unassigned
- * 0x00,0xFF TLS_EMPTY_RENEGOTIATION_INFO_SCSV [RFC5746]
- * 0x01-BF,* Unassigned
- * 0xC0,0x01 TLS_ECDH_ECDSA_WITH_NULL_SHA [RFC4492]
- * 0xC0,0x02 TLS_ECDH_ECDSA_WITH_RC4_128_SHA [RFC4492]
- * 0xC0,0x03 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA [RFC4492]
- * 0xC0,0x04 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA [RFC4492]
- * 0xC0,0x05 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA [RFC4492]
- * 0xC0,0x06 TLS_ECDHE_ECDSA_WITH_NULL_SHA [RFC4492]
- * 0xC0,0x07 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA [RFC4492]
- * 0xC0,0x08 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA [RFC4492]
- * 0xC0,0x09 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA [RFC4492]
- * 0xC0,0x0A TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA [RFC4492]
- * 0xC0,0x0B TLS_ECDH_RSA_WITH_NULL_SHA [RFC4492]
- * 0xC0,0x0C TLS_ECDH_RSA_WITH_RC4_128_SHA [RFC4492]
- * 0xC0,0x0D TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA [RFC4492]
- * 0xC0,0x0E TLS_ECDH_RSA_WITH_AES_128_CBC_SHA [RFC4492]
- * 0xC0,0x0F TLS_ECDH_RSA_WITH_AES_256_CBC_SHA [RFC4492]
- * 0xC0,0x10 TLS_ECDHE_RSA_WITH_NULL_SHA [RFC4492]
- * 0xC0,0x11 TLS_ECDHE_RSA_WITH_RC4_128_SHA [RFC4492]
- * 0xC0,0x12 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA [RFC4492]
- * 0xC0,0x13 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA [RFC4492]
- * 0xC0,0x14 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA [RFC4492]
- * 0xC0,0x15 TLS_ECDH_anon_WITH_NULL_SHA [RFC4492]
- * 0xC0,0x16 TLS_ECDH_anon_WITH_RC4_128_SHA [RFC4492]
- * 0xC0,0x17 TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA [RFC4492]
- * 0xC0,0x18 TLS_ECDH_anon_WITH_AES_128_CBC_SHA [RFC4492]
- * 0xC0,0x19 TLS_ECDH_anon_WITH_AES_256_CBC_SHA [RFC4492]
- * 0xC0,0x1A TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA [RFC5054]
- * 0xC0,0x1B TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA [RFC5054]
- * 0xC0,0x1C TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA [RFC5054]
- * 0xC0,0x1D TLS_SRP_SHA_WITH_AES_128_CBC_SHA [RFC5054]
- * 0xC0,0x1E TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA [RFC5054]
- * 0xC0,0x1F TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA [RFC5054]
- * 0xC0,0x20 TLS_SRP_SHA_WITH_AES_256_CBC_SHA [RFC5054]
- * 0xC0,0x21 TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA [RFC5054]
- * 0xC0,0x22 TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA [RFC5054]
- * 0xC0,0x23 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 [RFC5289]
- * 0xC0,0x24 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 [RFC5289]
- * 0xC0,0x25 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 [RFC5289]
- * 0xC0,0x26 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 [RFC5289]
- * 0xC0,0x27 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 [RFC5289]
- * 0xC0,0x28 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 [RFC5289]
- * 0xC0,0x29 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 [RFC5289]
- * 0xC0,0x2A TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 [RFC5289]
- * 0xC0,0x2B TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 [RFC5289]
- * 0xC0,0x2C TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 [RFC5289]
- * 0xC0,0x2D TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 [RFC5289]
- * 0xC0,0x2E TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 [RFC5289]
- * 0xC0,0x2F TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [RFC5289]
- * 0xC0,0x30 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 [RFC5289]
- * 0xC0,0x31 TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 [RFC5289]
- * 0xC0,0x32 TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 [RFC5289]
- * 0xC0,0x33 TLS_ECDHE_PSK_WITH_RC4_128_SHA [RFC5489]
- * 0xC0,0x34 TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA [RFC5489]
- * 0xC0,0x35 TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA [RFC5489]
- * 0xC0,0x36 TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA [RFC5489]
- * 0xC0,0x37 TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 [RFC5489]
- * 0xC0,0x38 TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 [RFC5489]
- * 0xC0,0x39 TLS_ECDHE_PSK_WITH_NULL_SHA [RFC5489]
- * 0xC0,0x3A TLS_ECDHE_PSK_WITH_NULL_SHA256 [RFC5489]
- * 0xC0,0x3B TLS_ECDHE_PSK_WITH_NULL_SHA384 [RFC5489]
- * 0xC0,0x3C-FF Unassigned
- * 0xC1-FD,* Unassigned
- * 0xFE,0x00-FD Unassigned
- * 0xFE,0xFE-FF Reserved to avoid conflicts with widely
- * deployed implementations [Pasi_Eronen]
- * 0xFF,0x00-FF Reserved for Private Use [RFC5246]
- */
-
- add("SSL_NULL_WITH_NULL_NULL",
- 0x0000, 1, K_NULL, B_NULL, F);
-
- /*
- * Definition of the CipherSuites that are enabled by default.
- * They are listed in preference order, most preferred first, using
- * the following criteria:
- * 1. Prefer the stronger buld cipher, in the order of AES_256,
- * AES_128, RC-4, 3DES-EDE.
- * 2. Prefer the stronger MAC algorithm, in the order of SHA384,
- * SHA256, SHA, MD5.
- * 3. Prefer the better performance of key exchange and digital
- * signature algorithm, in the order of ECDHE-ECDSA, ECDHE-RSA,
- * RSA, ECDH-ECDSA, ECDH-RSA, DHE-RSA, DHE-DSS.
- */
- int p = DEFAULT_SUITES_PRIORITY * 2;
-
- // shorten names to fit the following table cleanly.
- int max = ProtocolVersion.LIMIT_MAX_VALUE;
- int tls11 = ProtocolVersion.TLS11.v;
- int tls12 = ProtocolVersion.TLS12.v;
-
- // ID Key Exchange Cipher A obs suprt PRF
- // ====== ============ ========= = === ===== ========
- add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
- 0xc024, --p, K_ECDHE_ECDSA, B_AES_256, T, max, tls12, P_SHA384);
- add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
- 0xc028, --p, K_ECDHE_RSA, B_AES_256, T, max, tls12, P_SHA384);
- add("TLS_RSA_WITH_AES_256_CBC_SHA256",
- 0x003d, --p, K_RSA, B_AES_256, T, max, tls12, P_SHA256);
- add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",
- 0xc026, --p, K_ECDH_ECDSA, B_AES_256, T, max, tls12, P_SHA384);
- add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",
- 0xc02a, --p, K_ECDH_RSA, B_AES_256, T, max, tls12, P_SHA384);
- add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",
- 0x006b, --p, K_DHE_RSA, B_AES_256, T, max, tls12, P_SHA256);
- add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
- 0x006a, --p, K_DHE_DSS, B_AES_256, T, max, tls12, P_SHA256);
-
- add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
- 0xC00A, --p, K_ECDHE_ECDSA, B_AES_256, T);
- add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
- 0xC014, --p, K_ECDHE_RSA, B_AES_256, T);
- add("TLS_RSA_WITH_AES_256_CBC_SHA",
- 0x0035, --p, K_RSA, B_AES_256, T);
- add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
- 0xC005, --p, K_ECDH_ECDSA, B_AES_256, T);
- add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
- 0xC00F, --p, K_ECDH_RSA, B_AES_256, T);
- add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
- 0x0039, --p, K_DHE_RSA, B_AES_256, T);
- add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
- 0x0038, --p, K_DHE_DSS, B_AES_256, T);
-
- add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
- 0xc023, --p, K_ECDHE_ECDSA, B_AES_128, T, max, tls12, P_SHA256);
- add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
- 0xc027, --p, K_ECDHE_RSA, B_AES_128, T, max, tls12, P_SHA256);
- add("TLS_RSA_WITH_AES_128_CBC_SHA256",
- 0x003c, --p, K_RSA, B_AES_128, T, max, tls12, P_SHA256);
- add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",
- 0xc025, --p, K_ECDH_ECDSA, B_AES_128, T, max, tls12, P_SHA256);
- add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",
- 0xc029, --p, K_ECDH_RSA, B_AES_128, T, max, tls12, P_SHA256);
- add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",
- 0x0067, --p, K_DHE_RSA, B_AES_128, T, max, tls12, P_SHA256);
- add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA256",
- 0x0040, --p, K_DHE_DSS, B_AES_128, T, max, tls12, P_SHA256);
-
- add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
- 0xC009, --p, K_ECDHE_ECDSA, B_AES_128, T);
- add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
- 0xC013, --p, K_ECDHE_RSA, B_AES_128, T);
- add("TLS_RSA_WITH_AES_128_CBC_SHA",
- 0x002f, --p, K_RSA, B_AES_128, T);
- add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
- 0xC004, --p, K_ECDH_ECDSA, B_AES_128, T);
- add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
- 0xC00E, --p, K_ECDH_RSA, B_AES_128, T);
- add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
- 0x0033, --p, K_DHE_RSA, B_AES_128, T);
- add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
- 0x0032, --p, K_DHE_DSS, B_AES_128, T);
-
- add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
- 0xC007, --p, K_ECDHE_ECDSA, B_RC4_128, N);
- add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",
- 0xC011, --p, K_ECDHE_RSA, B_RC4_128, N);
- add("SSL_RSA_WITH_RC4_128_SHA",
- 0x0005, --p, K_RSA, B_RC4_128, N);
- add("TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
- 0xC002, --p, K_ECDH_ECDSA, B_RC4_128, N);
- add("TLS_ECDH_RSA_WITH_RC4_128_SHA",
- 0xC00C, --p, K_ECDH_RSA, B_RC4_128, N);
-
- add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
- 0xC008, --p, K_ECDHE_ECDSA, B_3DES, T);
- add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
- 0xC012, --p, K_ECDHE_RSA, B_3DES, T);
- add("SSL_RSA_WITH_3DES_EDE_CBC_SHA",
- 0x000a, --p, K_RSA, B_3DES, T);
- add("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
- 0xC003, --p, K_ECDH_ECDSA, B_3DES, T);
- add("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
- 0xC00D, --p, K_ECDH_RSA, B_3DES, T);
- add("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
- 0x0016, --p, K_DHE_RSA, B_3DES, T);
- add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
- 0x0013, --p, K_DHE_DSS, B_3DES, N);
-
- add("SSL_RSA_WITH_RC4_128_MD5",
- 0x0004, --p, K_RSA, B_RC4_128, N);
-
- // Renegotiation protection request Signalling Cipher Suite Value (SCSV)
- add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
- 0x00ff, --p, K_SCSV, B_NULL, T);
-
- /*
- * Definition of the CipherSuites that are supported but not enabled
- * by default.
- * They are listed in preference order, preferred first, using the
- * following criteria:
- * 1. CipherSuites for KRB5 need additional KRB5 service
- * configuration, and these suites are not common in practice,
- * so we put KRB5 based cipher suites at the end of the supported
- * list.
- * 2. If a cipher suite has been obsoleted, we put it at the end of
- * the list.
- * 3. Prefer the stronger bulk cipher, in the order of AES_256,
- * AES_128, RC-4, 3DES-EDE, DES, RC4_40, DES40, NULL.
- * 4. Prefer the stronger MAC algorithm, in the order of SHA384,
- * SHA256, SHA, MD5.
- * 5. Prefer the better performance of key exchange and digital
- * signature algorithm, in the order of ECDHE-ECDSA, ECDHE-RSA,
- * RSA, ECDH-ECDSA, ECDH-RSA, DHE-RSA, DHE-DSS, anonymous.
- */
- p = DEFAULT_SUITES_PRIORITY;
-
- add("TLS_DH_anon_WITH_AES_256_CBC_SHA256",
- 0x006d, --p, K_DH_ANON, B_AES_256, N, max, tls12, P_SHA256);
- add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
- 0xC019, --p, K_ECDH_ANON, B_AES_256, T);
- add("TLS_DH_anon_WITH_AES_256_CBC_SHA",
- 0x003a, --p, K_DH_ANON, B_AES_256, N);
-
- add("TLS_DH_anon_WITH_AES_128_CBC_SHA256",
- 0x006c, --p, K_DH_ANON, B_AES_128, N, max, tls12, P_SHA256);
- add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
- 0xC018, --p, K_ECDH_ANON, B_AES_128, T);
- add("TLS_DH_anon_WITH_AES_128_CBC_SHA",
- 0x0034, --p, K_DH_ANON, B_AES_128, N);
-
- add("TLS_ECDH_anon_WITH_RC4_128_SHA",
- 0xC016, --p, K_ECDH_ANON, B_RC4_128, N);
- add("SSL_DH_anon_WITH_RC4_128_MD5",
- 0x0018, --p, K_DH_ANON, B_RC4_128, N);
-
- add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
- 0xC017, --p, K_ECDH_ANON, B_3DES, T);
- add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",
- 0x001b, --p, K_DH_ANON, B_3DES, N);
-
- add("TLS_RSA_WITH_NULL_SHA256",
- 0x003b, --p, K_RSA, B_NULL, N, max, tls12, P_SHA256);
- add("TLS_ECDHE_ECDSA_WITH_NULL_SHA",
- 0xC006, --p, K_ECDHE_ECDSA, B_NULL, N);
- add("TLS_ECDHE_RSA_WITH_NULL_SHA",
- 0xC010, --p, K_ECDHE_RSA, B_NULL, N);
- add("SSL_RSA_WITH_NULL_SHA",
- 0x0002, --p, K_RSA, B_NULL, N);
- add("TLS_ECDH_ECDSA_WITH_NULL_SHA",
- 0xC001, --p, K_ECDH_ECDSA, B_NULL, N);
- add("TLS_ECDH_RSA_WITH_NULL_SHA",
- 0xC00B, --p, K_ECDH_RSA, B_NULL, N);
- add("TLS_ECDH_anon_WITH_NULL_SHA",
- 0xC015, --p, K_ECDH_ANON, B_NULL, N);
- add("SSL_RSA_WITH_NULL_MD5",
- 0x0001, --p, K_RSA, B_NULL, N);
-
- // weak cipher suites obsoleted in TLS 1.2
- add("SSL_RSA_WITH_DES_CBC_SHA",
- 0x0009, --p, K_RSA, B_DES, N, tls12);
- add("SSL_DHE_RSA_WITH_DES_CBC_SHA",
- 0x0015, --p, K_DHE_RSA, B_DES, N, tls12);
- add("SSL_DHE_DSS_WITH_DES_CBC_SHA",
- 0x0012, --p, K_DHE_DSS, B_DES, N, tls12);
- add("SSL_DH_anon_WITH_DES_CBC_SHA",
- 0x001a, --p, K_DH_ANON, B_DES, N, tls12);
-
- // weak cipher suites obsoleted in TLS 1.1
- add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",
- 0x0003, --p, K_RSA_EXPORT, B_RC4_40, N, tls11);
- add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",
- 0x0017, --p, K_DH_ANON, B_RC4_40, N, tls11);
-
- add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
- 0x0008, --p, K_RSA_EXPORT, B_DES_40, N, tls11);
- add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
- 0x0014, --p, K_DHE_RSA, B_DES_40, N, tls11);
- add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA",
- 0x0011, --p, K_DHE_DSS, B_DES_40, N, tls11);
- add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA",
- 0x0019, --p, K_DH_ANON, B_DES_40, N, tls11);
-
- // Supported Kerberos ciphersuites from RFC2712
- add("TLS_KRB5_WITH_RC4_128_SHA",
- 0x0020, --p, K_KRB5, B_RC4_128, N);
- add("TLS_KRB5_WITH_RC4_128_MD5",
- 0x0024, --p, K_KRB5, B_RC4_128, N);
- add("TLS_KRB5_WITH_3DES_EDE_CBC_SHA",
- 0x001f, --p, K_KRB5, B_3DES, N);
- add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5",
- 0x0023, --p, K_KRB5, B_3DES, N);
- add("TLS_KRB5_WITH_DES_CBC_SHA",
- 0x001e, --p, K_KRB5, B_DES, N, tls12);
- add("TLS_KRB5_WITH_DES_CBC_MD5",
- 0x0022, --p, K_KRB5, B_DES, N, tls12);
- add("TLS_KRB5_EXPORT_WITH_RC4_40_SHA",
- 0x0028, --p, K_KRB5_EXPORT, B_RC4_40, N, tls11);
- add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5",
- 0x002b, --p, K_KRB5_EXPORT, B_RC4_40, N, tls11);
- add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA",
- 0x0026, --p, K_KRB5_EXPORT, B_DES_40, N, tls11);
- add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5",
- 0x0029, --p, K_KRB5_EXPORT, B_DES_40, N, tls11);
-
- /*
- * Other values from the TLS Cipher Suite Registry, as of August 2010.
- *
- * http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
- *
- * Range Registration Procedures Notes
- * 000-191 Standards Action Refers to value of first byte
- * 192-254 Specification Required Refers to value of first byte
- * 255 Reserved for Private Use Refers to value of first byte
- */
-
- // Register the names of a few additional CipherSuites.
- // Makes them show up as names instead of numbers in
- // the debug output.
-
- // remaining unsupported ciphersuites defined in RFC2246.
- add("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5", 0x0006);
- add("SSL_RSA_WITH_IDEA_CBC_SHA", 0x0007);
- add("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", 0x000b);
- add("SSL_DH_DSS_WITH_DES_CBC_SHA", 0x000c);
- add("SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA", 0x000d);
- add("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", 0x000e);
- add("SSL_DH_RSA_WITH_DES_CBC_SHA", 0x000f);
- add("SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA", 0x0010);
-
- // SSL 3.0 Fortezza ciphersuites
- add("SSL_FORTEZZA_DMS_WITH_NULL_SHA", 0x001c);
- add("SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA", 0x001d);
-
- // 1024/56 bit exportable ciphersuites from expired internet draft
- add("SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA", 0x0062);
- add("SSL_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA", 0x0063);
- add("SSL_RSA_EXPORT1024_WITH_RC4_56_SHA", 0x0064);
- add("SSL_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA", 0x0065);
- add("SSL_DHE_DSS_WITH_RC4_128_SHA", 0x0066);
-
- // Netscape old and new SSL 3.0 FIPS ciphersuites
- // see http://www.mozilla.org/projects/security/pki/nss/ssl/fips-ssl-ciphersuites.html
- add("NETSCAPE_RSA_FIPS_WITH_3DES_EDE_CBC_SHA", 0xffe0);
- add("NETSCAPE_RSA_FIPS_WITH_DES_CBC_SHA", 0xffe1);
- add("SSL_RSA_FIPS_WITH_DES_CBC_SHA", 0xfefe);
- add("SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA", 0xfeff);
-
- // Unsupported Kerberos cipher suites from RFC 2712
- add("TLS_KRB5_WITH_IDEA_CBC_SHA", 0x0021);
- add("TLS_KRB5_WITH_IDEA_CBC_MD5", 0x0025);
- add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA", 0x0027);
- add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5", 0x002a);
-
- // Unsupported cipher suites from RFC 4162
- add("TLS_RSA_WITH_SEED_CBC_SHA", 0x0096);
- add("TLS_DH_DSS_WITH_SEED_CBC_SHA", 0x0097);
- add("TLS_DH_RSA_WITH_SEED_CBC_SHA", 0x0098);
- add("TLS_DHE_DSS_WITH_SEED_CBC_SHA", 0x0099);
- add("TLS_DHE_RSA_WITH_SEED_CBC_SHA", 0x009a);
- add("TLS_DH_anon_WITH_SEED_CBC_SHA", 0x009b);
-
- // Unsupported cipher suites from RFC 4279
- add("TLS_PSK_WITH_RC4_128_SHA", 0x008a);
- add("TLS_PSK_WITH_3DES_EDE_CBC_SHA", 0x008b);
- add("TLS_PSK_WITH_AES_128_CBC_SHA", 0x008c);
- add("TLS_PSK_WITH_AES_256_CBC_SHA", 0x008d);
- add("TLS_DHE_PSK_WITH_RC4_128_SHA", 0x008e);
- add("TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA", 0x008f);
- add("TLS_DHE_PSK_WITH_AES_128_CBC_SHA", 0x0090);
- add("TLS_DHE_PSK_WITH_AES_256_CBC_SHA", 0x0091);
- add("TLS_RSA_PSK_WITH_RC4_128_SHA", 0x0092);
- add("TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA", 0x0093);
- add("TLS_RSA_PSK_WITH_AES_128_CBC_SHA", 0x0094);
- add("TLS_RSA_PSK_WITH_AES_256_CBC_SHA", 0x0095);
-
- // Unsupported cipher suites from RFC 4785
- add("TLS_PSK_WITH_NULL_SHA", 0x002c);
- add("TLS_DHE_PSK_WITH_NULL_SHA", 0x002d);
- add("TLS_RSA_PSK_WITH_NULL_SHA", 0x002e);
-
- // Unsupported cipher suites from RFC 5246
- add("TLS_DH_DSS_WITH_AES_128_CBC_SHA", 0x0030);
- add("TLS_DH_RSA_WITH_AES_128_CBC_SHA", 0x0031);
- add("TLS_DH_DSS_WITH_AES_256_CBC_SHA", 0x0036);
- add("TLS_DH_RSA_WITH_AES_256_CBC_SHA", 0x0037);
- add("TLS_DH_DSS_WITH_AES_128_CBC_SHA256", 0x003e);
- add("TLS_DH_RSA_WITH_AES_128_CBC_SHA256", 0x003f);
- add("TLS_DH_DSS_WITH_AES_256_CBC_SHA256", 0x0068);
- add("TLS_DH_RSA_WITH_AES_256_CBC_SHA256", 0x0069);
-
- // Unsupported cipher suites from RFC 5288
- add("TLS_RSA_WITH_AES_128_GCM_SHA256", 0x009c);
- add("TLS_RSA_WITH_AES_256_GCM_SHA384", 0x009d);
- add("TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", 0x009e);
- add("TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", 0x009f);
- add("TLS_DH_RSA_WITH_AES_128_GCM_SHA256", 0x00a0);
- add("TLS_DH_RSA_WITH_AES_256_GCM_SHA384", 0x00a1);
- add("TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", 0x00a2);
- add("TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", 0x00a3);
- add("TLS_DH_DSS_WITH_AES_128_GCM_SHA256", 0x00a4);
- add("TLS_DH_DSS_WITH_AES_256_GCM_SHA384", 0x00a5);
- add("TLS_DH_anon_WITH_AES_128_GCM_SHA256", 0x00a6);
- add("TLS_DH_anon_WITH_AES_256_GCM_SHA384", 0x00a7);
-
- // Unsupported cipher suites from RFC 5487
- add("TLS_PSK_WITH_AES_128_GCM_SHA256", 0x00a8);
- add("TLS_PSK_WITH_AES_256_GCM_SHA384", 0x00a9);
- add("TLS_DHE_PSK_WITH_AES_128_GCM_SHA256", 0x00aa);
- add("TLS_DHE_PSK_WITH_AES_256_GCM_SHA384", 0x00ab);
- add("TLS_RSA_PSK_WITH_AES_128_GCM_SHA256", 0x00ac);
- add("TLS_RSA_PSK_WITH_AES_256_GCM_SHA384", 0x00ad);
- add("TLS_PSK_WITH_AES_128_CBC_SHA256", 0x00ae);
- add("TLS_PSK_WITH_AES_256_CBC_SHA384", 0x00af);
- add("TLS_PSK_WITH_NULL_SHA256", 0x00b0);
- add("TLS_PSK_WITH_NULL_SHA384", 0x00b1);
- add("TLS_DHE_PSK_WITH_AES_128_CBC_SHA256", 0x00b2);
- add("TLS_DHE_PSK_WITH_AES_256_CBC_SHA384", 0x00b3);
- add("TLS_DHE_PSK_WITH_NULL_SHA256", 0x00b4);
- add("TLS_DHE_PSK_WITH_NULL_SHA384", 0x00b5);
- add("TLS_RSA_PSK_WITH_AES_128_CBC_SHA256", 0x00b6);
- add("TLS_RSA_PSK_WITH_AES_256_CBC_SHA384", 0x00b7);
- add("TLS_RSA_PSK_WITH_NULL_SHA256", 0x00b8);
- add("TLS_RSA_PSK_WITH_NULL_SHA384", 0x00b9);
-
- // Unsupported cipher suites from RFC 5932
- add("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA", 0x0041);
- add("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA", 0x0042);
- add("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA", 0x0043);
- add("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA", 0x0044);
- add("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA", 0x0045);
- add("TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA", 0x0046);
- add("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA", 0x0084);
- add("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA", 0x0085);
- add("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA", 0x0086);
- add("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA", 0x0087);
- add("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA", 0x0088);
- add("TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA", 0x0089);
- add("TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0x00ba);
- add("TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256", 0x00bb);
- add("TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0x00bc);
- add("TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256", 0x00bd);
- add("TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256", 0x00be);
- add("TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256", 0x00bf);
- add("TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256", 0x00c0);
- add("TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256", 0x00c1);
- add("TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256", 0x00c2);
- add("TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256", 0x00c3);
- add("TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256", 0x00c4);
- add("TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256", 0x00c5);
-
- // Unsupported cipher suites from RFC 5054
- add("TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA", 0xc01a);
- add("TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA", 0xc01b);
- add("TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA", 0xc01c);
- add("TLS_SRP_SHA_WITH_AES_128_CBC_SHA", 0xc01d);
- add("TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA", 0xc01e);
- add("TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA", 0xc01f);
- add("TLS_SRP_SHA_WITH_AES_256_CBC_SHA", 0xc020);
- add("TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA", 0xc021);
- add("TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA", 0xc022);
-
- // Unsupported cipher suites from RFC 5289
- add("TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 0xc02b);
- add("TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 0xc02c);
- add("TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", 0xc02d);
- add("TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", 0xc02e);
- add("TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 0xc02f);
- add("TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", 0xc030);
- add("TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", 0xc031);
- add("TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", 0xc032);
-
- // Unsupported cipher suites from RFC 5489
- add("TLS_ECDHE_PSK_WITH_RC4_128_SHA", 0xc033);
- add("TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA", 0xc034);
- add("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA", 0xc035);
- add("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA", 0xc036);
- add("TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256", 0xc037);
- add("TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384", 0xc038);
- add("TLS_ECDHE_PSK_WITH_NULL_SHA", 0xc039);
- add("TLS_ECDHE_PSK_WITH_NULL_SHA256", 0xc03a);
- add("TLS_ECDHE_PSK_WITH_NULL_SHA384", 0xc03b);
- }
-
- // ciphersuite SSL_NULL_WITH_NULL_NULL
- final static CipherSuite C_NULL = CipherSuite.valueOf(0, 0);
-
- // ciphersuite TLS_EMPTY_RENEGOTIATION_INFO_SCSV
- final static CipherSuite C_SCSV = CipherSuite.valueOf(0x00, 0xff);
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/CipherSuiteList.java b/ojluni/src/main/java/sun/security/ssl/CipherSuiteList.java
deleted file mode 100755
index bf69b35..0000000
--- a/ojluni/src/main/java/sun/security/ssl/CipherSuiteList.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.util.*;
-
-import javax.net.ssl.SSLException;
-
-/**
- * A list of CipherSuites. Also maintains the lists of supported and
- * default ciphersuites and supports I/O from handshake streams.
- *
- * Instances of this class are immutable.
- *
- */
-final class CipherSuiteList {
-
- private final Collection<CipherSuite> cipherSuites;
- private String[] suiteNames;
-
- // flag indicating whether this list contains any ECC ciphersuites.
- // null if not yet checked.
- private volatile Boolean containsEC;
-
- // for use by buildAvailableCache() and
- // Handshaker.getKickstartMessage() only
- CipherSuiteList(Collection<CipherSuite> cipherSuites) {
- this.cipherSuites = cipherSuites;
- }
-
- /**
- * Create a CipherSuiteList with a single element.
- */
- CipherSuiteList(CipherSuite suite) {
- cipherSuites = new ArrayList<CipherSuite>(1);
- cipherSuites.add(suite);
- }
-
- /**
- * Construct a CipherSuiteList from a array of names. We don't bother
- * to eliminate duplicates.
- *
- * @exception IllegalArgumentException if the array or any of its elements
- * is null or if the ciphersuite name is unrecognized or unsupported
- * using currently installed providers.
- */
- CipherSuiteList(String[] names) {
- if (names == null) {
- throw new IllegalArgumentException("CipherSuites may not be null");
- }
- cipherSuites = new ArrayList<CipherSuite>(names.length);
- // refresh available cache once if a CipherSuite is not available
- // (maybe new JCE providers have been installed)
- boolean refreshed = false;
- for (int i = 0; i < names.length; i++) {
- String suiteName = names[i];
- CipherSuite suite = CipherSuite.valueOf(suiteName);
- if (suite.isAvailable() == false) {
- if (refreshed == false) {
- // clear the cache so that the isAvailable() call below
- // does a full check
- clearAvailableCache();
- refreshed = true;
- }
- // still missing?
- if (suite.isAvailable() == false) {
- throw new IllegalArgumentException("Cannot support "
- + suiteName + " with currently installed providers");
- }
- }
- cipherSuites.add(suite);
- }
- }
-
- /**
- * Read a CipherSuiteList from a HandshakeInStream in V3 ClientHello
- * format. Does not check if the listed ciphersuites are known or
- * supported.
- */
- CipherSuiteList(HandshakeInStream in) throws IOException {
- byte[] bytes = in.getBytes16();
- if ((bytes.length & 1) != 0) {
- throw new SSLException("Invalid ClientHello message");
- }
- cipherSuites = new ArrayList<CipherSuite>(bytes.length >> 1);
- for (int i = 0; i < bytes.length; i += 2) {
- cipherSuites.add(CipherSuite.valueOf(bytes[i], bytes[i+1]));
- }
- }
-
- /**
- * Return whether this list contains the given CipherSuite.
- */
- boolean contains(CipherSuite suite) {
- return cipherSuites.contains(suite);
- }
-
- // Return whether this list contains any ECC ciphersuites
- boolean containsEC() {
- if (containsEC == null) {
- for (CipherSuite c : cipherSuites) {
- switch (c.keyExchange) {
- case K_ECDH_ECDSA:
- case K_ECDH_RSA:
- case K_ECDHE_ECDSA:
- case K_ECDHE_RSA:
- case K_ECDH_ANON:
- containsEC = true;
- return true;
- default:
- break;
- }
- }
- containsEC = false;
- }
- return containsEC;
- }
-
- /**
- * Return an Iterator for the CipherSuites in this list.
- */
- Iterator<CipherSuite> iterator() {
- return cipherSuites.iterator();
- }
-
- /**
- * Return a reference to the internal Collection of CipherSuites.
- * The Collection MUST NOT be modified.
- */
- Collection<CipherSuite> collection() {
- return cipherSuites;
- }
-
- /**
- * Return the number of CipherSuites in this list.
- */
- int size() {
- return cipherSuites.size();
- }
-
- /**
- * Return an array with the names of the CipherSuites in this list.
- */
- synchronized String[] toStringArray() {
- if (suiteNames == null) {
- suiteNames = new String[cipherSuites.size()];
- int i = 0;
- for (CipherSuite c : cipherSuites) {
- suiteNames[i++] = c.name;
- }
- }
- return suiteNames.clone();
- }
-
- public String toString() {
- return cipherSuites.toString();
- }
-
- /**
- * Write this list to an HandshakeOutStream in V3 ClientHello format.
- */
- void send(HandshakeOutStream s) throws IOException {
- byte[] suiteBytes = new byte[cipherSuites.size() * 2];
- int i = 0;
- for (CipherSuite c : cipherSuites) {
- suiteBytes[i] = (byte)(c.id >> 8);
- suiteBytes[i+1] = (byte)c.id;
- i += 2;
- }
- s.putBytes16(suiteBytes);
- }
-
- /**
- * Clear cache of available ciphersuites. If we support all ciphers
- * internally, there is no need to clear the cache and calling this
- * method has no effect.
- */
- static synchronized void clearAvailableCache() {
- if (CipherSuite.DYNAMIC_AVAILABILITY) {
- CipherSuite.BulkCipher.clearAvailableCache();
- JsseJce.clearEcAvailable();
- }
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/ClientHandshaker.java b/ojluni/src/main/java/sun/security/ssl/ClientHandshaker.java
deleted file mode 100755
index 0c1022b..0000000
--- a/ojluni/src/main/java/sun/security/ssl/ClientHandshaker.java
+++ /dev/null
@@ -1,1345 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.math.BigInteger;
-import java.security.*;
-import java.util.*;
-
-import java.security.interfaces.ECPublicKey;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.ECParameterSpec;
-
-import java.security.cert.X509Certificate;
-import java.security.cert.CertificateException;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-
-import javax.net.ssl.*;
-
-import javax.security.auth.Subject;
-
-import sun.security.ssl.HandshakeMessage.*;
-import sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.KeyExchange.*;
-
-import sun.net.util.IPAddressUtil;
-
-/**
- * ClientHandshaker does the protocol handshaking from the point
- * of view of a client. It is driven asychronously by handshake messages
- * as delivered by the parent Handshaker class, and also uses
- * common functionality (e.g. key generation) that is provided there.
- *
- * @author David Brownell
- */
-final class ClientHandshaker extends Handshaker {
-
- // the server's public key from its certificate.
- private PublicKey serverKey;
-
- // the server's ephemeral public key from the server key exchange message
- // for ECDHE/ECDH_anon and RSA_EXPORT.
- private PublicKey ephemeralServerKey;
-
- // server's ephemeral public value for DHE/DH_anon key exchanges
- private BigInteger serverDH;
-
- private DHCrypt dh;
-
- private ECDHCrypt ecdh;
-
- private CertificateRequest certRequest;
-
- private boolean serverKeyExchangeReceived;
-
- /*
- * The RSA PreMasterSecret needs to know the version of
- * ClientHello that was used on this handshake. This represents
- * the "max version" this client is supporting. In the
- * case of an initial handshake, it's the max version enabled,
- * but in the case of a resumption attempt, it's the version
- * of the session we're trying to resume.
- */
- private ProtocolVersion maxProtocolVersion;
-
- // To switch off the SNI extension.
- private final static boolean enableSNIExtension =
- Debug.getBooleanProperty("jsse.enableSNIExtension", true);
-
- /*
- * Constructors
- */
- ClientHandshaker(SSLSocketImpl socket, SSLContextImpl context,
- ProtocolList enabledProtocols,
- ProtocolVersion activeProtocolVersion,
- boolean isInitialHandshake, boolean secureRenegotiation,
- byte[] clientVerifyData, byte[] serverVerifyData) {
-
- super(socket, context, enabledProtocols, true, true,
- activeProtocolVersion, isInitialHandshake, secureRenegotiation,
- clientVerifyData, serverVerifyData);
- }
-
- ClientHandshaker(SSLEngineImpl engine, SSLContextImpl context,
- ProtocolList enabledProtocols,
- ProtocolVersion activeProtocolVersion,
- boolean isInitialHandshake, boolean secureRenegotiation,
- byte[] clientVerifyData, byte[] serverVerifyData) {
-
- super(engine, context, enabledProtocols, true, true,
- activeProtocolVersion, isInitialHandshake, secureRenegotiation,
- clientVerifyData, serverVerifyData);
- }
-
- /*
- * This routine handles all the client side handshake messages, one at
- * a time. Given the message type (and in some cases the pending cipher
- * spec) it parses the type-specific message. Then it calls a function
- * that handles that specific message.
- *
- * It updates the state machine (need to verify it) as each message
- * is processed, and writes responses as needed using the connection
- * in the constructor.
- */
- void processMessage(byte type, int messageLen) throws IOException {
- if (state >= type
- && (type != HandshakeMessage.ht_hello_request)) {
- throw new SSLProtocolException(
- "Handshake message sequence violation, " + type);
- }
-
- switch (type) {
- case HandshakeMessage.ht_hello_request:
- this.serverHelloRequest(new HelloRequest(input));
- break;
-
- case HandshakeMessage.ht_server_hello:
- this.serverHello(new ServerHello(input, messageLen));
- break;
-
- case HandshakeMessage.ht_certificate:
- if (keyExchange == K_DH_ANON || keyExchange == K_ECDH_ANON
- || keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
- fatalSE(Alerts.alert_unexpected_message,
- "unexpected server cert chain");
- // NOTREACHED
- }
- this.serverCertificate(new CertificateMsg(input));
- serverKey =
- session.getPeerCertificates()[0].getPublicKey();
- break;
-
- case HandshakeMessage.ht_server_key_exchange:
- serverKeyExchangeReceived = true;
- switch (keyExchange) {
- case K_RSA_EXPORT:
- /**
- * The server key exchange message is sent by the server only
- * when the server certificate message does not contain the
- * proper amount of data to allow the client to exchange a
- * premaster secret, such as when RSA_EXPORT is used and the
- * public key in the server certificate is longer than 512 bits.
- */
- if (serverKey == null) {
- throw new SSLProtocolException
- ("Server did not send certificate message");
- }
-
- if (!(serverKey instanceof RSAPublicKey)) {
- throw new SSLProtocolException("Protocol violation:" +
- " the certificate type must be appropriate for the" +
- " selected cipher suite's key exchange algorithm");
- }
-
- if (JsseJce.getRSAKeyLength(serverKey) <= 512) {
- throw new SSLProtocolException("Protocol violation:" +
- " server sent a server key exchange message for" +
- " key exchange " + keyExchange +
- " when the public key in the server certificate" +
- " is less than or equal to 512 bits in length");
- }
-
- try {
- this.serverKeyExchange(new RSA_ServerKeyExchange(input));
- } catch (GeneralSecurityException e) {
- throwSSLException("Server key", e);
- }
- break;
- case K_DH_ANON:
- try {
- this.serverKeyExchange(new DH_ServerKeyExchange(
- input, protocolVersion));
- } catch (GeneralSecurityException e) {
- throwSSLException("Server key", e);
- }
- break;
- case K_DHE_DSS:
- case K_DHE_RSA:
- try {
- this.serverKeyExchange(new DH_ServerKeyExchange(
- input, serverKey,
- clnt_random.random_bytes, svr_random.random_bytes,
- messageLen,
- localSupportedSignAlgs, protocolVersion));
- } catch (GeneralSecurityException e) {
- throwSSLException("Server key", e);
- }
- break;
- case K_ECDHE_ECDSA:
- case K_ECDHE_RSA:
- case K_ECDH_ANON:
- try {
- this.serverKeyExchange(new ECDH_ServerKeyExchange
- (input, serverKey, clnt_random.random_bytes,
- svr_random.random_bytes,
- localSupportedSignAlgs, protocolVersion));
- } catch (GeneralSecurityException e) {
- throwSSLException("Server key", e);
- }
- break;
- case K_RSA:
- case K_DH_RSA:
- case K_DH_DSS:
- case K_ECDH_ECDSA:
- case K_ECDH_RSA:
- throw new SSLProtocolException(
- "Protocol violation: server sent a server key exchange"
- + "message for key exchange " + keyExchange);
- case K_KRB5:
- case K_KRB5_EXPORT:
- throw new SSLProtocolException(
- "unexpected receipt of server key exchange algorithm");
- default:
- throw new SSLProtocolException(
- "unsupported key exchange algorithm = "
- + keyExchange);
- }
- break;
-
- case HandshakeMessage.ht_certificate_request:
- // save for later, it's handled by serverHelloDone
- if ((keyExchange == K_DH_ANON) || (keyExchange == K_ECDH_ANON)) {
- throw new SSLHandshakeException(
- "Client authentication requested for "+
- "anonymous cipher suite.");
- } else if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
- throw new SSLHandshakeException(
- "Client certificate requested for "+
- "kerberos cipher suite.");
- }
- certRequest = new CertificateRequest(input, protocolVersion);
- if (debug != null && Debug.isOn("handshake")) {
- certRequest.print(System.out);
- }
-
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- Collection<SignatureAndHashAlgorithm> peerSignAlgs =
- certRequest.getSignAlgorithms();
- if (peerSignAlgs == null || peerSignAlgs.isEmpty()) {
- throw new SSLHandshakeException(
- "No peer supported signature algorithms");
- }
-
- Collection<SignatureAndHashAlgorithm> supportedPeerSignAlgs =
- SignatureAndHashAlgorithm.getSupportedAlgorithms(
- peerSignAlgs);
- if (supportedPeerSignAlgs.isEmpty()) {
- throw new SSLHandshakeException(
- "No supported signature and hash algorithm in common");
- }
-
- setPeerSupportedSignAlgs(supportedPeerSignAlgs);
- session.setPeerSupportedSignatureAlgorithms(
- supportedPeerSignAlgs);
- }
-
- break;
-
- case HandshakeMessage.ht_server_hello_done:
- this.serverHelloDone(new ServerHelloDone(input));
- break;
-
- case HandshakeMessage.ht_finished:
- this.serverFinished(
- new Finished(protocolVersion, input, cipherSuite));
- break;
-
- default:
- throw new SSLProtocolException(
- "Illegal client handshake msg, " + type);
- }
-
- //
- // Move state machine forward if the message handling
- // code didn't already do so
- //
- if (state < type) {
- state = type;
- }
- }
-
- /*
- * Used by the server to kickstart negotiations -- this requests a
- * "client hello" to renegotiate current cipher specs (e.g. maybe lots
- * of data has been encrypted with the same keys, or the server needs
- * the client to present a certificate).
- */
- private void serverHelloRequest(HelloRequest mesg) throws IOException {
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
-
- //
- // Could be (e.g. at connection setup) that we already
- // sent the "client hello" but the server's not seen it.
- //
- if (state < HandshakeMessage.ht_client_hello) {
- if (!secureRenegotiation && !allowUnsafeRenegotiation) {
- // renegotiation is not allowed.
- if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
- // response with a no_renegotiation warning,
- warningSE(Alerts.alert_no_renegotiation);
-
- // invalidate the handshake so that the caller can
- // dispose this object.
- invalidated = true;
-
- // If there is still unread block in the handshake
- // input stream, it would be truncated with the disposal
- // and the next handshake message will become incomplete.
- //
- // However, according to SSL/TLS specifications, no more
- // handshake message should immediately follow ClientHello
- // or HelloRequest. So just let it be.
- } else {
- // For SSLv3, send the handshake_failure fatal error.
- // Note that SSLv3 does not define a no_renegotiation
- // alert like TLSv1. However we cannot ignore the message
- // simply, otherwise the other side was waiting for a
- // response that would never come.
- fatalSE(Alerts.alert_handshake_failure,
- "Renegotiation is not allowed");
- }
- } else {
- if (!secureRenegotiation) {
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println(
- "Warning: continue with insecure renegotiation");
- }
- }
- kickstart();
- }
- }
- }
-
-
- /*
- * Server chooses session parameters given options created by the
- * client -- basically, cipher options, session id, and someday a
- * set of compression options.
- *
- * There are two branches of the state machine, decided by the
- * details of this message. One is the "fast" handshake, where we
- * can resume the pre-existing session we asked resume. The other
- * is a more expensive "full" handshake, with key exchange and
- * probably authentication getting done.
- */
- private void serverHello(ServerHello mesg) throws IOException {
- serverKeyExchangeReceived = false;
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
-
- // check if the server selected protocol version is OK for us
- ProtocolVersion mesgVersion = mesg.protocolVersion;
- if (!isNegotiable(mesgVersion)) {
- throw new SSLHandshakeException(
- "Server chose " + mesgVersion +
- ", but that protocol version is not enabled or not supported " +
- "by the client.");
- }
-
- handshakeHash.protocolDetermined(mesgVersion);
-
- // Set protocolVersion and propagate to SSLSocket and the
- // Handshake streams
- setVersion(mesgVersion);
-
- // check the "renegotiation_info" extension
- RenegotiationInfoExtension serverHelloRI = (RenegotiationInfoExtension)
- mesg.extensions.get(ExtensionType.EXT_RENEGOTIATION_INFO);
- if (serverHelloRI != null) {
- if (isInitialHandshake) {
- // verify the length of the "renegotiated_connection" field
- if (!serverHelloRI.isEmpty()) {
- // abort the handshake with a fatal handshake_failure alert
- fatalSE(Alerts.alert_handshake_failure,
- "The renegotiation_info field is not empty");
- }
-
- secureRenegotiation = true;
- } else {
- // For a legacy renegotiation, the client MUST verify that
- // it does not contain the "renegotiation_info" extension.
- if (!secureRenegotiation) {
- fatalSE(Alerts.alert_handshake_failure,
- "Unexpected renegotiation indication extension");
- }
-
- // verify the client_verify_data and server_verify_data values
- byte[] verifyData =
- new byte[clientVerifyData.length + serverVerifyData.length];
- System.arraycopy(clientVerifyData, 0, verifyData,
- 0, clientVerifyData.length);
- System.arraycopy(serverVerifyData, 0, verifyData,
- clientVerifyData.length, serverVerifyData.length);
- if (!Arrays.equals(verifyData,
- serverHelloRI.getRenegotiatedConnection())) {
- fatalSE(Alerts.alert_handshake_failure,
- "Incorrect verify data in ServerHello " +
- "renegotiation_info message");
- }
- }
- } else {
- // no renegotiation indication extension
- if (isInitialHandshake) {
- if (!allowLegacyHelloMessages) {
- // abort the handshake with a fatal handshake_failure alert
- fatalSE(Alerts.alert_handshake_failure,
- "Failed to negotiate the use of secure renegotiation");
- }
-
- secureRenegotiation = false;
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println("Warning: No renegotiation " +
- "indication extension in ServerHello");
- }
- } else {
- // For a secure renegotiation, the client must abort the
- // handshake if no "renegotiation_info" extension is present.
- if (secureRenegotiation) {
- fatalSE(Alerts.alert_handshake_failure,
- "No renegotiation indication extension");
- }
-
- // we have already allowed unsafe renegotation before request
- // the renegotiation.
- }
- }
-
- //
- // Save server nonce, we always use it to compute connection
- // keys and it's also used to create the master secret if we're
- // creating a new session (i.e. in the full handshake).
- //
- svr_random = mesg.svr_random;
-
- if (isNegotiable(mesg.cipherSuite) == false) {
- fatalSE(Alerts.alert_illegal_parameter,
- "Server selected improper ciphersuite " + mesg.cipherSuite);
- }
-
- setCipherSuite(mesg.cipherSuite);
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg());
- }
-
- if (mesg.compression_method != 0) {
- fatalSE(Alerts.alert_illegal_parameter,
- "compression type not supported, "
- + mesg.compression_method);
- // NOTREACHED
- }
-
- // so far so good, let's look at the session
- if (session != null) {
- // we tried to resume, let's see what the server decided
- if (session.getSessionId().equals(mesg.sessionId)) {
- // server resumed the session, let's make sure everything
- // checks out
-
- // Verify that the session ciphers are unchanged.
- CipherSuite sessionSuite = session.getSuite();
- if (cipherSuite != sessionSuite) {
- throw new SSLProtocolException
- ("Server returned wrong cipher suite for session");
- }
-
- // verify protocol version match
- ProtocolVersion sessionVersion = session.getProtocolVersion();
- if (protocolVersion != sessionVersion) {
- throw new SSLProtocolException
- ("Server resumed session with wrong protocol version");
- }
-
- // validate subject identity
- if (sessionSuite.keyExchange == K_KRB5 ||
- sessionSuite.keyExchange == K_KRB5_EXPORT) {
- Principal localPrincipal = session.getLocalPrincipal();
-
- Subject subject = null;
- try {
- subject = AccessController.doPrivileged(
- new PrivilegedExceptionAction<Subject>() {
- public Subject run() throws Exception {
- return Krb5Helper.getClientSubject(getAccSE());
- }});
- } catch (PrivilegedActionException e) {
- subject = null;
- if (debug != null && Debug.isOn("session")) {
- System.out.println("Attempt to obtain" +
- " subject failed!");
- }
- }
-
- if (subject != null) {
- // Eliminate dependency on KerberosPrincipal
- Set<Principal> principals =
- subject.getPrincipals(Principal.class);
- if (!principals.contains(localPrincipal)) {
- throw new SSLProtocolException("Server resumed" +
- " session with wrong subject identity");
- } else {
- if (debug != null && Debug.isOn("session"))
- System.out.println("Subject identity is same");
- }
- } else {
- if (debug != null && Debug.isOn("session"))
- System.out.println("Kerberos credentials are not" +
- " present in the current Subject; check if " +
- " javax.security.auth.useSubjectAsCreds" +
- " system property has been set to false");
- throw new SSLProtocolException
- ("Server resumed session with no subject");
- }
- }
-
- // looks fine; resume it, and update the state machine.
- resumingSession = true;
- state = HandshakeMessage.ht_finished - 1;
- calculateConnectionKeys(session.getMasterSecret());
- if (debug != null && Debug.isOn("session")) {
- System.out.println("%% Server resumed " + session);
- }
- } else {
- // we wanted to resume, but the server refused
- session = null;
- if (!enableNewSession) {
- throw new SSLException
- ("New session creation is disabled");
- }
- }
- }
-
- if (resumingSession && session != null) {
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- handshakeHash.setCertificateVerifyAlg(null);
- }
-
- setHandshakeSessionSE(session);
- return;
- }
-
- // check extensions
- for (HelloExtension ext : mesg.extensions.list()) {
- ExtensionType type = ext.type;
- if ((type != ExtensionType.EXT_ELLIPTIC_CURVES)
- && (type != ExtensionType.EXT_EC_POINT_FORMATS)
- && (type != ExtensionType.EXT_SERVER_NAME)
- && (type != ExtensionType.EXT_RENEGOTIATION_INFO)) {
- fatalSE(Alerts.alert_unsupported_extension,
- "Server sent an unsupported extension: " + type);
- }
- }
-
- // Create a new session, we need to do the full handshake
- session = new SSLSessionImpl(protocolVersion, cipherSuite,
- getLocalSupportedSignAlgs(),
- mesg.sessionId, getHostSE(), getPortSE());
- setHandshakeSessionSE(session);
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println("** " + cipherSuite);
- }
- }
-
- /*
- * Server's own key was either a signing-only key, or was too
- * large for export rules ... this message holds an ephemeral
- * RSA key to use for key exchange.
- */
- private void serverKeyExchange(RSA_ServerKeyExchange mesg)
- throws IOException, GeneralSecurityException {
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
- if (!mesg.verify(serverKey, clnt_random, svr_random)) {
- fatalSE(Alerts.alert_handshake_failure,
- "server key exchange invalid");
- // NOTREACHED
- }
- ephemeralServerKey = mesg.getPublicKey();
- }
-
-
- /*
- * Diffie-Hellman key exchange. We save the server public key and
- * our own D-H algorithm object so we can defer key calculations
- * until after we've sent the client key exchange message (which
- * gives client and server some useful parallelism).
- */
- private void serverKeyExchange(DH_ServerKeyExchange mesg)
- throws IOException {
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
- dh = new DHCrypt(mesg.getModulus(), mesg.getBase(),
- sslContext.getSecureRandom());
- serverDH = mesg.getServerPublicKey();
- }
-
- private void serverKeyExchange(ECDH_ServerKeyExchange mesg)
- throws IOException {
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
- ECPublicKey key = mesg.getPublicKey();
- ecdh = new ECDHCrypt(key.getParams(), sslContext.getSecureRandom());
- ephemeralServerKey = key;
- }
-
- /*
- * The server's "Hello Done" message is the client's sign that
- * it's time to do all the hard work.
- */
- private void serverHelloDone(ServerHelloDone mesg) throws IOException {
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
- /*
- * Always make sure the input has been digested before we
- * start emitting data, to ensure the hashes are correctly
- * computed for the Finished and CertificateVerify messages
- * which we send (here).
- */
- input.digestNow();
-
- /*
- * FIRST ... if requested, send an appropriate Certificate chain
- * to authenticate the client, and remember the associated private
- * key to sign the CertificateVerify message.
- */
- PrivateKey signingKey = null;
-
- if (certRequest != null) {
- X509ExtendedKeyManager km = sslContext.getX509KeyManager();
-
- ArrayList<String> keytypesTmp = new ArrayList<>(4);
-
- for (int i = 0; i < certRequest.types.length; i++) {
- String typeName;
-
- switch (certRequest.types[i]) {
- case CertificateRequest.cct_rsa_sign:
- typeName = "RSA";
- break;
-
- case CertificateRequest.cct_dss_sign:
- typeName = "DSA";
- break;
-
- case CertificateRequest.cct_ecdsa_sign:
- // ignore if we do not have EC crypto available
- typeName = JsseJce.isEcAvailable() ? "EC" : null;
- break;
-
- // Fixed DH/ECDH client authentication not supported
- case CertificateRequest.cct_rsa_fixed_dh:
- case CertificateRequest.cct_dss_fixed_dh:
- case CertificateRequest.cct_rsa_fixed_ecdh:
- case CertificateRequest.cct_ecdsa_fixed_ecdh:
- // Any other values (currently not used in TLS)
- case CertificateRequest.cct_rsa_ephemeral_dh:
- case CertificateRequest.cct_dss_ephemeral_dh:
- default:
- typeName = null;
- break;
- }
-
- if ((typeName != null) && (!keytypesTmp.contains(typeName))) {
- keytypesTmp.add(typeName);
- }
- }
-
- String alias = null;
- int keytypesTmpSize = keytypesTmp.size();
- if (keytypesTmpSize != 0) {
- String keytypes[] =
- keytypesTmp.toArray(new String[keytypesTmpSize]);
-
- if (conn != null) {
- alias = km.chooseClientAlias(keytypes,
- certRequest.getAuthorities(), conn);
- } else {
- alias = km.chooseEngineClientAlias(keytypes,
- certRequest.getAuthorities(), engine);
- }
- }
-
- CertificateMsg m1 = null;
- if (alias != null) {
- X509Certificate[] certs = km.getCertificateChain(alias);
- if ((certs != null) && (certs.length != 0)) {
- PublicKey publicKey = certs[0].getPublicKey();
- // for EC, make sure we use a supported named curve
- if (publicKey instanceof ECPublicKey) {
- ECParameterSpec params =
- ((ECPublicKey)publicKey).getParams();
- int index =
- SupportedEllipticCurvesExtension.getCurveIndex(
- params);
- if (!SupportedEllipticCurvesExtension.isSupported(
- index)) {
- publicKey = null;
- }
- }
- if (publicKey != null) {
- m1 = new CertificateMsg(certs);
- signingKey = km.getPrivateKey(alias);
- session.setLocalPrivateKey(signingKey);
- session.setLocalCertificates(certs);
- }
- }
- }
- if (m1 == null) {
- //
- // No appropriate cert was found ... report this to the
- // server. For SSLv3, send the no_certificate alert;
- // TLS uses an empty cert chain instead.
- //
- if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
- m1 = new CertificateMsg(new X509Certificate [0]);
- } else {
- warningSE(Alerts.alert_no_certificate);
- }
- }
-
- //
- // At last ... send any client certificate chain.
- //
- if (m1 != null) {
- if (debug != null && Debug.isOn("handshake")) {
- m1.print(System.out);
- }
- m1.write(output);
- }
- }
-
- /*
- * SECOND ... send the client key exchange message. The
- * procedure used is a function of the cipher suite selected;
- * one is always needed.
- */
- HandshakeMessage m2;
-
- switch (keyExchange) {
-
- case K_RSA:
- case K_RSA_EXPORT:
- if (serverKey == null) {
- throw new SSLProtocolException
- ("Server did not send certificate message");
- }
-
- if (!(serverKey instanceof RSAPublicKey)) {
- throw new SSLProtocolException
- ("Server certificate does not include an RSA key");
- }
-
- /*
- * For RSA key exchange, we randomly generate a new
- * pre-master secret and encrypt it with the server's
- * public key. Then we save that pre-master secret
- * so that we can calculate the keying data later;
- * it's a performance speedup not to do that until
- * the client's waiting for the server response, but
- * more of a speedup for the D-H case.
- *
- * If the RSA_EXPORT scheme is active, when the public
- * key in the server certificate is less than or equal
- * to 512 bits in length, use the cert's public key,
- * otherwise, the ephemeral one.
- */
- PublicKey key;
- if (keyExchange == K_RSA) {
- key = serverKey;
- } else { // K_RSA_EXPORT
- if (JsseJce.getRSAKeyLength(serverKey) <= 512) {
- // extraneous ephemeralServerKey check done
- // above in processMessage()
- key = serverKey;
- } else {
- if (ephemeralServerKey == null) {
- throw new SSLProtocolException("Server did not send" +
- " a RSA_EXPORT Server Key Exchange message");
- }
- key = ephemeralServerKey;
- }
- }
-
- m2 = new RSAClientKeyExchange(protocolVersion, maxProtocolVersion,
- sslContext.getSecureRandom(), key);
- break;
- case K_DH_RSA:
- case K_DH_DSS:
- /*
- * For DH Key exchange, we only need to make sure the server
- * knows our public key, so we calculate the same pre-master
- * secret.
- *
- * For certs that had DH keys in them, we send an empty
- * handshake message (no key) ... we flag this case by
- * passing a null "dhPublic" value.
- *
- * Otherwise we send ephemeral DH keys, unsigned.
- */
- // if (useDH_RSA || useDH_DSS)
- m2 = new DHClientKeyExchange();
- break;
- case K_DHE_RSA:
- case K_DHE_DSS:
- case K_DH_ANON:
- if (dh == null) {
- throw new SSLProtocolException
- ("Server did not send a DH Server Key Exchange message");
- }
- m2 = new DHClientKeyExchange(dh.getPublicKey());
- break;
- case K_ECDHE_RSA:
- case K_ECDHE_ECDSA:
- case K_ECDH_ANON:
- if (ecdh == null) {
- throw new SSLProtocolException
- ("Server did not send a ECDH Server Key Exchange message");
- }
- m2 = new ECDHClientKeyExchange(ecdh.getPublicKey());
- break;
- case K_ECDH_RSA:
- case K_ECDH_ECDSA:
- if (serverKey == null) {
- throw new SSLProtocolException
- ("Server did not send certificate message");
- }
- if (serverKey instanceof ECPublicKey == false) {
- throw new SSLProtocolException
- ("Server certificate does not include an EC key");
- }
- ECParameterSpec params = ((ECPublicKey)serverKey).getParams();
- ecdh = new ECDHCrypt(params, sslContext.getSecureRandom());
- m2 = new ECDHClientKeyExchange(ecdh.getPublicKey());
- break;
- case K_KRB5:
- case K_KRB5_EXPORT:
- String hostname = getHostSE();
- if (hostname == null) {
- throw new IOException("Hostname is required" +
- " to use Kerberos cipher suites");
- }
- KerberosClientKeyExchange kerberosMsg =
- new KerberosClientKeyExchange(
- hostname, isLoopbackSE(), getAccSE(), protocolVersion,
- sslContext.getSecureRandom());
- // Record the principals involved in exchange
- session.setPeerPrincipal(kerberosMsg.getPeerPrincipal());
- session.setLocalPrincipal(kerberosMsg.getLocalPrincipal());
- m2 = kerberosMsg;
- break;
- default:
- // somethings very wrong
- throw new RuntimeException
- ("Unsupported key exchange: " + keyExchange);
- }
- if (debug != null && Debug.isOn("handshake")) {
- m2.print(System.out);
- }
- m2.write(output);
-
-
- /*
- * THIRD, send a "change_cipher_spec" record followed by the
- * "Finished" message. We flush the messages we've queued up, to
- * get concurrency between client and server. The concurrency is
- * useful as we calculate the master secret, which is needed both
- * to compute the "Finished" message, and to compute the keys used
- * to protect all records following the change_cipher_spec.
- */
-
- output.doHashes();
- output.flush();
-
- /*
- * We deferred calculating the master secret and this connection's
- * keying data; we do it now. Deferring this calculation is good
- * from a performance point of view, since it lets us do it during
- * some time that network delays and the server's own calculations
- * would otherwise cause to be "dead" in the critical path.
- */
- SecretKey preMasterSecret;
- switch (keyExchange) {
- case K_RSA:
- case K_RSA_EXPORT:
- preMasterSecret = ((RSAClientKeyExchange)m2).preMaster;
- break;
- case K_KRB5:
- case K_KRB5_EXPORT:
- byte[] secretBytes =
- ((KerberosClientKeyExchange)m2).getUnencryptedPreMasterSecret();
- preMasterSecret = new SecretKeySpec(secretBytes,
- "TlsPremasterSecret");
- break;
- case K_DHE_RSA:
- case K_DHE_DSS:
- case K_DH_ANON:
- preMasterSecret = dh.getAgreedSecret(serverDH, true);
- break;
- case K_ECDHE_RSA:
- case K_ECDHE_ECDSA:
- case K_ECDH_ANON:
- preMasterSecret = ecdh.getAgreedSecret(ephemeralServerKey);
- break;
- case K_ECDH_RSA:
- case K_ECDH_ECDSA:
- preMasterSecret = ecdh.getAgreedSecret(serverKey);
- break;
- default:
- throw new IOException("Internal error: unknown key exchange "
- + keyExchange);
- }
-
- calculateKeys(preMasterSecret, null);
-
- /*
- * FOURTH, if we sent a Certificate, we need to send a signed
- * CertificateVerify (unless the key in the client's certificate
- * was a Diffie-Hellman key).).
- *
- * This uses a hash of the previous handshake messages ... either
- * a nonfinal one (if the particular implementation supports it)
- * or else using the third element in the arrays of hashes being
- * computed.
- */
- if (signingKey != null) {
- CertificateVerify m3;
- try {
- SignatureAndHashAlgorithm preferableSignatureAlgorithm = null;
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- preferableSignatureAlgorithm =
- SignatureAndHashAlgorithm.getPreferableAlgorithm(
- peerSupportedSignAlgs, signingKey.getAlgorithm(),
- signingKey);
-
- if (preferableSignatureAlgorithm == null) {
- throw new SSLHandshakeException(
- "No supported signature algorithm");
- }
-
- String hashAlg =
- SignatureAndHashAlgorithm.getHashAlgorithmName(
- preferableSignatureAlgorithm);
- if (hashAlg == null || hashAlg.length() == 0) {
- throw new SSLHandshakeException(
- "No supported hash algorithm");
- }
-
- handshakeHash.setCertificateVerifyAlg(hashAlg);
- }
-
- m3 = new CertificateVerify(protocolVersion, handshakeHash,
- signingKey, session.getMasterSecret(),
- sslContext.getSecureRandom(),
- preferableSignatureAlgorithm);
- } catch (GeneralSecurityException e) {
- fatalSE(Alerts.alert_handshake_failure,
- "Error signing certificate verify", e);
- // NOTREACHED, make compiler happy
- m3 = null;
- }
- if (debug != null && Debug.isOn("handshake")) {
- m3.print(System.out);
- }
- m3.write(output);
- output.doHashes();
- } else {
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- handshakeHash.setCertificateVerifyAlg(null);
- }
- }
-
- /*
- * OK, that's that!
- */
- sendChangeCipherAndFinish(false);
- }
-
-
- /*
- * "Finished" is the last handshake message sent. If we got this
- * far, the MAC has been validated post-decryption. We validate
- * the two hashes here as an additional sanity check, protecting
- * the handshake against various active attacks.
- */
- private void serverFinished(Finished mesg) throws IOException {
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
-
- boolean verified = mesg.verify(handshakeHash, Finished.SERVER,
- session.getMasterSecret());
-
- if (!verified) {
- fatalSE(Alerts.alert_illegal_parameter,
- "server 'finished' message doesn't verify");
- // NOTREACHED
- }
-
- /*
- * save server verify data for secure renegotiation
- */
- if (secureRenegotiation) {
- serverVerifyData = mesg.getVerifyData();
- }
-
- /*
- * OK, it verified. If we're doing the fast handshake, add that
- * "Finished" message to the hash of handshake messages, then send
- * our own change_cipher_spec and Finished message for the server
- * to verify in turn. These are the last handshake messages.
- *
- * In any case, update the session cache. We're done handshaking,
- * so there are no threats any more associated with partially
- * completed handshakes.
- */
- if (resumingSession) {
- input.digestNow();
- sendChangeCipherAndFinish(true);
- }
- session.setLastAccessedTime(System.currentTimeMillis());
-
- if (!resumingSession) {
- if (session.isRejoinable()) {
- ((SSLSessionContextImpl) sslContext
- .engineGetClientSessionContext())
- .put(session);
- if (debug != null && Debug.isOn("session")) {
- System.out.println("%% Cached client session: " + session);
- }
- } else if (debug != null && Debug.isOn("session")) {
- System.out.println(
- "%% Didn't cache non-resumable client session: "
- + session);
- }
- }
- }
-
-
- /*
- * Send my change-cipher-spec and Finished message ... done as the
- * last handshake act in either the short or long sequences. In
- * the short one, we've already seen the server's Finished; in the
- * long one, we wait for it now.
- */
- private void sendChangeCipherAndFinish(boolean finishedTag)
- throws IOException {
- Finished mesg = new Finished(protocolVersion, handshakeHash,
- Finished.CLIENT, session.getMasterSecret(), cipherSuite);
-
- /*
- * Send the change_cipher_spec message, then the Finished message
- * which we just calculated (and protected using the keys we just
- * calculated). Server responds with its Finished message, except
- * in the "fast handshake" (resume session) case.
- */
- sendChangeCipherSpec(mesg, finishedTag);
-
- /*
- * save client verify data for secure renegotiation
- */
- if (secureRenegotiation) {
- clientVerifyData = mesg.getVerifyData();
- }
-
- /*
- * Update state machine so server MUST send 'finished' next.
- * (In "long" handshake case; in short case, we're responding
- * to its message.)
- */
- state = HandshakeMessage.ht_finished - 1;
- }
-
-
- /*
- * Returns a ClientHello message to kickstart renegotiations
- */
- HandshakeMessage getKickstartMessage() throws SSLException {
- // session ID of the ClientHello message
- SessionId sessionId = SSLSessionImpl.nullSession.getSessionId();
-
- // a list of cipher suites sent by the client
- CipherSuiteList cipherSuites = getActiveCipherSuites();
-
- // set the max protocol version this client is supporting.
- maxProtocolVersion = protocolVersion;
-
- //
- // Try to resume an existing session. This might be mandatory,
- // given certain API options.
- //
- session = ((SSLSessionContextImpl)sslContext
- .engineGetClientSessionContext())
- .get(getHostSE(), getPortSE());
- if (debug != null && Debug.isOn("session")) {
- if (session != null) {
- System.out.println("%% Client cached "
- + session
- + (session.isRejoinable() ? "" : " (not rejoinable)"));
- } else {
- System.out.println("%% No cached client session");
- }
- }
- if ((session != null) && (session.isRejoinable() == false)) {
- session = null;
- }
-
- if (session != null) {
- CipherSuite sessionSuite = session.getSuite();
- ProtocolVersion sessionVersion = session.getProtocolVersion();
- if (isNegotiable(sessionSuite) == false) {
- if (debug != null && Debug.isOn("session")) {
- System.out.println("%% can't resume, unavailable cipher");
- }
- session = null;
- }
-
- if ((session != null) && !isNegotiable(sessionVersion)) {
- if (debug != null && Debug.isOn("session")) {
- System.out.println("%% can't resume, protocol disabled");
- }
- session = null;
- }
-
- if (session != null) {
- if (debug != null) {
- if (Debug.isOn("handshake") || Debug.isOn("session")) {
- System.out.println("%% Try resuming " + session
- + " from port " + getLocalPortSE());
- }
- }
-
- sessionId = session.getSessionId();
- maxProtocolVersion = sessionVersion;
-
- // Update SSL version number in underlying SSL socket and
- // handshake output stream, so that the output records (at the
- // record layer) have the correct version
- setVersion(sessionVersion);
- }
-
- /*
- * Force use of the previous session ciphersuite, and
- * add the SCSV if enabled.
- */
- if (!enableNewSession) {
- if (session == null) {
- throw new SSLHandshakeException(
- "Can't reuse existing SSL client session");
- }
-
- Collection<CipherSuite> cipherList = new ArrayList<>(2);
- cipherList.add(sessionSuite);
- if (!secureRenegotiation &&
- cipherSuites.contains(CipherSuite.C_SCSV)) {
- cipherList.add(CipherSuite.C_SCSV);
- } // otherwise, renegotiation_info extension will be used
-
- cipherSuites = new CipherSuiteList(cipherList);
- }
- }
-
- if (session == null && !enableNewSession) {
- throw new SSLHandshakeException("No existing session to resume");
- }
-
- // exclude SCSV for secure renegotiation
- if (secureRenegotiation && cipherSuites.contains(CipherSuite.C_SCSV)) {
- Collection<CipherSuite> cipherList =
- new ArrayList<>(cipherSuites.size() - 1);
- for (CipherSuite suite : cipherSuites.collection()) {
- if (suite != CipherSuite.C_SCSV) {
- cipherList.add(suite);
- }
- }
-
- cipherSuites = new CipherSuiteList(cipherList);
- }
-
- // make sure there is a negotiable cipher suite.
- boolean negotiable = false;
- for (CipherSuite suite : cipherSuites.collection()) {
- if (isNegotiable(suite)) {
- negotiable = true;
- break;
- }
- }
-
- if (!negotiable) {
- throw new SSLHandshakeException("No negotiable cipher suite");
- }
-
- // Not a TLS1.2+ handshake
- // For SSLv2Hello, HandshakeHash.reset() will be called, so we
- // cannot call HandshakeHash.protocolDetermined() here. As it does
- // not follow the spec that HandshakeHash.reset() can be only be
- // called before protocolDetermined.
- // if (maxProtocolVersion.v < ProtocolVersion.TLS12.v) {
- // handshakeHash.protocolDetermined(maxProtocolVersion);
- // }
-
- // create the ClientHello message
- ClientHello clientHelloMessage = new ClientHello(
- sslContext.getSecureRandom(), maxProtocolVersion,
- sessionId, cipherSuites);
-
- // add signature_algorithm extension
- if (maxProtocolVersion.v >= ProtocolVersion.TLS12.v) {
- // we will always send the signature_algorithm extension
- Collection<SignatureAndHashAlgorithm> localSignAlgs =
- getLocalSupportedSignAlgs();
- if (localSignAlgs.isEmpty()) {
- throw new SSLHandshakeException(
- "No supported signature algorithm");
- }
-
- clientHelloMessage.addSignatureAlgorithmsExtension(localSignAlgs);
- }
-
- // add server_name extension
- if (enableSNIExtension) {
- // We cannot use the hostname resolved from name services. For
- // virtual hosting, multiple hostnames may be bound to the same IP
- // address, so the hostname resolved from name services is not
- // reliable.
- String hostname = getRawHostnameSE();
-
- // we only allow FQDN
- if (hostname != null && hostname.indexOf('.') > 0 &&
- !IPAddressUtil.isIPv4LiteralAddress(hostname) &&
- !IPAddressUtil.isIPv6LiteralAddress(hostname)) {
- clientHelloMessage.addServerNameIndicationExtension(hostname);
- }
- }
-
- // reset the client random cookie
- clnt_random = clientHelloMessage.clnt_random;
-
- /*
- * need to set the renegotiation_info extension for:
- * 1: secure renegotiation
- * 2: initial handshake and no SCSV in the ClientHello
- * 3: insecure renegotiation and no SCSV in the ClientHello
- */
- if (secureRenegotiation ||
- !cipherSuites.contains(CipherSuite.C_SCSV)) {
- clientHelloMessage.addRenegotiationInfoExtension(clientVerifyData);
- }
-
- return clientHelloMessage;
- }
-
- /*
- * Fault detected during handshake.
- */
- void handshakeAlert(byte description) throws SSLProtocolException {
- String message = Alerts.alertDescription(description);
-
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println("SSL - handshake alert: " + message);
- }
- throw new SSLProtocolException("handshake alert: " + message);
- }
-
- /*
- * Unless we are using an anonymous ciphersuite, the server always
- * sends a certificate message (for the CipherSuites we currently
- * support). The trust manager verifies the chain for us.
- */
- private void serverCertificate(CertificateMsg mesg) throws IOException {
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
- X509Certificate[] peerCerts = mesg.getCertificateChain();
- if (peerCerts.length == 0) {
- fatalSE(Alerts.alert_bad_certificate,
- "empty certificate chain");
- }
- // ask the trust manager to verify the chain
- X509TrustManager tm = sslContext.getX509TrustManager();
- try {
- // find out the key exchange algorithm used
- // use "RSA" for non-ephemeral "RSA_EXPORT"
- String keyExchangeString;
- if (keyExchange == K_RSA_EXPORT && !serverKeyExchangeReceived) {
- keyExchangeString = K_RSA.name;
- } else {
- keyExchangeString = keyExchange.name;
- }
-
- if (tm instanceof X509ExtendedTrustManager) {
- if (conn != null) {
- ((X509ExtendedTrustManager)tm).checkServerTrusted(
- peerCerts.clone(),
- keyExchangeString,
- conn);
- } else {
- ((X509ExtendedTrustManager)tm).checkServerTrusted(
- peerCerts.clone(),
- keyExchangeString,
- engine);
- }
- } else {
- // Unlikely to happen, because we have wrapped the old
- // X509TrustManager with the new X509ExtendedTrustManager.
- throw new CertificateException(
- "Improper X509TrustManager implementation");
- }
- } catch (CertificateException e) {
- // This will throw an exception, so include the original error.
- fatalSE(Alerts.alert_certificate_unknown, e);
- }
- session.setPeerCertificates(peerCerts);
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/DHClientKeyExchange.java b/ojluni/src/main/java/sun/security/ssl/DHClientKeyExchange.java
deleted file mode 100755
index b450098..0000000
--- a/ojluni/src/main/java/sun/security/ssl/DHClientKeyExchange.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.math.BigInteger;
-import javax.net.ssl.SSLHandshakeException;
-
-/*
- * Message used by clients to send their Diffie-Hellman public
- * keys to servers.
- *
- * @author David Brownell
- */
-final class DHClientKeyExchange extends HandshakeMessage {
-
- int messageType() {
- return ht_client_key_exchange;
- }
-
- /*
- * This value may be empty if it was included in the
- * client's certificate ...
- */
- private byte dh_Yc[]; // 1 to 2^16 -1 bytes
-
- BigInteger getClientPublicKey() {
- return dh_Yc == null ? null : new BigInteger(1, dh_Yc);
- }
-
- /*
- * Either pass the client's public key explicitly (because it's
- * using DHE or DH_anon), or implicitly (the public key was in the
- * certificate).
- */
- DHClientKeyExchange(BigInteger publicKey) {
- dh_Yc = toByteArray(publicKey);
- }
-
- DHClientKeyExchange() {
- dh_Yc = null;
- }
-
- /*
- * Get the client's public key either explicitly or implicitly.
- * (It's ugly to have an empty record be sent in the latter case,
- * but that's what the protocol spec requires.)
- */
- DHClientKeyExchange(HandshakeInStream input) throws IOException {
- if (input.available() >= 2) {
- dh_Yc = input.getBytes16();
- } else {
- // currently, we don't support cipher suites that requires
- // implicit public key of client.
- throw new SSLHandshakeException(
- "Unsupported implicit client DiffieHellman public key");
- }
- }
-
- int messageLength() {
- if (dh_Yc == null) {
- return 0;
- } else {
- return dh_Yc.length + 2;
- }
- }
-
- void send(HandshakeOutStream s) throws IOException {
- if (dh_Yc != null && dh_Yc.length != 0) {
- s.putBytes16(dh_Yc);
- }
- }
-
- void print(PrintStream s) throws IOException {
- s.println("*** ClientKeyExchange, DH");
-
- if (debug != null && Debug.isOn("verbose")) {
- Debug.println(s, "DH Public key", dh_Yc);
- }
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/DHCrypt.java b/ojluni/src/main/java/sun/security/ssl/DHCrypt.java
deleted file mode 100755
index ae9118f..0000000
--- a/ojluni/src/main/java/sun/security/ssl/DHCrypt.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.math.BigInteger;
-import java.security.*;
-import java.io.IOException;
-import javax.net.ssl.SSLHandshakeException;
-import javax.crypto.SecretKey;
-import javax.crypto.KeyAgreement;
-import javax.crypto.interfaces.DHPublicKey;
-import javax.crypto.spec.*;
-
-import sun.security.util.KeyUtil;
-
-/**
- * This class implements the Diffie-Hellman key exchange algorithm.
- * D-H means combining your private key with your partners public key to
- * generate a number. The peer does the same with its private key and our
- * public key. Through the magic of Diffie-Hellman we both come up with the
- * same number. This number is secret (discounting MITM attacks) and hence
- * called the shared secret. It has the same length as the modulus, e.g. 512
- * or 1024 bit. Man-in-the-middle attacks are typically countered by an
- * independent authentication step using certificates (RSA, DSA, etc.).
- *
- * The thing to note is that the shared secret is constant for two partners
- * with constant private keys. This is often not what we want, which is why
- * it is generally a good idea to create a new private key for each session.
- * Generating a private key involves one modular exponentiation assuming
- * suitable D-H parameters are available.
- *
- * General usage of this class (TLS DHE case):
- * . if we are server, call DHCrypt(keyLength,random). This generates
- * an ephemeral keypair of the request length.
- * . if we are client, call DHCrypt(modulus, base, random). This
- * generates an ephemeral keypair using the parameters specified by
- * the server.
- * . send parameters and public value to remote peer
- * . receive peers ephemeral public key
- * . call getAgreedSecret() to calculate the shared secret
- *
- * In TLS the server chooses the parameter values itself, the client must use
- * those sent to it by the server.
- *
- * The use of ephemeral keys as described above also achieves what is called
- * "forward secrecy". This means that even if the authentication keys are
- * broken at a later date, the shared secret remains secure. The session is
- * compromised only if the authentication keys are already broken at the
- * time the key exchange takes place and an active MITM attack is used.
- * This is in contrast to straightforward encrypting RSA key exchanges.
- *
- * @author David Brownell
- */
-final class DHCrypt {
-
- // group parameters (prime modulus and generator)
- private BigInteger modulus; // P (aka N)
- private BigInteger base; // G (aka alpha)
-
- // our private key (including private component x)
- private PrivateKey privateKey;
-
- // public component of our key, X = (g ^ x) mod p
- private BigInteger publicValue; // X (aka y)
-
- // the times to recove from failure if public key validation
- private static int MAX_FAILOVER_TIMES = 2;
-
- /**
- * Generate a Diffie-Hellman keypair of the specified size.
- */
- DHCrypt(int keyLength, SecureRandom random) {
- try {
- KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman");
- kpg.initialize(keyLength, random);
-
- DHPublicKeySpec spec = generateDHPublicKeySpec(kpg);
- if (spec == null) {
- throw new RuntimeException("Could not generate DH keypair");
- }
-
- publicValue = spec.getY();
- modulus = spec.getP();
- base = spec.getG();
- } catch (GeneralSecurityException e) {
- throw new RuntimeException("Could not generate DH keypair", e);
- }
- }
-
-
- /**
- * Generate a Diffie-Hellman keypair using the specified parameters.
- *
- * @param modulus the Diffie-Hellman modulus P
- * @param base the Diffie-Hellman base G
- */
- DHCrypt(BigInteger modulus, BigInteger base, SecureRandom random) {
- this.modulus = modulus;
- this.base = base;
- try {
- KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("DiffieHellman");
- DHParameterSpec params = new DHParameterSpec(modulus, base);
- kpg.initialize(params, random);
-
- DHPublicKeySpec spec = generateDHPublicKeySpec(kpg);
- if (spec == null) {
- throw new RuntimeException("Could not generate DH keypair");
- }
-
- publicValue = spec.getY();
- } catch (GeneralSecurityException e) {
- throw new RuntimeException("Could not generate DH keypair", e);
- }
- }
-
-
- static DHPublicKeySpec getDHPublicKeySpec(PublicKey key) {
- if (key instanceof DHPublicKey) {
- DHPublicKey dhKey = (DHPublicKey)key;
- DHParameterSpec params = dhKey.getParams();
- return new DHPublicKeySpec(dhKey.getY(),
- params.getP(), params.getG());
- }
- try {
- KeyFactory factory = JsseJce.getKeyFactory("DH");
- return factory.getKeySpec(key, DHPublicKeySpec.class);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
-
- /** Returns the Diffie-Hellman modulus. */
- BigInteger getModulus() {
- return modulus;
- }
-
- /** Returns the Diffie-Hellman base (generator). */
- BigInteger getBase() {
- return base;
- }
-
- /**
- * Gets the public key of this end of the key exchange.
- */
- BigInteger getPublicKey() {
- return publicValue;
- }
-
- /**
- * Get the secret data that has been agreed on through Diffie-Hellman
- * key agreement protocol. Note that in the two party protocol, if
- * the peer keys are already known, no other data needs to be sent in
- * order to agree on a secret. That is, a secured message may be
- * sent without any mandatory round-trip overheads.
- *
- * <P>It is illegal to call this member function if the private key
- * has not been set (or generated).
- *
- * @param peerPublicKey the peer's public key.
- * @param keyIsValidated whether the {@code peerPublicKey} has beed
- * validated
- * @return the secret, which is an unsigned big-endian integer
- * the same size as the Diffie-Hellman modulus.
- */
- SecretKey getAgreedSecret(BigInteger peerPublicValue,
- boolean keyIsValidated) throws IOException {
- try {
- KeyFactory kf = JsseJce.getKeyFactory("DiffieHellman");
- DHPublicKeySpec spec =
- new DHPublicKeySpec(peerPublicValue, modulus, base);
- PublicKey publicKey = kf.generatePublic(spec);
- KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman");
-
- // validate the Diffie-Hellman public key
- if (!keyIsValidated &&
- !KeyUtil.isOracleJCEProvider(ka.getProvider().getName())) {
- try {
- KeyUtil.validate(spec);
- } catch (InvalidKeyException ike) {
- // prefer handshake_failure alert to internal_error alert
- throw new SSLHandshakeException(ike.getMessage());
- }
- }
-
- ka.init(privateKey);
- ka.doPhase(publicKey, true);
- return ka.generateSecret("TlsPremasterSecret");
- } catch (GeneralSecurityException e) {
- throw new RuntimeException("Could not generate secret", e);
- }
- }
-
- // Generate and validate DHPublicKeySpec
- private DHPublicKeySpec generateDHPublicKeySpec(KeyPairGenerator kpg)
- throws GeneralSecurityException {
-
- boolean doExtraValiadtion =
- (!KeyUtil.isOracleJCEProvider(kpg.getProvider().getName()));
- for (int i = 0; i <= MAX_FAILOVER_TIMES; i++) {
- KeyPair kp = kpg.generateKeyPair();
- privateKey = kp.getPrivate();
- DHPublicKeySpec spec = getDHPublicKeySpec(kp.getPublic());
-
- // validate the Diffie-Hellman public key
- if (doExtraValiadtion) {
- try {
- KeyUtil.validate(spec);
- } catch (InvalidKeyException ivke) {
- if (i == MAX_FAILOVER_TIMES) {
- throw ivke;
- }
- // otherwise, ignore the exception and try the next one
- continue;
- }
- }
-
- return spec;
- }
-
- return null;
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/Debug.java b/ojluni/src/main/java/sun/security/ssl/Debug.java
deleted file mode 100755
index a270816..0000000
--- a/ojluni/src/main/java/sun/security/ssl/Debug.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.PrintStream;
-import java.security.AccessController;
-import java.util.Locale;
-
-import sun.security.action.GetPropertyAction;
-
-/**
- * This class has be shamefully lifted from sun.security.util.Debug
- *
- * @author Gary Ellison
- */
-public class Debug {
-
- private String prefix;
-
- private static String args;
-
- static {
- args = java.security.AccessController.doPrivileged(
- new GetPropertyAction("javax.net.debug", ""));
- args = args.toLowerCase(Locale.ENGLISH);
- if (args.equals("help")) {
- Help();
- }
- }
-
- public static void Help()
- {
- System.err.println();
- System.err.println("all turn on all debugging");
- System.err.println("ssl turn on ssl debugging");
- System.err.println();
- System.err.println("The following can be used with ssl:");
- System.err.println("\trecord enable per-record tracing");
- System.err.println("\thandshake print each handshake message");
- System.err.println("\tkeygen print key generation data");
- System.err.println("\tsession print session activity");
- System.err.println("\tdefaultctx print default SSL initialization");
- System.err.println("\tsslctx print SSLContext tracing");
- System.err.println("\tsessioncache print session cache tracing");
- System.err.println("\tkeymanager print key manager tracing");
- System.err.println("\ttrustmanager print trust manager tracing");
- System.err.println("\tpluggability print pluggability tracing");
- System.err.println();
- System.err.println("\thandshake debugging can be widened with:");
- System.err.println("\tdata hex dump of each handshake message");
- System.err.println("\tverbose verbose handshake message printing");
- System.err.println();
- System.err.println("\trecord debugging can be widened with:");
- System.err.println("\tplaintext hex dump of record plaintext");
- System.err.println("\tpacket print raw SSL/TLS packets");
- System.err.println();
- System.exit(0);
- }
-
- /**
- * Get a Debug object corresponding to whether or not the given
- * option is set. Set the prefix to be the same as option.
- */
-
- public static Debug getInstance(String option)
- {
- return getInstance(option, option);
- }
-
- /**
- * Get a Debug object corresponding to whether or not the given
- * option is set. Set the prefix to be prefix.
- */
- public static Debug getInstance(String option, String prefix)
- {
- if (isOn(option)) {
- Debug d = new Debug();
- d.prefix = prefix;
- return d;
- } else {
- return null;
- }
- }
-
- /**
- * True if the property "javax.net.debug" contains the
- * string "option".
- */
- public static boolean isOn(String option)
- {
- if (args == null) {
- return false;
- } else {
- int n = 0;
- option = option.toLowerCase(Locale.ENGLISH);
-
- if (args.indexOf("all") != -1) {
- return true;
- } else if ((n = args.indexOf("ssl")) != -1) {
- if (args.indexOf("sslctx", n) == -1) {
- // don't enable data and plaintext options by default
- if (!(option.equals("data")
- || option.equals("packet")
- || option.equals("plaintext"))) {
- return true;
- }
- }
- }
- return (args.indexOf(option) != -1);
- }
- }
-
- /**
- * print a message to stderr that is prefixed with the prefix
- * created from the call to getInstance.
- */
-
- public void println(String message)
- {
- System.err.println(prefix + ": "+message);
- }
-
- /**
- * print a blank line to stderr that is prefixed with the prefix.
- */
-
- public void println()
- {
- System.err.println(prefix + ":");
- }
-
- /**
- * print a message to stderr that is prefixed with the prefix.
- */
-
- public static void println(String prefix, String message)
- {
- System.err.println(prefix + ": "+message);
- }
-
- public static void println(PrintStream s, String name, byte[] data) {
- s.print(name + ": { ");
- if (data == null) {
- s.print("null");
- } else {
- for (int i = 0; i < data.length; i++) {
- if (i != 0) s.print(", ");
- s.print(data[i] & 0x0ff);
- }
- }
- s.println(" }");
- }
-
- /**
- * Return the value of the boolean System property propName.
- *
- * Note use of doPrivileged(). Do make accessible to applications.
- */
- static boolean getBooleanProperty(String propName, boolean defaultValue) {
- // if set, require value of either true or false
- String b = AccessController.doPrivileged(
- new GetPropertyAction(propName));
- if (b == null) {
- return defaultValue;
- } else if (b.equalsIgnoreCase("false")) {
- return false;
- } else if (b.equalsIgnoreCase("true")) {
- return true;
- } else {
- throw new RuntimeException("Value of " + propName
- + " must either be 'true' or 'false'");
- }
- }
-
- static String toString(byte[] b) {
- return sun.security.util.Debug.toString(b);
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/ECDHClientKeyExchange.java b/ojluni/src/main/java/sun/security/ssl/ECDHClientKeyExchange.java
deleted file mode 100755
index d89945c..0000000
--- a/ojluni/src/main/java/sun/security/ssl/ECDHClientKeyExchange.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.IOException;
-import java.io.PrintStream;
-
-import java.security.PublicKey;
-import java.security.interfaces.ECPublicKey;
-import java.security.spec.*;
-
-/**
- * ClientKeyExchange message for all ECDH based key exchange methods. It
- * contains the client's ephemeral public value.
- *
- * @since 1.6
- * @author Andreas Sterbenz
- */
-final class ECDHClientKeyExchange extends HandshakeMessage {
-
- int messageType() {
- return ht_client_key_exchange;
- }
-
- private byte[] encodedPoint;
-
- byte[] getEncodedPoint() {
- return encodedPoint;
- }
-
- // Called by the client with its ephemeral public key.
- ECDHClientKeyExchange(PublicKey publicKey) {
- ECPublicKey ecKey = (ECPublicKey)publicKey;
- ECPoint point = ecKey.getW();
- ECParameterSpec params = ecKey.getParams();
- encodedPoint = JsseJce.encodePoint(point, params.getCurve());
- }
-
- ECDHClientKeyExchange(HandshakeInStream input) throws IOException {
- encodedPoint = input.getBytes8();
- }
-
- int messageLength() {
- return encodedPoint.length + 1;
- }
-
- void send(HandshakeOutStream s) throws IOException {
- s.putBytes8(encodedPoint);
- }
-
- void print(PrintStream s) throws IOException {
- s.println("*** ECDHClientKeyExchange");
-
- if (debug != null && Debug.isOn("verbose")) {
- Debug.println(s, "ECDH Public value", encodedPoint);
- }
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/ECDHCrypt.java b/ojluni/src/main/java/sun/security/ssl/ECDHCrypt.java
deleted file mode 100755
index 84dc467..0000000
--- a/ojluni/src/main/java/sun/security/ssl/ECDHCrypt.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.security.*;
-import java.security.interfaces.ECPublicKey;
-import java.security.spec.*;
-
-import javax.crypto.SecretKey;
-import javax.crypto.KeyAgreement;
-import javax.crypto.spec.*;
-
-/**
- * Helper class for the ECDH key exchange. It generates the appropriate
- * ephemeral keys as necessary and performs the actual shared secret derivation.
- *
- * @since 1.6
- * @author Andreas Sterbenz
- */
-final class ECDHCrypt {
-
- // our private key
- private PrivateKey privateKey;
-
- // our public key
- private ECPublicKey publicKey;
-
- // Called by ServerHandshaker for static ECDH
- ECDHCrypt(PrivateKey privateKey, PublicKey publicKey) {
- this.privateKey = privateKey;
- this.publicKey = (ECPublicKey)publicKey;
- }
-
- // Called by ServerHandshaker for ephemeral ECDH
- ECDHCrypt(String curveName, SecureRandom random) {
- try {
- KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
- ECGenParameterSpec params = new ECGenParameterSpec(curveName);
- kpg.initialize(params, random);
- KeyPair kp = kpg.generateKeyPair();
- privateKey = kp.getPrivate();
- publicKey = (ECPublicKey)kp.getPublic();
- } catch (GeneralSecurityException e) {
- throw new RuntimeException("Could not generate DH keypair", e);
- }
- }
-
- // Called by ClientHandshaker with params it received from the server
- ECDHCrypt(ECParameterSpec params, SecureRandom random) {
- try {
- KeyPairGenerator kpg = JsseJce.getKeyPairGenerator("EC");
- kpg.initialize(params, random);
- KeyPair kp = kpg.generateKeyPair();
- privateKey = kp.getPrivate();
- publicKey = (ECPublicKey)kp.getPublic();
- } catch (GeneralSecurityException e) {
- throw new RuntimeException("Could not generate DH keypair", e);
- }
- }
-
- /**
- * Gets the public key of this end of the key exchange.
- */
- PublicKey getPublicKey() {
- return publicKey;
- }
-
- // called by ClientHandshaker with either the server's static or ephemeral public key
- SecretKey getAgreedSecret(PublicKey peerPublicKey) {
- try {
- KeyAgreement ka = JsseJce.getKeyAgreement("ECDH");
- ka.init(privateKey);
- ka.doPhase(peerPublicKey, true);
- return ka.generateSecret("TlsPremasterSecret");
- } catch (GeneralSecurityException e) {
- throw new RuntimeException("Could not generate secret", e);
- }
- }
-
- // called by ServerHandshaker
- SecretKey getAgreedSecret(byte[] encodedPoint) {
- try {
- ECParameterSpec params = publicKey.getParams();
- ECPoint point = JsseJce.decodePoint(encodedPoint, params.getCurve());
- KeyFactory kf = JsseJce.getKeyFactory("EC");
- ECPublicKeySpec spec = new ECPublicKeySpec(point, params);
- PublicKey peerPublicKey = kf.generatePublic(spec);
- return getAgreedSecret(peerPublicKey);
- } catch (GeneralSecurityException e) {
- throw new RuntimeException("Could not generate secret", e);
- } catch (java.io.IOException e) {
- throw new RuntimeException("Could not generate secret", e);
- }
- }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/EngineArgs.java b/ojluni/src/main/java/sun/security/ssl/EngineArgs.java
deleted file mode 100755
index 5f89d0c..0000000
--- a/ojluni/src/main/java/sun/security/ssl/EngineArgs.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.nio.*;
-
-/*
- * A multi-purpose class which handles all of the SSLEngine arguments.
- * It validates arguments, checks for RO conditions, does space
- * calculations, performs scatter/gather, etc.
- *
- * @author Brad R. Wetmore
- */
-class EngineArgs {
-
- /*
- * Keep track of the input parameters.
- */
- ByteBuffer netData;
- ByteBuffer [] appData;
-
- private int offset; // offset/len for the appData array.
- private int len;
-
- /*
- * The initial pos/limit conditions. This is useful because we can
- * quickly calculate the amount consumed/produced in successful
- * operations, or easily return the buffers to their pre-error
- * conditions.
- */
- private int netPos;
- private int netLim;
-
- private int [] appPoss;
- private int [] appLims;
-
- /*
- * Sum total of the space remaining in all of the appData buffers
- */
- private int appRemaining = 0;
-
- private boolean wrapMethod;
-
- /*
- * Called by the SSLEngine.wrap() method.
- */
- EngineArgs(ByteBuffer [] appData, int offset, int len,
- ByteBuffer netData) {
- this.wrapMethod = true;
- init(netData, appData, offset, len);
- }
-
- /*
- * Called by the SSLEngine.unwrap() method.
- */
- EngineArgs(ByteBuffer netData, ByteBuffer [] appData, int offset,
- int len) {
- this.wrapMethod = false;
- init(netData, appData, offset, len);
- }
-
- /*
- * The main initialization method for the arguments. Most
- * of them are pretty obvious as to what they do.
- *
- * Since we're already iterating over appData array for validity
- * checking, we also keep track of how much remainging space is
- * available. Info is used in both unwrap (to see if there is
- * enough space available in the destination), and in wrap (to
- * determine how much more we can copy into the outgoing data
- * buffer.
- */
- private void init(ByteBuffer netData, ByteBuffer [] appData,
- int offset, int len) {
-
- if ((netData == null) || (appData == null)) {
- throw new IllegalArgumentException("src/dst is null");
- }
-
- if ((offset < 0) || (len < 0) || (offset > appData.length - len)) {
- throw new IndexOutOfBoundsException();
- }
-
- if (wrapMethod && netData.isReadOnly()) {
- throw new ReadOnlyBufferException();
- }
-
- netPos = netData.position();
- netLim = netData.limit();
-
- appPoss = new int [appData.length];
- appLims = new int [appData.length];
-
- for (int i = offset; i < offset + len; i++) {
- if (appData[i] == null) {
- throw new IllegalArgumentException(
- "appData[" + i + "] == null");
- }
-
- /*
- * If we're unwrapping, then check to make sure our
- * destination bufffers are writable.
- */
- if (!wrapMethod && appData[i].isReadOnly()) {
- throw new ReadOnlyBufferException();
- }
-
- appRemaining += appData[i].remaining();
-
- appPoss[i] = appData[i].position();
- appLims[i] = appData[i].limit();
- }
-
- /*
- * Ok, looks like we have a good set of args, let's
- * store the rest of this stuff.
- */
- this.netData = netData;
- this.appData = appData;
- this.offset = offset;
- this.len = len;
- }
-
- /*
- * Given spaceLeft bytes to transfer, gather up that much data
- * from the appData buffers (starting at offset in the array),
- * and transfer it into the netData buffer.
- *
- * The user has already ensured there is enough room.
- */
- void gather(int spaceLeft) {
- for (int i = offset; (i < (offset + len)) && (spaceLeft > 0); i++) {
- int amount = Math.min(appData[i].remaining(), spaceLeft);
- appData[i].limit(appData[i].position() + amount);
- netData.put(appData[i]);
- appRemaining -= amount;
- spaceLeft -= amount;
- }
- }
-
- /*
- * Using the supplied buffer, scatter the data into the appData buffers
- * (starting at offset in the array).
- *
- * The user has already ensured there is enough room.
- */
- void scatter(ByteBuffer readyData) {
- int amountLeft = readyData.remaining();
-
- for (int i = offset; (i < (offset + len)) && (amountLeft > 0);
- i++) {
- int amount = Math.min(appData[i].remaining(), amountLeft);
- readyData.limit(readyData.position() + amount);
- appData[i].put(readyData);
- amountLeft -= amount;
- }
- assert(readyData.remaining() == 0);
- }
-
- int getAppRemaining() {
- return appRemaining;
- }
-
- /*
- * Calculate the bytesConsumed/byteProduced. Aren't you glad
- * we saved this off earlier?
- */
- int deltaNet() {
- return (netData.position() - netPos);
- }
-
- /*
- * Calculate the bytesConsumed/byteProduced. Aren't you glad
- * we saved this off earlier?
- */
- int deltaApp() {
- int sum = 0; // Only calculating 2^14 here, don't need a long.
-
- for (int i = offset; i < offset + len; i++) {
- sum += appData[i].position() - appPoss[i];
- }
-
- return sum;
- }
-
- /*
- * In the case of Exception, we want to reset the positions
- * to appear as though no data has been consumed or produced.
- *
- * Currently, this method is only called as we are preparing to
- * fail out, and thus we don't need to actually recalculate
- * appRemaining. If that assumption changes, that variable should
- * be updated here.
- */
- void resetPos() {
- netData.position(netPos);
- for (int i = offset; i < offset + len; i++) {
- // See comment above about recalculating appRemaining.
- appData[i].position(appPoss[i]);
- }
- }
-
- /*
- * We are doing lots of ByteBuffer manipulations, in which case
- * we need to make sure that the limits get set back correctly.
- * This is one of the last things to get done before returning to
- * the user.
- */
- void resetLim() {
- netData.limit(netLim);
- for (int i = offset; i < offset + len; i++) {
- appData[i].limit(appLims[i]);
- }
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/EngineInputRecord.java b/ojluni/src/main/java/sun/security/ssl/EngineInputRecord.java
deleted file mode 100755
index fb7b133..0000000
--- a/ojluni/src/main/java/sun/security/ssl/EngineInputRecord.java
+++ /dev/null
@@ -1,438 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.nio.*;
-import javax.net.ssl.*;
-import javax.crypto.BadPaddingException;
-import sun.misc.HexDumpEncoder;
-
-
-/**
- * Wrapper class around InputRecord.
- *
- * Application data is kept external to the InputRecord,
- * but handshake data (alert/change_cipher_spec/handshake) will
- * be kept internally in the ByteArrayInputStream.
- *
- * @author Brad Wetmore
- */
-final class EngineInputRecord extends InputRecord {
-
- private SSLEngineImpl engine;
-
- /*
- * A dummy ByteBuffer we'll pass back even when the data
- * is stored internally. It'll never actually be used.
- */
- static private ByteBuffer tmpBB = ByteBuffer.allocate(0);
-
- /*
- * Flag to tell whether the last read/parsed data resides
- * internal in the ByteArrayInputStream, or in the external
- * buffers.
- */
- private boolean internalData;
-
- EngineInputRecord(SSLEngineImpl engine) {
- super();
- this.engine = engine;
- }
-
- byte contentType() {
- if (internalData) {
- return super.contentType();
- } else {
- return ct_application_data;
- }
- }
-
- /*
- * Check if there is enough inbound data in the ByteBuffer
- * to make a inbound packet. Look for both SSLv2 and SSLv3.
- *
- * @return -1 if there are not enough bytes to tell (small header),
- */
- int bytesInCompletePacket(ByteBuffer buf) throws SSLException {
-
- /*
- * SSLv2 length field is in bytes 0/1
- * SSLv3/TLS length field is in bytes 3/4
- */
- if (buf.remaining() < 5) {
- return -1;
- }
-
- int pos = buf.position();
- byte byteZero = buf.get(pos);
-
- int len = 0;
-
- /*
- * If we have already verified previous packets, we can
- * ignore the verifications steps, and jump right to the
- * determination. Otherwise, try one last hueristic to
- * see if it's SSL/TLS.
- */
- if (formatVerified ||
- (byteZero == ct_handshake) ||
- (byteZero == ct_alert)) {
- /*
- * Last sanity check that it's not a wild record
- */
- ProtocolVersion recordVersion =
- ProtocolVersion.valueOf(buf.get(pos + 1), buf.get(pos + 2));
-
- // Check if too old (currently not possible)
- // or if the major version does not match.
- // The actual version negotiation is in the handshaker classes
- if ((recordVersion.v < ProtocolVersion.MIN.v)
- || (recordVersion.major > ProtocolVersion.MAX.major)) {
- throw new SSLException(
- "Unsupported record version " + recordVersion);
- }
-
- /*
- * Reasonably sure this is a V3, disable further checks.
- * We can't do the same in the v2 check below, because
- * read still needs to parse/handle the v2 clientHello.
- */
- formatVerified = true;
-
- /*
- * One of the SSLv3/TLS message types.
- */
- len = ((buf.get(pos + 3) & 0xff) << 8) +
- (buf.get(pos + 4) & 0xff) + headerSize;
-
- } else {
- /*
- * Must be SSLv2 or something unknown.
- * Check if it's short (2 bytes) or
- * long (3) header.
- *
- * Internals can warn about unsupported SSLv2
- */
- boolean isShort = ((byteZero & 0x80) != 0);
-
- if (isShort &&
- ((buf.get(pos + 2) == 1) || buf.get(pos + 2) == 4)) {
-
- ProtocolVersion recordVersion =
- ProtocolVersion.valueOf(buf.get(pos + 3), buf.get(pos + 4));
-
- // Check if too old (currently not possible)
- // or if the major version does not match.
- // The actual version negotiation is in the handshaker classes
- if ((recordVersion.v < ProtocolVersion.MIN.v)
- || (recordVersion.major > ProtocolVersion.MAX.major)) {
-
- // if it's not SSLv2, we're out of here.
- if (recordVersion.v != ProtocolVersion.SSL20Hello.v) {
- throw new SSLException(
- "Unsupported record version " + recordVersion);
- }
- }
-
- /*
- * Client or Server Hello
- */
- int mask = (isShort ? 0x7f : 0x3f);
- len = ((byteZero & mask) << 8) + (buf.get(pos + 1) & 0xff) +
- (isShort ? 2 : 3);
-
- } else {
- // Gobblygook!
- throw new SSLException(
- "Unrecognized SSL message, plaintext connection?");
- }
- }
-
- return len;
- }
-
- /*
- * Pass the data down if it's internally cached, otherwise
- * do it here.
- *
- * If internal data, data is decrypted internally.
- *
- * If external data(app), return a new ByteBuffer with data to
- * process.
- */
- ByteBuffer decrypt(MAC signer,
- CipherBox box, ByteBuffer bb) throws BadPaddingException {
-
- if (internalData) {
- decrypt(signer, box); // MAC is checked during decryption
- return tmpBB;
- }
-
- BadPaddingException reservedBPE = null;
- int tagLen = signer.MAClen();
- int cipheredLength = bb.remaining();
-
- if (!box.isNullCipher()) {
- // sanity check length of the ciphertext
- if (!box.sanityCheck(tagLen, cipheredLength)) {
- throw new BadPaddingException(
- "ciphertext sanity check failed");
- }
-
- try {
- // Note that the CipherBox.decrypt() does not change
- // the capacity of the buffer.
- box.decrypt(bb, tagLen);
- } catch (BadPaddingException bpe) {
- // RFC 2246 states that decryption_failed should be used
- // for this purpose. However, that allows certain attacks,
- // so we just send bad record MAC. We also need to make
- // sure to always check the MAC to avoid a timing attack
- // for the same issue. See paper by Vaudenay et al and the
- // update in RFC 4346/5246.
- //
- // Failover to message authentication code checking.
- reservedBPE = bpe;
- } finally {
- bb.rewind();
- }
- }
-
- if (tagLen != 0) {
- int macOffset = bb.limit() - tagLen;
-
- // Note that although it is not necessary, we run the same MAC
- // computation and comparison on the payload for both stream
- // cipher and CBC block cipher.
- if (bb.remaining() < tagLen) {
- // negative data length, something is wrong
- if (reservedBPE == null) {
- reservedBPE = new BadPaddingException("bad record");
- }
-
- // set offset of the dummy MAC
- macOffset = cipheredLength - tagLen;
- bb.limit(cipheredLength);
- }
-
- // Run MAC computation and comparison on the payload.
- if (checkMacTags(contentType(), bb, signer, false)) {
- if (reservedBPE == null) {
- reservedBPE = new BadPaddingException("bad record MAC");
- }
- }
-
- // Run MAC computation and comparison on the remainder.
- //
- // It is only necessary for CBC block cipher. It is used to get a
- // constant time of MAC computation and comparison on each record.
- if (box.isCBCMode()) {
- int remainingLen = calculateRemainingLen(
- signer, cipheredLength, macOffset);
-
- // NOTE: here we use the InputRecord.buf because I did not find
- // an effective way to work on ByteBuffer when its capacity is
- // less than remainingLen.
-
- // NOTE: remainingLen may be bigger (less than 1 block of the
- // hash algorithm of the MAC) than the cipheredLength. However,
- // We won't need to worry about it because we always use a
- // maximum buffer for every record. We need a change here if
- // we use small buffer size in the future.
- if (remainingLen > buf.length) {
- // unlikely to happen, just a placehold
- throw new RuntimeException(
- "Internal buffer capacity error");
- }
-
- // Won't need to worry about the result on the remainder. And
- // then we won't need to worry about what's actual data to
- // check MAC tag on. We start the check from the header of the
- // buffer so that we don't need to construct a new byte buffer.
- checkMacTags(contentType(), buf, 0, remainingLen, signer, true);
- }
-
- bb.limit(macOffset);
- }
-
- // Is it a failover?
- if (reservedBPE != null) {
- throw reservedBPE;
- }
-
- return bb.slice();
- }
-
- /*
- * Run MAC computation and comparison
- *
- * Please DON'T change the content of the ByteBuffer parameter!
- */
- private static boolean checkMacTags(byte contentType, ByteBuffer bb,
- MAC signer, boolean isSimulated) {
-
- int tagLen = signer.MAClen();
- int lim = bb.limit();
- int macData = lim - tagLen;
-
- bb.limit(macData);
- byte[] hash = signer.compute(contentType, bb, isSimulated);
- if (hash == null || tagLen != hash.length) {
- // Something is wrong with MAC implementation.
- throw new RuntimeException("Internal MAC error");
- }
-
- bb.position(macData);
- bb.limit(lim);
- try {
- int[] results = compareMacTags(bb, hash);
- return (results[0] != 0);
- } finally {
- bb.rewind();
- bb.limit(macData);
- }
- }
-
- /*
- * A constant-time comparison of the MAC tags.
- *
- * Please DON'T change the content of the ByteBuffer parameter!
- */
- private static int[] compareMacTags(ByteBuffer bb, byte[] tag) {
-
- // An array of hits is used to prevent Hotspot optimization for
- // the purpose of a constant-time check.
- int[] results = {0, 0}; // {missed #, matched #}
-
- // The caller ensures there are enough bytes available in the buffer.
- // So we won't need to check the remaining of the buffer.
- for (int i = 0; i < tag.length; i++) {
- if (bb.get() != tag[i]) {
- results[0]++; // mismatched bytes
- } else {
- results[1]++; // matched bytes
- }
- }
-
- return results;
- }
-
- /*
- * Override the actual write below. We do things this way to be
- * consistent with InputRecord. InputRecord may try to write out
- * data to the peer, and *then* throw an Exception. This forces
- * data to be generated/output before the exception is ever
- * generated.
- */
- void writeBuffer(OutputStream s, byte [] buf, int off, int len)
- throws IOException {
- /*
- * Copy data out of buffer, it's ready to go.
- */
- ByteBuffer netBB = (ByteBuffer)
- (ByteBuffer.allocate(len).put(buf, 0, len).flip());
- engine.writer.putOutboundDataSync(netBB);
- }
-
- /*
- * Delineate or read a complete packet from src.
- *
- * If internal data (hs, alert, ccs), the data is read and
- * stored internally.
- *
- * If external data (app), return a new ByteBuffer which points
- * to the data to process.
- */
- ByteBuffer read(ByteBuffer srcBB) throws IOException {
- /*
- * Could have a src == null/dst == null check here,
- * but that was already checked by SSLEngine.unwrap before
- * ever attempting to read.
- */
-
- /*
- * If we have anything besides application data,
- * or if we haven't even done the initial v2 verification,
- * we send this down to be processed by the underlying
- * internal cache.
- */
- if (!formatVerified ||
- (srcBB.get(srcBB.position()) != ct_application_data)) {
- internalData = true;
- read(new ByteBufferInputStream(srcBB), (OutputStream) null);
- return tmpBB;
- }
-
- internalData = false;
-
- int srcPos = srcBB.position();
- int srcLim = srcBB.limit();
-
- ProtocolVersion recordVersion = ProtocolVersion.valueOf(
- srcBB.get(srcPos + 1), srcBB.get(srcPos + 2));
- // Check if too old (currently not possible)
- // or if the major version does not match.
- // The actual version negotiation is in the handshaker classes
- if ((recordVersion.v < ProtocolVersion.MIN.v)
- || (recordVersion.major > ProtocolVersion.MAX.major)) {
- throw new SSLException(
- "Unsupported record version " + recordVersion);
- }
-
- /*
- * It's really application data. How much to consume?
- * Jump over the header.
- */
- int len = bytesInCompletePacket(srcBB);
- assert(len > 0);
-
- if (debug != null && Debug.isOn("packet")) {
- try {
- HexDumpEncoder hd = new HexDumpEncoder();
- srcBB.limit(srcPos + len);
- ByteBuffer bb = srcBB.duplicate(); // Use copy of BB
-
- System.out.println("[Raw read (bb)]: length = " + len);
- hd.encodeBuffer(bb, System.out);
- } catch (IOException e) { }
- }
-
- // Demarcate past header to end of packet.
- srcBB.position(srcPos + headerSize);
- srcBB.limit(srcPos + len);
-
- // Protect remainder of buffer, create slice to actually
- // operate on.
- ByteBuffer bb = srcBB.slice();
-
- srcBB.position(srcBB.limit());
- srcBB.limit(srcLim);
-
- return bb;
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/EngineOutputRecord.java b/ojluni/src/main/java/sun/security/ssl/EngineOutputRecord.java
deleted file mode 100755
index c7605fd..0000000
--- a/ojluni/src/main/java/sun/security/ssl/EngineOutputRecord.java
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.nio.*;
-
-import javax.net.ssl.SSLException;
-import sun.misc.HexDumpEncoder;
-
-
-/**
- * A OutputRecord class extension which uses external ByteBuffers
- * or the internal ByteArrayOutputStream for data manipulations.
- * <P>
- * Instead of rewriting this entire class
- * to use ByteBuffers, we leave things intact, so handshake, CCS,
- * and alerts will continue to use the internal buffers, but application
- * data will use external buffers.
- *
- * @author Brad Wetmore
- */
-final class EngineOutputRecord extends OutputRecord {
-
- private SSLEngineImpl engine;
- private EngineWriter writer;
-
- private boolean finishedMsg = false;
-
- /*
- * All handshake hashing is done by the superclass
- */
-
- /*
- * Default constructor makes a record supporting the maximum
- * SSL record size. It allocates the header bytes directly.
- *
- * @param type the content type for the record
- */
- EngineOutputRecord(byte type, SSLEngineImpl engine) {
- super(type, recordSize(type));
- this.engine = engine;
- writer = engine.writer;
- }
-
- /**
- * Get the size of the buffer we need for records of the specified
- * type.
- * <P>
- * Application data buffers will provide their own byte buffers,
- * and will not use the internal byte caching.
- */
- private static int recordSize(byte type) {
- switch (type) {
-
- case ct_change_cipher_spec:
- case ct_alert:
- return maxAlertRecordSize;
-
- case ct_handshake:
- return maxRecordSize;
-
- case ct_application_data:
- return 0;
- }
-
- throw new RuntimeException("Unknown record type: " + type);
- }
-
- void setFinishedMsg() {
- finishedMsg = true;
- }
-
- public void flush() throws IOException {
- finishedMsg = false;
- }
-
- boolean isFinishedMsg() {
- return finishedMsg;
- }
-
-
- /**
- * Calculate the MAC value, storing the result either in
- * the internal buffer, or at the end of the destination
- * ByteBuffer.
- * <P>
- * We assume that the higher levels have assured us enough
- * room, otherwise we'll indirectly throw a
- * BufferOverFlowException runtime exception.
- *
- * position should equal limit, and points to the next
- * free spot.
- */
- private void addMAC(MAC signer, ByteBuffer bb)
- throws IOException {
-
- if (signer.MAClen() != 0) {
- byte[] hash = signer.compute(contentType(), bb, false);
-
- /*
- * position was advanced to limit in compute above.
- *
- * Mark next area as writable (above layers should have
- * established that we have plenty of room), then write
- * out the hash.
- */
- bb.limit(bb.limit() + hash.length);
- bb.put(hash);
- }
- }
-
- /*
- * Encrypt a ByteBuffer.
- *
- * We assume that the higher levels have assured us enough
- * room for the encryption (plus padding), otherwise we'll
- * indirectly throw a BufferOverFlowException runtime exception.
- *
- * position and limit will be the same, and points to the
- * next free spot.
- */
- void encrypt(CipherBox box, ByteBuffer bb) {
- box.encrypt(bb);
- }
-
- /*
- * Override the actual write below. We do things this way to be
- * consistent with InputRecord. InputRecord may try to write out
- * data to the peer, and *then* throw an Exception. This forces
- * data to be generated/output before the exception is ever
- * generated.
- */
- @Override
- void writeBuffer(OutputStream s, byte [] buf, int off, int len,
- int debugOffset) throws IOException {
- /*
- * Copy data out of buffer, it's ready to go.
- */
- ByteBuffer netBB = (ByteBuffer)
- ByteBuffer.allocate(len).put(buf, 0, len).flip();
- writer.putOutboundData(netBB);
- }
-
- /*
- * Main method for writing non-application data.
- * We MAC/encrypt, then send down for processing.
- */
- void write(MAC writeMAC, CipherBox writeCipher) throws IOException {
- /*
- * Sanity check.
- */
- switch (contentType()) {
- case ct_change_cipher_spec:
- case ct_alert:
- case ct_handshake:
- break;
- default:
- throw new RuntimeException("unexpected byte buffers");
- }
-
- /*
- * Don't bother to really write empty records. We went this
- * far to drive the handshake machinery, for correctness; not
- * writing empty records improves performance by cutting CPU
- * time and network resource usage. Also, some protocol
- * implementations are fragile and don't like to see empty
- * records, so this increases robustness.
- *
- * (Even change cipher spec messages have a byte of data!)
- */
- if (!isEmpty()) {
- // compress(); // eventually
- addMAC(writeMAC);
- encrypt(writeCipher);
- write((OutputStream)null, false, // send down for processing
- (ByteArrayOutputStream)null);
- }
- return;
- }
-
- /**
- * Main wrap/write driver.
- */
- void write(EngineArgs ea, MAC writeMAC, CipherBox writeCipher)
- throws IOException {
- /*
- * sanity check to make sure someone didn't inadvertantly
- * send us an impossible combination we don't know how
- * to process.
- */
- assert(contentType() == ct_application_data);
-
- /*
- * Have we set the MAC's yet? If not, we're not ready
- * to process application data yet.
- */
- if (writeMAC == MAC.NULL) {
- return;
- }
-
- /*
- * Don't bother to really write empty records. We went this
- * far to drive the handshake machinery, for correctness; not
- * writing empty records improves performance by cutting CPU
- * time and network resource usage. Also, some protocol
- * implementations are fragile and don't like to see empty
- * records, so this increases robustness.
- */
- if (ea.getAppRemaining() == 0) {
- return;
- }
-
- /*
- * By default, we counter chosen plaintext issues on CBC mode
- * ciphersuites in SSLv3/TLS1.0 by sending one byte of application
- * data in the first record of every payload, and the rest in
- * subsequent record(s). Note that the issues have been solved in
- * TLS 1.1 or later.
- *
- * It is not necessary to split the very first application record of
- * a freshly negotiated TLS session, as there is no previous
- * application data to guess. To improve compatibility, we will not
- * split such records.
- *
- * Because of the compatibility, we'd better produce no more than
- * SSLSession.getPacketBufferSize() net data for each wrap. As we
- * need a one-byte record at first, the 2nd record size should be
- * equal to or less than Record.maxDataSizeMinusOneByteRecord.
- *
- * This avoids issues in the outbound direction. For a full fix,
- * the peer must have similar protections.
- */
- int length;
- if (engine.needToSplitPayload(writeCipher, protocolVersion)) {
- write(ea, writeMAC, writeCipher, 0x01);
- ea.resetLim(); // reset application data buffer limit
- length = Math.min(ea.getAppRemaining(),
- maxDataSizeMinusOneByteRecord);
- } else {
- length = Math.min(ea.getAppRemaining(), maxDataSize);
- }
-
- // Don't bother to really write empty records.
- if (length > 0) {
- write(ea, writeMAC, writeCipher, length);
- }
-
- return;
- }
-
- void write(EngineArgs ea, MAC writeMAC, CipherBox writeCipher,
- int length) throws IOException {
- /*
- * Copy out existing buffer values.
- */
- ByteBuffer dstBB = ea.netData;
- int dstPos = dstBB.position();
- int dstLim = dstBB.limit();
-
- /*
- * Where to put the data. Jump over the header.
- *
- * Don't need to worry about SSLv2 rewrites, if we're here,
- * that's long since done.
- */
- int dstData = dstPos + headerSize;
- dstBB.position(dstData);
-
- ea.gather(length);
-
- /*
- * "flip" but skip over header again, add MAC & encrypt
- * addMAC will expand the limit to reflect the new
- * data.
- */
- dstBB.limit(dstBB.position());
- dstBB.position(dstData);
- addMAC(writeMAC, dstBB);
-
- /*
- * Encrypt may pad, so again the limit may have changed.
- */
- dstBB.limit(dstBB.position());
- dstBB.position(dstData);
- encrypt(writeCipher, dstBB);
-
- if (debug != null
- && (Debug.isOn("record") || Debug.isOn("handshake"))) {
- if ((debug != null && Debug.isOn("record"))
- || contentType() == ct_change_cipher_spec)
- System.out.println(Thread.currentThread().getName()
- // v3.0/v3.1 ...
- + ", WRITE: " + protocolVersion
- + " " + InputRecord.contentName(contentType())
- + ", length = " + length);
- }
-
- int packetLength = dstBB.limit() - dstData;
-
- /*
- * Finish out the record header.
- */
- dstBB.put(dstPos, contentType());
- dstBB.put(dstPos + 1, protocolVersion.major);
- dstBB.put(dstPos + 2, protocolVersion.minor);
- dstBB.put(dstPos + 3, (byte)(packetLength >> 8));
- dstBB.put(dstPos + 4, (byte)packetLength);
-
- /*
- * Position was already set by encrypt() above.
- */
- dstBB.limit(dstLim);
-
- return;
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/EngineWriter.java b/ojluni/src/main/java/sun/security/ssl/EngineWriter.java
deleted file mode 100755
index c930af7..0000000
--- a/ojluni/src/main/java/sun/security/ssl/EngineWriter.java
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import javax.net.ssl.*;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.LinkedList;
-import javax.net.ssl.SSLEngineResult.HandshakeStatus;
-import sun.misc.HexDumpEncoder;
-
-/**
- * A class to help abstract away SSLEngine writing synchronization.
- */
-final class EngineWriter {
-
- /*
- * Outgoing handshake Data waiting for a ride is stored here.
- * Normal application data is written directly into the outbound
- * buffer, but handshake data can be written out at any time,
- * so we have buffer it somewhere.
- *
- * When wrap is called, we first check to see if there is
- * any data waiting, then if we're in a data transfer state,
- * we try to write app data.
- *
- * This will contain either ByteBuffers, or the marker
- * HandshakeStatus.FINISHED to signify that a handshake just completed.
- */
- private LinkedList<Object> outboundList;
-
- private boolean outboundClosed = false;
-
- /* Class and subclass dynamic debugging support */
- private static final Debug debug = Debug.getInstance("ssl");
-
- EngineWriter() {
- outboundList = new LinkedList<Object>();
- }
-
- /*
- * Upper levels assured us we had room for at least one packet of data.
- * As per the SSLEngine spec, we only return one SSL packets worth of
- * data.
- */
- private HandshakeStatus getOutboundData(ByteBuffer dstBB) {
-
- Object msg = outboundList.removeFirst();
- assert(msg instanceof ByteBuffer);
-
- ByteBuffer bbIn = (ByteBuffer) msg;
- assert(dstBB.remaining() >= bbIn.remaining());
-
- dstBB.put(bbIn);
-
- /*
- * If we have more data in the queue, it's either
- * a finished message, or an indication that we need
- * to call wrap again.
- */
- if (hasOutboundDataInternal()) {
- msg = outboundList.getFirst();
- if (msg == HandshakeStatus.FINISHED) {
- outboundList.removeFirst(); // consume the message
- return HandshakeStatus.FINISHED;
- } else {
- return HandshakeStatus.NEED_WRAP;
- }
- } else {
- return null;
- }
- }
-
- /*
- * Properly orders the output of the data written to the wrap call.
- * This is only handshake data, application data goes through the
- * other writeRecord.
- */
- synchronized void writeRecord(EngineOutputRecord outputRecord,
- MAC writeMAC, CipherBox writeCipher) throws IOException {
-
- /*
- * Only output if we're still open.
- */
- if (outboundClosed) {
- throw new IOException("writer side was already closed.");
- }
-
- outputRecord.write(writeMAC, writeCipher);
-
- /*
- * Did our handshakers notify that we just sent the
- * Finished message?
- *
- * Add an "I'm finished" message to the queue.
- */
- if (outputRecord.isFinishedMsg()) {
- outboundList.addLast(HandshakeStatus.FINISHED);
- }
- }
-
- /*
- * Output the packet info.
- */
- private void dumpPacket(EngineArgs ea, boolean hsData) {
- try {
- HexDumpEncoder hd = new HexDumpEncoder();
-
- ByteBuffer bb = ea.netData.duplicate();
-
- int pos = bb.position();
- bb.position(pos - ea.deltaNet());
- bb.limit(pos);
-
- System.out.println("[Raw write" +
- (hsData ? "" : " (bb)") + "]: length = " +
- bb.remaining());
- hd.encodeBuffer(bb, System.out);
- } catch (IOException e) { }
- }
-
- /*
- * Properly orders the output of the data written to the wrap call.
- * Only app data goes through here, handshake data goes through
- * the other writeRecord.
- *
- * Shouldn't expect to have an IOException here.
- *
- * Return any determined status.
- */
- synchronized HandshakeStatus writeRecord(
- EngineOutputRecord outputRecord, EngineArgs ea, MAC writeMAC,
- CipherBox writeCipher) throws IOException {
-
- /*
- * If we have data ready to go, output this first before
- * trying to consume app data.
- */
- if (hasOutboundDataInternal()) {
- HandshakeStatus hss = getOutboundData(ea.netData);
-
- if (debug != null && Debug.isOn("packet")) {
- /*
- * We could have put the dump in
- * OutputRecord.write(OutputStream), but let's actually
- * output when it's actually output by the SSLEngine.
- */
- dumpPacket(ea, true);
- }
-
- return hss;
- }
-
- /*
- * If we are closed, no more app data can be output.
- * Only existing handshake data (above) can be obtained.
- */
- if (outboundClosed) {
- throw new IOException("The write side was already closed");
- }
-
- outputRecord.write(ea, writeMAC, writeCipher);
-
- if (debug != null && Debug.isOn("packet")) {
- dumpPacket(ea, false);
- }
-
- /*
- * No way new outbound handshake data got here if we're
- * locked properly.
- *
- * We don't have any status we can return.
- */
- return null;
- }
-
- /*
- * We already hold "this" lock, this is the callback from the
- * outputRecord.write() above. We already know this
- * writer can accept more data (outboundClosed == false),
- * and the closure is sync'd.
- */
- void putOutboundData(ByteBuffer bytes) {
- outboundList.addLast(bytes);
- }
-
- /*
- * This is for the really rare case that someone is writing from
- * the *InputRecord* before we know what to do with it.
- */
- synchronized void putOutboundDataSync(ByteBuffer bytes)
- throws IOException {
-
- if (outboundClosed) {
- throw new IOException("Write side already closed");
- }
-
- outboundList.addLast(bytes);
- }
-
- /*
- * Non-synch'd version of this method, called by internals
- */
- private boolean hasOutboundDataInternal() {
- return (outboundList.size() != 0);
- }
-
- synchronized boolean hasOutboundData() {
- return hasOutboundDataInternal();
- }
-
- synchronized boolean isOutboundDone() {
- return outboundClosed && !hasOutboundDataInternal();
- }
-
- synchronized void closeOutbound() {
- outboundClosed = true;
- }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/EphemeralKeyManager.java b/ojluni/src/main/java/sun/security/ssl/EphemeralKeyManager.java
deleted file mode 100755
index 47dba95..0000000
--- a/ojluni/src/main/java/sun/security/ssl/EphemeralKeyManager.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.security.*;
-
-/**
- * The "KeyManager" for ephemeral RSA keys. Ephemeral DH and ECDH keys
- * are handled by the DHCrypt and ECDHCrypt classes, respectively.
- *
- * @author Andreas Sterbenz
- */
-final class EphemeralKeyManager {
-
- // indices for the keys array below
- private final static int INDEX_RSA512 = 0;
- private final static int INDEX_RSA1024 = 1;
-
- /*
- * Current cached RSA KeyPairs. Elements are never null.
- * Indexed via the the constants above.
- */
- private final EphemeralKeyPair[] keys = new EphemeralKeyPair[] {
- new EphemeralKeyPair(null),
- new EphemeralKeyPair(null),
- };
-
- EphemeralKeyManager() {
- // empty
- }
-
- /*
- * Get a temporary RSA KeyPair.
- */
- KeyPair getRSAKeyPair(boolean export, SecureRandom random) {
- int length, index;
- if (export) {
- length = 512;
- index = INDEX_RSA512;
- } else {
- length = 1024;
- index = INDEX_RSA1024;
- }
-
- synchronized (keys) {
- KeyPair kp = keys[index].getKeyPair();
- if (kp == null) {
- try {
- KeyPairGenerator kgen = JsseJce.getKeyPairGenerator("RSA");
- kgen.initialize(length, random);
- keys[index] = new EphemeralKeyPair(kgen.genKeyPair());
- kp = keys[index].getKeyPair();
- } catch (Exception e) {
- // ignore
- }
- }
- return kp;
- }
- }
-
- /**
- * Inner class to handle storage of ephemeral KeyPairs.
- */
- private static class EphemeralKeyPair {
-
- // maximum number of times a KeyPair is used
- private final static int MAX_USE = 200;
-
- // maximum time interval in which the keypair is used (1 hour in ms)
- private final static long USE_INTERVAL = 3600*1000;
-
- private KeyPair keyPair;
- private int uses;
- private long expirationTime;
-
- private EphemeralKeyPair(KeyPair keyPair) {
- this.keyPair = keyPair;
- expirationTime = System.currentTimeMillis() + USE_INTERVAL;
- }
-
- /*
- * Check if the KeyPair can still be used.
- */
- private boolean isValid() {
- return (keyPair != null) && (uses < MAX_USE)
- && (System.currentTimeMillis() < expirationTime);
- }
-
- /*
- * Return the KeyPair or null if it is invalid.
- */
- private KeyPair getKeyPair() {
- if (isValid() == false) {
- keyPair = null;
- return null;
- }
- uses++;
- return keyPair;
- }
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/HandshakeHash.java b/ojluni/src/main/java/sun/security/ssl/HandshakeHash.java
deleted file mode 100755
index ffb8f32..0000000
--- a/ojluni/src/main/java/sun/security/ssl/HandshakeHash.java
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.ByteArrayOutputStream;
-import java.security.*;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-
-/**
- * Abstraction for the SSL/TLS hash of all handshake messages that is
- * maintained to verify the integrity of the negotiation. Internally,
- * it consists of an MD5 and an SHA1 digest. They are used in the client
- * and server finished messages and in certificate verify messages (if sent).
- *
- * This class transparently deals with cloneable and non-cloneable digests.
- *
- * This class now supports TLS 1.2 also. The key difference for TLS 1.2
- * is that you cannot determine the hash algorithms for CertificateVerify
- * at a early stage. On the other hand, it's simpler than TLS 1.1 (and earlier)
- * that there is no messy MD5+SHA1 digests.
- *
- * You need to obey these conventions when using this class:
- *
- * 1. protocolDetermined(version) should be called when the negotiated
- * protocol version is determined.
- *
- * 2. Before protocolDetermined() is called, only update(), reset(),
- * restrictCertificateVerifyAlgs(), setFinishedAlg(), and
- * setCertificateVerifyAlg() can be called.
- *
- * 3. After protocolDetermined() is called, reset() cannot be called.
- *
- * 4. After protocolDetermined() is called, if the version is pre-TLS 1.2,
- * getFinishedHash() and getCertificateVerifyHash() cannot be called. Otherwise,
- * getMD5Clone() and getSHAClone() cannot be called.
- *
- * 5. getMD5Clone() and getSHAClone() can only be called after
- * protocolDetermined() is called and version is pre-TLS 1.2.
- *
- * 6. getFinishedHash() and getCertificateVerifyHash() can only be called after
- * all protocolDetermined(), setCertificateVerifyAlg() and setFinishedAlg()
- * have been called and the version is TLS 1.2. If a CertificateVerify message
- * is to be used, call setCertificateVerifyAlg() with the hash algorithm as the
- * argument. Otherwise, you still must call setCertificateVerifyAlg(null) before
- * calculating any hash value.
- *
- * Suggestions: Call protocolDetermined(), restrictCertificateVerifyAlgs(),
- * setFinishedAlg(), and setCertificateVerifyAlg() as early as possible.
- *
- * Example:
- * <pre>
- * HandshakeHash hh = new HandshakeHash(...)
- * hh.protocolDetermined(ProtocolVersion.TLS12);
- * hh.update(clientHelloBytes);
- * hh.setFinishedAlg("SHA-256");
- * hh.update(serverHelloBytes);
- * ...
- * hh.setCertificateVerifyAlg("SHA-384");
- * hh.update(CertificateVerifyBytes);
- * byte[] cvDigest = hh.getCertificateVerifyHash();
- * ...
- * hh.update(finished1);
- * byte[] finDigest1 = hh.getFinishedHash();
- * hh.update(finished2);
- * byte[] finDigest2 = hh.getFinishedHash();
- * </pre>
- * If no CertificateVerify message is to be used, call
- * <pre>
- * hh.setCertificateVerifyAlg(null);
- * </pre>
- * This call can be made once you are certain that this message
- * will never be used.
- */
-final class HandshakeHash {
-
- // Common
-
- // -1: unknown
- // 1: <=TLS 1.1
- // 2: TLS 1.2
- private int version = -1;
- private ByteArrayOutputStream data = new ByteArrayOutputStream();
- private final boolean isServer;
-
- // For TLS 1.1
- private MessageDigest md5, sha;
- private final int clonesNeeded; // needs to be saved for later use
-
- // For TLS 1.2
- // cvAlgDetermined == true means setCertificateVerifyAlg() is called
- private boolean cvAlgDetermined = false;
- private String cvAlg;
- private MessageDigest finMD;
-
- /**
- * Create a new HandshakeHash. needCertificateVerify indicates whether
- * a hash for the certificate verify message is required. The argument
- * algs is a set of all possible hash algorithms that might be used in
- * TLS 1.2. If the caller is sure that TLS 1.2 won't be used or no
- * CertificateVerify message will be used, leave it null or empty.
- */
- HandshakeHash(boolean isServer, boolean needCertificateVerify,
- Set<String> algs) {
- this.isServer = isServer;
- clonesNeeded = needCertificateVerify ? 3 : 2;
- }
-
- void update(byte[] b, int offset, int len) {
- switch (version) {
- case 1:
- md5.update(b, offset, len);
- sha.update(b, offset, len);
- break;
- default:
- if (finMD != null) {
- finMD.update(b, offset, len);
- }
- data.write(b, offset, len);
- break;
- }
- }
-
- /**
- * Reset the remaining digests. Note this does *not* reset the number of
- * digest clones that can be obtained. Digests that have already been
- * cloned and are gone remain gone.
- */
- void reset() {
- if (version != -1) {
- throw new RuntimeException(
- "reset() can be only be called before protocolDetermined");
- }
- data.reset();
- }
-
-
- void protocolDetermined(ProtocolVersion pv) {
-
- // Do not set again, will ignore
- if (version != -1) return;
-
- version = pv.compareTo(ProtocolVersion.TLS12) >= 0 ? 2 : 1;
- switch (version) {
- case 1:
- // initiate md5, sha and call update on saved array
- try {
- md5 = CloneableDigest.getDigest("MD5", clonesNeeded);
- sha = CloneableDigest.getDigest("SHA", clonesNeeded);
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException
- ("Algorithm MD5 or SHA not available", e);
- }
- byte[] bytes = data.toByteArray();
- update(bytes, 0, bytes.length);
- break;
- case 2:
- break;
- }
- }
-
- /////////////////////////////////////////////////////////////
- // Below are old methods for pre-TLS 1.1
- /////////////////////////////////////////////////////////////
-
- /**
- * Return a new MD5 digest updated with all data hashed so far.
- */
- MessageDigest getMD5Clone() {
- if (version != 1) {
- throw new RuntimeException(
- "getMD5Clone() can be only be called for TLS 1.1");
- }
- return cloneDigest(md5);
- }
-
- /**
- * Return a new SHA digest updated with all data hashed so far.
- */
- MessageDigest getSHAClone() {
- if (version != 1) {
- throw new RuntimeException(
- "getSHAClone() can be only be called for TLS 1.1");
- }
- return cloneDigest(sha);
- }
-
- private static MessageDigest cloneDigest(MessageDigest digest) {
- try {
- return (MessageDigest)digest.clone();
- } catch (CloneNotSupportedException e) {
- // cannot occur for digests generated via CloneableDigest
- throw new RuntimeException("Could not clone digest", e);
- }
- }
-
- /////////////////////////////////////////////////////////////
- // Below are new methods for TLS 1.2
- /////////////////////////////////////////////////////////////
-
- private static String normalizeAlgName(String alg) {
- alg = alg.toUpperCase(Locale.US);
- if (alg.startsWith("SHA")) {
- if (alg.length() == 3) {
- return "SHA-1";
- }
- if (alg.charAt(3) != '-') {
- return "SHA-" + alg.substring(3);
- }
- }
- return alg;
- }
- /**
- * Specifies the hash algorithm used in Finished. This should be called
- * based in info in ServerHello.
- * Can be called multiple times.
- */
- void setFinishedAlg(String s) {
- if (s == null) {
- throw new RuntimeException(
- "setFinishedAlg's argument cannot be null");
- }
-
- // Can be called multiple times, but only set once
- if (finMD != null) return;
-
- try {
- finMD = CloneableDigest.getDigest(normalizeAlgName(s), 2);
- } catch (NoSuchAlgorithmException e) {
- throw new Error(e);
- }
- finMD.update(data.toByteArray());
- }
-
- /**
- * Restricts the possible algorithms for the CertificateVerify. Called by
- * the server based on info in CertRequest. The argument must be a subset
- * of the argument with the same name in the constructor. The method can be
- * called multiple times. If the caller is sure that no CertificateVerify
- * message will be used, leave this argument null or empty.
- */
- void restrictCertificateVerifyAlgs(Set<String> algs) {
- if (version == 1) {
- throw new RuntimeException(
- "setCertificateVerifyAlg() cannot be called for TLS 1.1");
- }
- // Not used yet
- }
-
- /**
- * Specifies the hash algorithm used in CertificateVerify.
- * Can be called multiple times.
- */
- void setCertificateVerifyAlg(String s) {
-
- // Can be called multiple times, but only set once
- if (cvAlgDetermined) return;
-
- cvAlg = s == null ? null : normalizeAlgName(s);
- cvAlgDetermined = true;
- }
-
- byte[] getAllHandshakeMessages() {
- return data.toByteArray();
- }
-
- /**
- * Calculates the hash in the CertificateVerify. Must be called right
- * after setCertificateVerifyAlg()
- */
- /*byte[] getCertificateVerifyHash() {
- throw new Error("Do not call getCertificateVerifyHash()");
- }*/
-
- /**
- * Calculates the hash in Finished. Must be called after setFinishedAlg().
- * This method can be called twice, for Finished messages of the server
- * side and client side respectively.
- */
- byte[] getFinishedHash() {
- try {
- return cloneDigest(finMD).digest();
- } catch (Exception e) {
- throw new Error("BAD");
- }
- }
-}
-
-/**
- * A wrapper for MessageDigests that simulates cloning of non-cloneable
- * digests. It uses the standard MessageDigest API and therefore can be used
- * transparently in place of a regular digest.
- *
- * Note that we extend the MessageDigest class directly rather than
- * MessageDigestSpi. This works because MessageDigest was originally designed
- * this way in the JDK 1.1 days which allows us to avoid creating an internal
- * provider.
- *
- * It can be "cloned" a limited number of times, which is specified at
- * construction time. This is achieved by internally maintaining n digests
- * in parallel. Consequently, it is only 1/n-th times as fast as the original
- * digest.
- *
- * Example:
- * MessageDigest md = CloneableDigest.getDigest("SHA", 2);
- * md.update(data1);
- * MessageDigest md2 = (MessageDigest)md.clone();
- * md2.update(data2);
- * byte[] d1 = md2.digest(); // digest of data1 || data2
- * md.update(data3);
- * byte[] d2 = md.digest(); // digest of data1 || data3
- *
- * This class is not thread safe.
- *
- */
-final class CloneableDigest extends MessageDigest implements Cloneable {
-
- /**
- * The individual MessageDigests. Initially, all elements are non-null.
- * When clone() is called, the non-null element with the maximum index is
- * returned and the array element set to null.
- *
- * All non-null element are always in the same state.
- */
- private final MessageDigest[] digests;
-
- private CloneableDigest(MessageDigest digest, int n, String algorithm)
- throws NoSuchAlgorithmException {
- super(algorithm);
- digests = new MessageDigest[n];
- digests[0] = digest;
- for (int i = 1; i < n; i++) {
- digests[i] = JsseJce.getMessageDigest(algorithm);
- }
- }
-
- /**
- * Return a MessageDigest for the given algorithm that can be cloned the
- * specified number of times. If the default implementation supports
- * cloning, it is returned. Otherwise, an instance of this class is
- * returned.
- */
- static MessageDigest getDigest(String algorithm, int n)
- throws NoSuchAlgorithmException {
- MessageDigest digest = JsseJce.getMessageDigest(algorithm);
- try {
- digest.clone();
- // already cloneable, use it
- return digest;
- } catch (CloneNotSupportedException e) {
- return new CloneableDigest(digest, n, algorithm);
- }
- }
-
- /**
- * Check if this object is still usable. If it has already been cloned the
- * maximum number of times, there are no digests left and this object can no
- * longer be used.
- */
- private void checkState() {
- // XXX handshaking currently doesn't stop updating hashes...
- // if (digests[0] == null) {
- // throw new IllegalStateException("no digests left");
- // }
- }
-
- protected int engineGetDigestLength() {
- checkState();
- return digests[0].getDigestLength();
- }
-
- protected void engineUpdate(byte b) {
- checkState();
- for (int i = 0; (i < digests.length) && (digests[i] != null); i++) {
- digests[i].update(b);
- }
- }
-
- protected void engineUpdate(byte[] b, int offset, int len) {
- checkState();
- for (int i = 0; (i < digests.length) && (digests[i] != null); i++) {
- digests[i].update(b, offset, len);
- }
- }
-
- protected byte[] engineDigest() {
- checkState();
- byte[] digest = digests[0].digest();
- digestReset();
- return digest;
- }
-
- protected int engineDigest(byte[] buf, int offset, int len)
- throws DigestException {
- checkState();
- int n = digests[0].digest(buf, offset, len);
- digestReset();
- return n;
- }
-
- /**
- * Reset all digests after a digest() call. digests[0] has already been
- * implicitly reset by the digest() call and does not need to be reset
- * again.
- */
- private void digestReset() {
- for (int i = 1; (i < digests.length) && (digests[i] != null); i++) {
- digests[i].reset();
- }
- }
-
- protected void engineReset() {
- checkState();
- for (int i = 0; (i < digests.length) && (digests[i] != null); i++) {
- digests[i].reset();
- }
- }
-
- public Object clone() {
- checkState();
- for (int i = digests.length - 1; i >= 0; i--) {
- if (digests[i] != null) {
- MessageDigest digest = digests[i];
- digests[i] = null;
- return digest;
- }
- }
- // cannot occur
- throw new InternalError();
- }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/HandshakeInStream.java b/ojluni/src/main/java/sun/security/ssl/HandshakeInStream.java
deleted file mode 100755
index 81c8464..0000000
--- a/ojluni/src/main/java/sun/security/ssl/HandshakeInStream.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.security.MessageDigest;
-
-import javax.net.ssl.SSLException;
-
-/**
- * InputStream for handshake data, used internally only. Contains the
- * handshake message buffer and methods to parse them.
- *
- * Once a new handshake record arrives, it is buffered in this class until
- * processed by the Handshaker. The buffer may also contain incomplete
- * handshake messages in case the message is split across multiple records.
- * Handshaker.process_record deals with all that. It may also contain
- * handshake messages larger than the default buffer size (e.g. large
- * certificate messages). The buffer is grown dynamically to handle that
- * (see InputRecord.queueHandshake()).
- *
- * Note that the InputRecord used as a buffer here is separate from the
- * AppInStream.r, which is where data from the socket is initially read
- * into. This is because once the initial handshake has been completed,
- * handshake and application data messages may be interleaved arbitrarily
- * and must be processed independently.
- *
- * @author David Brownell
- */
-public class HandshakeInStream extends InputStream {
-
- InputRecord r;
-
- /*
- * Construct the stream; we'll be accumulating hashes of the
- * input records using two sets of digests.
- */
- HandshakeInStream(HandshakeHash handshakeHash) {
- r = new InputRecord();
- r.setHandshakeHash(handshakeHash);
- }
-
-
- // overridden InputStream methods
-
- /*
- * Return the number of bytes available for read().
- *
- * Note that this returns the bytes remaining in the buffer, not
- * the bytes remaining in the current handshake message.
- */
- public int available() {
- return r.available();
- }
-
- /*
- * Get a byte of handshake data.
- */
- public int read() throws IOException {
- int n = r.read();
- if (n == -1) {
- throw new SSLException("Unexpected end of handshake data");
- }
- return n;
- }
-
- /*
- * Get a bunch of bytes of handshake data.
- */
- public int read(byte b [], int off, int len) throws IOException {
- // we read from a ByteArrayInputStream, it always returns the
- // data in a single read if enough is available
- int n = r.read(b, off, len);
- if (n != len) {
- throw new SSLException("Unexpected end of handshake data");
- }
- return n;
- }
-
- /*
- * Skip some handshake data.
- */
- public long skip(long n) throws IOException {
- return r.skip(n);
- }
-
- /*
- * Mark/ reset code, implemented using InputRecord mark/ reset.
- *
- * Note that it currently provides only a limited mark functionality
- * and should be used with care (once a new handshake record has been
- * read, data that has already been consumed is lost even if marked).
- */
-
- public void mark(int readlimit) {
- r.mark(readlimit);
- }
-
- public void reset() {
- r.reset();
- }
-
- public boolean markSupported() {
- return true;
- }
-
-
- // handshake management functions
-
- /*
- * Here's an incoming record with handshake data. Queue the contents;
- * it might be one or more entire messages, complete a message that's
- * partly queued, or both.
- */
- void incomingRecord(InputRecord in) throws IOException {
- r.queueHandshake(in);
- }
-
- /*
- * Hash any data we've consumed but not yet hashed. Useful mostly
- * for processing client certificate messages (so we can check the
- * immediately following cert verify message) and finished messages
- * (so we can compute our own finished message).
- */
- void digestNow() {
- r.doHashes();
- }
-
- /*
- * Do more than skip that handshake data ... totally ignore it.
- * The difference is that the data does not get hashed.
- */
- void ignore(int n) {
- r.ignore(n);
- }
-
-
- // Message parsing methods
-
- /*
- * Read 8, 16, 24, and 32 bit SSL integer data types, encoded
- * in standard big-endian form.
- */
-
- int getInt8() throws IOException {
- return read();
- }
-
- int getInt16() throws IOException {
- return (getInt8() << 8) | getInt8();
- }
-
- int getInt24() throws IOException {
- return (getInt8() << 16) | (getInt8() << 8) | getInt8();
- }
-
- int getInt32() throws IOException {
- return (getInt8() << 24) | (getInt8() << 16)
- | (getInt8() << 8) | getInt8();
- }
-
- /*
- * Read byte vectors with 8, 16, and 24 bit length encodings.
- */
-
- byte[] getBytes8() throws IOException {
- int len = getInt8();
- verifyLength(len);
- byte b[] = new byte[len];
-
- read(b, 0, len);
- return b;
- }
-
- public byte[] getBytes16() throws IOException {
- int len = getInt16();
- verifyLength(len);
- byte b[] = new byte[len];
-
- read(b, 0, len);
- return b;
- }
-
- byte[] getBytes24() throws IOException {
- int len = getInt24();
- verifyLength(len);
- byte b[] = new byte[len];
-
- read(b, 0, len);
- return b;
- }
-
- // Is a length greater than available bytes in the record?
- private void verifyLength(int len) throws SSLException {
- if (len > available()) {
- throw new SSLException(
- "Not enough data to fill declared vector size");
- }
- }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/HandshakeMessage.java b/ojluni/src/main/java/sun/security/ssl/HandshakeMessage.java
deleted file mode 100755
index 1c85a03..0000000
--- a/ojluni/src/main/java/sun/security/ssl/HandshakeMessage.java
+++ /dev/null
@@ -1,2018 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.math.BigInteger;
-import java.security.*;
-import java.security.interfaces.*;
-import java.security.spec.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-
-import java.lang.reflect.*;
-
-import javax.security.auth.x500.X500Principal;
-
-import javax.crypto.KeyGenerator;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.DHPublicKeySpec;
-
-import javax.net.ssl.*;
-
-import sun.security.internal.spec.TlsPrfParameterSpec;
-import sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.PRF.*;
-import sun.security.util.KeyUtil;
-
-/**
- * Many data structures are involved in the handshake messages. These
- * classes are used as structures, with public data members. They are
- * not visible outside the SSL package.
- *
- * Handshake messages all have a common header format, and they are all
- * encoded in a "handshake data" SSL record substream. The base class
- * here (HandshakeMessage) provides a common framework and records the
- * SSL record type of the particular handshake message.
- *
- * This file contains subclasses for all the basic handshake messages.
- * All handshake messages know how to encode and decode themselves on
- * SSL streams; this facilitates using the same code on SSL client and
- * server sides, although they don't send and receive the same messages.
- *
- * Messages also know how to print themselves, which is quite handy
- * for debugging. They always identify their type, and can optionally
- * dump all of their content.
- *
- * @author David Brownell
- */
-public abstract class HandshakeMessage {
-
- HandshakeMessage() { }
-
- // enum HandshakeType:
- static final byte ht_hello_request = 0;
- static final byte ht_client_hello = 1;
- static final byte ht_server_hello = 2;
-
- static final byte ht_certificate = 11;
- static final byte ht_server_key_exchange = 12;
- static final byte ht_certificate_request = 13;
- static final byte ht_server_hello_done = 14;
- static final byte ht_certificate_verify = 15;
- static final byte ht_client_key_exchange = 16;
-
- static final byte ht_finished = 20;
-
- /* Class and subclass dynamic debugging support */
- public static final Debug debug = Debug.getInstance("ssl");
-
- /**
- * Utility method to convert a BigInteger to a byte array in unsigned
- * format as needed in the handshake messages. BigInteger uses
- * 2's complement format, i.e. it prepends an extra zero if the MSB
- * is set. We remove that.
- */
- static byte[] toByteArray(BigInteger bi) {
- byte[] b = bi.toByteArray();
- if ((b.length > 1) && (b[0] == 0)) {
- int n = b.length - 1;
- byte[] newarray = new byte[n];
- System.arraycopy(b, 1, newarray, 0, n);
- b = newarray;
- }
- return b;
- }
-
- /*
- * SSL 3.0 MAC padding constants.
- * Also used by CertificateVerify and Finished during the handshake.
- */
- static final byte[] MD5_pad1 = genPad(0x36, 48);
- static final byte[] MD5_pad2 = genPad(0x5c, 48);
-
- static final byte[] SHA_pad1 = genPad(0x36, 40);
- static final byte[] SHA_pad2 = genPad(0x5c, 40);
-
- private static byte[] genPad(int b, int count) {
- byte[] padding = new byte[count];
- Arrays.fill(padding, (byte)b);
- return padding;
- }
-
- /*
- * Write a handshake message on the (handshake) output stream.
- * This is just a four byte header followed by the data.
- *
- * NOTE that huge messages -- notably, ones with huge cert
- * chains -- are handled correctly.
- */
- final void write(HandshakeOutStream s) throws IOException {
- int len = messageLength();
- if (len >= Record.OVERFLOW_OF_INT24) {
- throw new SSLException("Handshake message too big"
- + ", type = " + messageType() + ", len = " + len);
- }
- s.write(messageType());
- s.putInt24(len);
- send(s);
- }
-
- /*
- * Subclasses implement these methods so those kinds of
- * messages can be emitted. Base class delegates to subclass.
- */
- abstract int messageType();
- abstract int messageLength();
- abstract void send(HandshakeOutStream s) throws IOException;
-
- /*
- * Write a descriptive message on the output stream; for debugging.
- */
- abstract void print(PrintStream p) throws IOException;
-
-//
-// NOTE: the rest of these classes are nested within this one, and are
-// imported by other classes in this package. There are a few other
-// handshake message classes, not neatly nested here because of current
-// licensing requirement for native (RSA) methods. They belong here,
-// but those native methods complicate things a lot!
-//
-
-
-/*
- * HelloRequest ... SERVER --> CLIENT
- *
- * Server can ask the client to initiate a new handshake, e.g. to change
- * session parameters after a connection has been (re)established.
- */
-static final class HelloRequest extends HandshakeMessage {
- int messageType() { return ht_hello_request; }
-
- HelloRequest() { }
-
- HelloRequest(HandshakeInStream in) throws IOException
- {
- // nothing in this message
- }
-
- int messageLength() { return 0; }
-
- void send(HandshakeOutStream out) throws IOException
- {
- // nothing in this messaage
- }
-
- void print(PrintStream out) throws IOException
- {
- out.println("*** HelloRequest (empty)");
- }
-
-}
-
-
-/*
- * ClientHello ... CLIENT --> SERVER
- *
- * Client initiates handshake by telling server what it wants, and what it
- * can support (prioritized by what's first in the ciphe suite list).
- *
- * By RFC2246:7.4.1.2 it's explicitly anticipated that this message
- * will have more data added at the end ... e.g. what CAs the client trusts.
- * Until we know how to parse it, we will just read what we know
- * about, and let our caller handle the jumps over unknown data.
- */
-static final class ClientHello extends HandshakeMessage {
-
- ProtocolVersion protocolVersion;
- RandomCookie clnt_random;
- SessionId sessionId;
- private CipherSuiteList cipherSuites;
- byte[] compression_methods;
-
- HelloExtensions extensions = new HelloExtensions();
-
- private final static byte[] NULL_COMPRESSION = new byte[] {0};
-
- ClientHello(SecureRandom generator, ProtocolVersion protocolVersion,
- SessionId sessionId, CipherSuiteList cipherSuites) {
-
- this.protocolVersion = protocolVersion;
- this.sessionId = sessionId;
- this.cipherSuites = cipherSuites;
-
- if (cipherSuites.containsEC()) {
- extensions.add(SupportedEllipticCurvesExtension.DEFAULT);
- extensions.add(SupportedEllipticPointFormatsExtension.DEFAULT);
- }
-
- clnt_random = new RandomCookie(generator);
- compression_methods = NULL_COMPRESSION;
- }
-
- ClientHello(HandshakeInStream s, int messageLength) throws IOException {
- protocolVersion = ProtocolVersion.valueOf(s.getInt8(), s.getInt8());
- clnt_random = new RandomCookie(s);
- sessionId = new SessionId(s.getBytes8());
- cipherSuites = new CipherSuiteList(s);
- compression_methods = s.getBytes8();
- if (messageLength() != messageLength) {
- extensions = new HelloExtensions(s);
- }
- }
-
- CipherSuiteList getCipherSuites() {
- return cipherSuites;
- }
-
- // add renegotiation_info extension
- void addRenegotiationInfoExtension(byte[] clientVerifyData) {
- HelloExtension renegotiationInfo = new RenegotiationInfoExtension(
- clientVerifyData, new byte[0]);
- extensions.add(renegotiationInfo);
- }
-
- // add server_name extension
- void addServerNameIndicationExtension(String hostname) {
- // We would have checked that the hostname ia a FQDN.
- ArrayList<String> hostnames = new ArrayList<>(1);
- hostnames.add(hostname);
-
- try {
- extensions.add(new ServerNameExtension(hostnames));
- } catch (IOException ioe) {
- // ignore the exception and return
- }
- }
-
- // add signature_algorithm extension
- void addSignatureAlgorithmsExtension(
- Collection<SignatureAndHashAlgorithm> algorithms) {
- HelloExtension signatureAlgorithm =
- new SignatureAlgorithmsExtension(algorithms);
- extensions.add(signatureAlgorithm);
- }
-
- @Override
- int messageType() { return ht_client_hello; }
-
- @Override
- int messageLength() {
- /*
- * Add fixed size parts of each field...
- * version + random + session + cipher + compress
- */
- return (2 + 32 + 1 + 2 + 1
- + sessionId.length() /* ... + variable parts */
- + (cipherSuites.size() * 2)
- + compression_methods.length)
- + extensions.length();
- }
-
- @Override
- void send(HandshakeOutStream s) throws IOException {
- s.putInt8(protocolVersion.major);
- s.putInt8(protocolVersion.minor);
- clnt_random.send(s);
- s.putBytes8(sessionId.getId());
- cipherSuites.send(s);
- s.putBytes8(compression_methods);
- extensions.send(s);
- }
-
- @Override
- void print(PrintStream s) throws IOException {
- s.println("*** ClientHello, " + protocolVersion);
-
- if (debug != null && Debug.isOn("verbose")) {
- s.print("RandomCookie: ");
- clnt_random.print(s);
-
- s.print("Session ID: ");
- s.println(sessionId);
-
- s.println("Cipher Suites: " + cipherSuites);
-
- Debug.println(s, "Compression Methods", compression_methods);
- extensions.print(s);
- s.println("***");
- }
- }
-}
-
-/*
- * ServerHello ... SERVER --> CLIENT
- *
- * Server chooses protocol options from among those it supports and the
- * client supports. Then it sends the basic session descriptive parameters
- * back to the client.
- */
-static final
-class ServerHello extends HandshakeMessage
-{
- int messageType() { return ht_server_hello; }
-
- ProtocolVersion protocolVersion;
- RandomCookie svr_random;
- SessionId sessionId;
- CipherSuite cipherSuite;
- byte compression_method;
- HelloExtensions extensions = new HelloExtensions();
-
- ServerHello() {
- // empty
- }
-
- ServerHello(HandshakeInStream input, int messageLength)
- throws IOException {
- protocolVersion = ProtocolVersion.valueOf(input.getInt8(),
- input.getInt8());
- svr_random = new RandomCookie(input);
- sessionId = new SessionId(input.getBytes8());
- cipherSuite = CipherSuite.valueOf(input.getInt8(), input.getInt8());
- compression_method = (byte)input.getInt8();
- if (messageLength() != messageLength) {
- extensions = new HelloExtensions(input);
- }
- }
-
- int messageLength()
- {
- // almost fixed size, except session ID and extensions:
- // major + minor = 2
- // random = 32
- // session ID len field = 1
- // cipher suite + compression = 3
- // extensions: if present, 2 + length of extensions
- return 38 + sessionId.length() + extensions.length();
- }
-
- void send(HandshakeOutStream s) throws IOException
- {
- s.putInt8(protocolVersion.major);
- s.putInt8(protocolVersion.minor);
- svr_random.send(s);
- s.putBytes8(sessionId.getId());
- s.putInt8(cipherSuite.id >> 8);
- s.putInt8(cipherSuite.id & 0xff);
- s.putInt8(compression_method);
- extensions.send(s);
- }
-
- void print(PrintStream s) throws IOException
- {
- s.println("*** ServerHello, " + protocolVersion);
-
- if (debug != null && Debug.isOn("verbose")) {
- s.print("RandomCookie: ");
- svr_random.print(s);
-
- int i;
-
- s.print("Session ID: ");
- s.println(sessionId);
-
- s.println("Cipher Suite: " + cipherSuite);
- s.println("Compression Method: " + compression_method);
- extensions.print(s);
- s.println("***");
- }
- }
-}
-
-
-/*
- * CertificateMsg ... send by both CLIENT and SERVER
- *
- * Each end of a connection may need to pass its certificate chain to
- * the other end. Such chains are intended to validate an identity with
- * reference to some certifying authority. Examples include companies
- * like Verisign, or financial institutions. There's some control over
- * the certifying authorities which are sent.
- *
- * NOTE: that these messages might be huge, taking many handshake records.
- * Up to 2^48 bytes of certificate may be sent, in records of at most 2^14
- * bytes each ... up to 2^32 records sent on the output stream.
- */
-static final
-class CertificateMsg extends HandshakeMessage
-{
- int messageType() { return ht_certificate; }
-
- private X509Certificate[] chain;
-
- private List<byte[]> encodedChain;
-
- private int messageLength;
-
- CertificateMsg(X509Certificate[] certs) {
- chain = certs;
- }
-
- CertificateMsg(HandshakeInStream input) throws IOException {
- int chainLen = input.getInt24();
- List<Certificate> v = new ArrayList<>(4);
-
- CertificateFactory cf = null;
- while (chainLen > 0) {
- byte[] cert = input.getBytes24();
- chainLen -= (3 + cert.length);
- try {
- if (cf == null) {
- cf = CertificateFactory.getInstance("X.509");
- }
- v.add(cf.generateCertificate(new ByteArrayInputStream(cert)));
- } catch (CertificateException e) {
- throw (SSLProtocolException)new SSLProtocolException(
- e.getMessage()).initCause(e);
- }
- }
-
- chain = v.toArray(new X509Certificate[v.size()]);
- }
-
- int messageLength() {
- if (encodedChain == null) {
- messageLength = 3;
- encodedChain = new ArrayList<byte[]>(chain.length);
- try {
- for (X509Certificate cert : chain) {
- byte[] b = cert.getEncoded();
- encodedChain.add(b);
- messageLength += b.length + 3;
- }
- } catch (CertificateEncodingException e) {
- encodedChain = null;
- throw new RuntimeException("Could not encode certificates", e);
- }
- }
- return messageLength;
- }
-
- void send(HandshakeOutStream s) throws IOException {
- s.putInt24(messageLength() - 3);
- for (byte[] b : encodedChain) {
- s.putBytes24(b);
- }
- }
-
- void print(PrintStream s) throws IOException {
- s.println("*** Certificate chain");
-
- if (debug != null && Debug.isOn("verbose")) {
- for (int i = 0; i < chain.length; i++)
- s.println("chain [" + i + "] = " + chain[i]);
- s.println("***");
- }
- }
-
- X509Certificate[] getCertificateChain() {
- return chain.clone();
- }
-}
-
-/*
- * ServerKeyExchange ... SERVER --> CLIENT
- *
- * The cipher suite selected, when combined with the certificate exchanged,
- * implies one of several different kinds of key exchange. Most current
- * cipher suites require the server to send more than its certificate.
- *
- * The primary exceptions are when a server sends an encryption-capable
- * RSA public key in its cert, to be used with RSA (or RSA_export) key
- * exchange; and when a server sends its Diffie-Hellman cert. Those kinds
- * of key exchange do not require a ServerKeyExchange message.
- *
- * Key exchange can be viewed as having three modes, which are explicit
- * for the Diffie-Hellman flavors and poorly specified for RSA ones:
- *
- * - "Ephemeral" keys. Here, a "temporary" key is allocated by the
- * server, and signed. Diffie-Hellman keys signed using RSA or
- * DSS are ephemeral (DHE flavor). RSA keys get used to do the same
- * thing, to cut the key size down to 512 bits (export restrictions)
- * or for signing-only RSA certificates.
- *
- * - Anonymity. Here no server certificate is sent, only the public
- * key of the server. This case is subject to man-in-the-middle
- * attacks. This can be done with Diffie-Hellman keys (DH_anon) or
- * with RSA keys, but is only used in SSLv3 for DH_anon.
- *
- * - "Normal" case. Here a server certificate is sent, and the public
- * key there is used directly in exchanging the premaster secret.
- * For example, Diffie-Hellman "DH" flavor, and any RSA flavor with
- * only 512 bit keys.
- *
- * If a server certificate is sent, there is no anonymity. However,
- * when a certificate is sent, ephemeral keys may still be used to
- * exchange the premaster secret. That's how RSA_EXPORT often works,
- * as well as how the DHE_* flavors work.
- */
-static abstract class ServerKeyExchange extends HandshakeMessage
-{
- int messageType() { return ht_server_key_exchange; }
-}
-
-
-/*
- * Using RSA for Key Exchange: exchange a session key that's not as big
- * as the signing-only key. Used for export applications, since exported
- * RSA encryption keys can't be bigger than 512 bytes.
- *
- * This is never used when keys are 512 bits or smaller, and isn't used
- * on "US Domestic" ciphers in any case.
- */
-static final
-class RSA_ServerKeyExchange extends ServerKeyExchange
-{
- private byte rsa_modulus[]; // 1 to 2^16 - 1 bytes
- private byte rsa_exponent[]; // 1 to 2^16 - 1 bytes
-
- private Signature signature;
- private byte[] signatureBytes;
-
- /*
- * Hash the nonces and the ephemeral RSA public key.
- */
- private void updateSignature(byte clntNonce[], byte svrNonce[])
- throws SignatureException {
- int tmp;
-
- signature.update(clntNonce);
- signature.update(svrNonce);
-
- tmp = rsa_modulus.length;
- signature.update((byte)(tmp >> 8));
- signature.update((byte)(tmp & 0x0ff));
- signature.update(rsa_modulus);
-
- tmp = rsa_exponent.length;
- signature.update((byte)(tmp >> 8));
- signature.update((byte)(tmp & 0x0ff));
- signature.update(rsa_exponent);
- }
-
-
- /*
- * Construct an RSA server key exchange message, using data
- * known _only_ to the server.
- *
- * The client knows the public key corresponding to this private
- * key, from the Certificate message sent previously. To comply
- * with US export regulations we use short RSA keys ... either
- * long term ones in the server's X509 cert, or else ephemeral
- * ones sent using this message.
- */
- RSA_ServerKeyExchange(PublicKey ephemeralKey, PrivateKey privateKey,
- RandomCookie clntNonce, RandomCookie svrNonce, SecureRandom sr)
- throws GeneralSecurityException {
- RSAPublicKeySpec rsaKey = JsseJce.getRSAPublicKeySpec(ephemeralKey);
- rsa_modulus = toByteArray(rsaKey.getModulus());
- rsa_exponent = toByteArray(rsaKey.getPublicExponent());
- signature = RSASignature.getInstance();
- signature.initSign(privateKey, sr);
- updateSignature(clntNonce.random_bytes, svrNonce.random_bytes);
- signatureBytes = signature.sign();
- }
-
-
- /*
- * Parse an RSA server key exchange message, using data known
- * to the client (and, in some situations, eavesdroppers).
- */
- RSA_ServerKeyExchange(HandshakeInStream input)
- throws IOException, NoSuchAlgorithmException {
- signature = RSASignature.getInstance();
- rsa_modulus = input.getBytes16();
- rsa_exponent = input.getBytes16();
- signatureBytes = input.getBytes16();
- }
-
- /*
- * Get the ephemeral RSA public key that will be used in this
- * SSL connection.
- */
- PublicKey getPublicKey() {
- try {
- KeyFactory kfac = JsseJce.getKeyFactory("RSA");
- // modulus and exponent are always positive
- RSAPublicKeySpec kspec = new RSAPublicKeySpec(
- new BigInteger(1, rsa_modulus),
- new BigInteger(1, rsa_exponent));
- return kfac.generatePublic(kspec);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- /*
- * Verify the signed temporary key using the hashes computed
- * from it and the two nonces. This is called by clients
- * with "exportable" RSA flavors.
- */
- boolean verify(PublicKey certifiedKey, RandomCookie clntNonce,
- RandomCookie svrNonce) throws GeneralSecurityException {
- signature.initVerify(certifiedKey);
- updateSignature(clntNonce.random_bytes, svrNonce.random_bytes);
- return signature.verify(signatureBytes);
- }
-
- int messageLength() {
- return 6 + rsa_modulus.length + rsa_exponent.length
- + signatureBytes.length;
- }
-
- void send(HandshakeOutStream s) throws IOException {
- s.putBytes16(rsa_modulus);
- s.putBytes16(rsa_exponent);
- s.putBytes16(signatureBytes);
- }
-
- void print(PrintStream s) throws IOException {
- s.println("*** RSA ServerKeyExchange");
-
- if (debug != null && Debug.isOn("verbose")) {
- Debug.println(s, "RSA Modulus", rsa_modulus);
- Debug.println(s, "RSA Public Exponent", rsa_exponent);
- }
- }
-}
-
-
-/*
- * Using Diffie-Hellman algorithm for key exchange. All we really need to
- * do is securely get Diffie-Hellman keys (using the same P, G parameters)
- * to our peer, then we automatically have a shared secret without need
- * to exchange any more data. (D-H only solutions, such as SKIP, could
- * eliminate key exchange negotiations and get faster connection setup.
- * But they still need a signature algorithm like DSS/DSA to support the
- * trusted distribution of keys without relying on unscalable physical
- * key distribution systems.)
- *
- * This class supports several DH-based key exchange algorithms, though
- * perhaps eventually each deserves its own class. Notably, this has
- * basic support for DH_anon and its DHE_DSS and DHE_RSA signed variants.
- */
-static final
-class DH_ServerKeyExchange extends ServerKeyExchange
-{
- // Fix message encoding, see 4348279
- private final static boolean dhKeyExchangeFix =
- Debug.getBooleanProperty("com.sun.net.ssl.dhKeyExchangeFix", true);
-
- private byte dh_p []; // 1 to 2^16 - 1 bytes
- private byte dh_g []; // 1 to 2^16 - 1 bytes
- private byte dh_Ys []; // 1 to 2^16 - 1 bytes
-
- private byte signature [];
-
- // protocol version being established using this ServerKeyExchange message
- ProtocolVersion protocolVersion;
-
- // the preferable signature algorithm used by this ServerKeyExchange message
- private SignatureAndHashAlgorithm preferableSignatureAlgorithm;
-
- /*
- * Construct from initialized DH key object, for DH_anon
- * key exchange.
- */
- DH_ServerKeyExchange(DHCrypt obj, ProtocolVersion protocolVersion) {
- this.protocolVersion = protocolVersion;
- this.preferableSignatureAlgorithm = null;
-
- // The DH key has been validated in the constructor of DHCrypt.
- setValues(obj);
- signature = null;
- }
-
- /*
- * Construct from initialized DH key object and the key associated
- * with the cert chain which was sent ... for DHE_DSS and DHE_RSA
- * key exchange. (Constructor called by server.)
- */
- DH_ServerKeyExchange(DHCrypt obj, PrivateKey key, byte clntNonce[],
- byte svrNonce[], SecureRandom sr,
- SignatureAndHashAlgorithm signAlgorithm,
- ProtocolVersion protocolVersion) throws GeneralSecurityException {
-
- this.protocolVersion = protocolVersion;
-
- // The DH key has been validated in the constructor of DHCrypt.
- setValues(obj);
-
- Signature sig;
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- this.preferableSignatureAlgorithm = signAlgorithm;
- sig = JsseJce.getSignature(signAlgorithm.getAlgorithmName());
- } else {
- this.preferableSignatureAlgorithm = null;
- if (key.getAlgorithm().equals("DSA")) {
- sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
- } else {
- sig = RSASignature.getInstance();
- }
- }
-
- sig.initSign(key, sr);
- updateSignature(sig, clntNonce, svrNonce);
- signature = sig.sign();
- }
-
- /*
- * Construct a DH_ServerKeyExchange message from an input
- * stream, as if sent from server to client for use with
- * DH_anon key exchange
- */
- DH_ServerKeyExchange(HandshakeInStream input,
- ProtocolVersion protocolVersion)
- throws IOException, GeneralSecurityException {
-
- this.protocolVersion = protocolVersion;
- this.preferableSignatureAlgorithm = null;
-
- dh_p = input.getBytes16();
- dh_g = input.getBytes16();
- dh_Ys = input.getBytes16();
- KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys),
- new BigInteger(1, dh_p),
- new BigInteger(1, dh_g)));
-
- signature = null;
- }
-
- /*
- * Construct a DH_ServerKeyExchange message from an input stream
- * and a certificate, as if sent from server to client for use with
- * DHE_DSS or DHE_RSA key exchange. (Called by client.)
- */
- DH_ServerKeyExchange(HandshakeInStream input, PublicKey publicKey,
- byte clntNonce[], byte svrNonce[], int messageSize,
- Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
- ProtocolVersion protocolVersion)
- throws IOException, GeneralSecurityException {
-
- this.protocolVersion = protocolVersion;
-
- // read params: ServerDHParams
- dh_p = input.getBytes16();
- dh_g = input.getBytes16();
- dh_Ys = input.getBytes16();
- KeyUtil.validate(new DHPublicKeySpec(new BigInteger(1, dh_Ys),
- new BigInteger(1, dh_p),
- new BigInteger(1, dh_g)));
-
- // read the signature and hash algorithm
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- int hash = input.getInt8(); // hash algorithm
- int signature = input.getInt8(); // signature algorithm
-
- preferableSignatureAlgorithm =
- SignatureAndHashAlgorithm.valueOf(hash, signature, 0);
-
- // Is it a local supported signature algorithm?
- if (!localSupportedSignAlgs.contains(
- preferableSignatureAlgorithm)) {
- throw new SSLHandshakeException(
- "Unsupported SignatureAndHashAlgorithm in " +
- "ServerKeyExchange message");
- }
- } else {
- this.preferableSignatureAlgorithm = null;
- }
-
- // read the signature
- byte signature[];
- if (dhKeyExchangeFix) {
- signature = input.getBytes16();
- } else {
- messageSize -= (dh_p.length + 2);
- messageSize -= (dh_g.length + 2);
- messageSize -= (dh_Ys.length + 2);
-
- signature = new byte[messageSize];
- input.read(signature);
- }
-
- Signature sig;
- String algorithm = publicKey.getAlgorithm();
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- sig = JsseJce.getSignature(
- preferableSignatureAlgorithm.getAlgorithmName());
- } else {
- if (algorithm.equals("DSA")) {
- sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
- } else if (algorithm.equals("RSA")) {
- sig = RSASignature.getInstance();
- } else {
- throw new SSLKeyException("neither an RSA or a DSA key");
- }
- }
-
- sig.initVerify(publicKey);
- updateSignature(sig, clntNonce, svrNonce);
-
- if (sig.verify(signature) == false ) {
- throw new SSLKeyException("Server D-H key verification failed");
- }
- }
-
- /* Return the Diffie-Hellman modulus */
- BigInteger getModulus() {
- return new BigInteger(1, dh_p);
- }
-
- /* Return the Diffie-Hellman base/generator */
- BigInteger getBase() {
- return new BigInteger(1, dh_g);
- }
-
- /* Return the server's Diffie-Hellman public key */
- BigInteger getServerPublicKey() {
- return new BigInteger(1, dh_Ys);
- }
-
- /*
- * Update sig with nonces and Diffie-Hellman public key.
- */
- private void updateSignature(Signature sig, byte clntNonce[],
- byte svrNonce[]) throws SignatureException {
- int tmp;
-
- sig.update(clntNonce);
- sig.update(svrNonce);
-
- tmp = dh_p.length;
- sig.update((byte)(tmp >> 8));
- sig.update((byte)(tmp & 0x0ff));
- sig.update(dh_p);
-
- tmp = dh_g.length;
- sig.update((byte)(tmp >> 8));
- sig.update((byte)(tmp & 0x0ff));
- sig.update(dh_g);
-
- tmp = dh_Ys.length;
- sig.update((byte)(tmp >> 8));
- sig.update((byte)(tmp & 0x0ff));
- sig.update(dh_Ys);
- }
-
- private void setValues(DHCrypt obj) {
- dh_p = toByteArray(obj.getModulus());
- dh_g = toByteArray(obj.getBase());
- dh_Ys = toByteArray(obj.getPublicKey());
- }
-
- int messageLength() {
- int temp = 6; // overhead for p, g, y(s) values.
-
- temp += dh_p.length;
- temp += dh_g.length;
- temp += dh_Ys.length;
-
- if (signature != null) {
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- temp += SignatureAndHashAlgorithm.sizeInRecord();
- }
-
- temp += signature.length;
- if (dhKeyExchangeFix) {
- temp += 2;
- }
- }
-
- return temp;
- }
-
- void send(HandshakeOutStream s) throws IOException {
- s.putBytes16(dh_p);
- s.putBytes16(dh_g);
- s.putBytes16(dh_Ys);
-
- if (signature != null) {
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- s.putInt8(preferableSignatureAlgorithm.getHashValue());
- s.putInt8(preferableSignatureAlgorithm.getSignatureValue());
- }
-
- if (dhKeyExchangeFix) {
- s.putBytes16(signature);
- } else {
- s.write(signature);
- }
- }
- }
-
- void print(PrintStream s) throws IOException {
- s.println("*** Diffie-Hellman ServerKeyExchange");
-
- if (debug != null && Debug.isOn("verbose")) {
- Debug.println(s, "DH Modulus", dh_p);
- Debug.println(s, "DH Base", dh_g);
- Debug.println(s, "Server DH Public Key", dh_Ys);
-
- if (signature == null) {
- s.println("Anonymous");
- } else {
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- s.println("Signature Algorithm " +
- preferableSignatureAlgorithm.getAlgorithmName());
- }
-
- s.println("Signed with a DSA or RSA public key");
- }
- }
- }
-}
-
-/*
- * ECDH server key exchange message. Sent by the server for ECDHE and ECDH_anon
- * ciphersuites to communicate its ephemeral public key (including the
- * EC domain parameters).
- *
- * We support named curves only, no explicitly encoded curves.
- */
-static final
-class ECDH_ServerKeyExchange extends ServerKeyExchange {
-
- // constants for ECCurveType
- private final static int CURVE_EXPLICIT_PRIME = 1;
- private final static int CURVE_EXPLICIT_CHAR2 = 2;
- private final static int CURVE_NAMED_CURVE = 3;
-
- // id of the curve we are using
- private int curveId;
- // encoded public point
- private byte[] pointBytes;
-
- // signature bytes (or null if anonymous)
- private byte[] signatureBytes;
-
- // public key object encapsulated in this message
- private ECPublicKey publicKey;
-
- // protocol version being established using this ServerKeyExchange message
- ProtocolVersion protocolVersion;
-
- // the preferable signature algorithm used by this ServerKeyExchange message
- private SignatureAndHashAlgorithm preferableSignatureAlgorithm;
-
- ECDH_ServerKeyExchange(ECDHCrypt obj, PrivateKey privateKey,
- byte[] clntNonce, byte[] svrNonce, SecureRandom sr,
- SignatureAndHashAlgorithm signAlgorithm,
- ProtocolVersion protocolVersion) throws GeneralSecurityException {
-
- this.protocolVersion = protocolVersion;
-
- publicKey = (ECPublicKey)obj.getPublicKey();
- ECParameterSpec params = publicKey.getParams();
- ECPoint point = publicKey.getW();
- pointBytes = JsseJce.encodePoint(point, params.getCurve());
- curveId = SupportedEllipticCurvesExtension.getCurveIndex(params);
-
- if (privateKey == null) {
- // ECDH_anon
- return;
- }
-
- Signature sig;
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- this.preferableSignatureAlgorithm = signAlgorithm;
- sig = JsseJce.getSignature(signAlgorithm.getAlgorithmName());
- } else {
- sig = getSignature(privateKey.getAlgorithm());
- }
- sig.initSign(privateKey); // where is the SecureRandom?
-
- updateSignature(sig, clntNonce, svrNonce);
- signatureBytes = sig.sign();
- }
-
- /*
- * Parse an ECDH server key exchange message.
- */
- ECDH_ServerKeyExchange(HandshakeInStream input, PublicKey signingKey,
- byte[] clntNonce, byte[] svrNonce,
- Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
- ProtocolVersion protocolVersion)
- throws IOException, GeneralSecurityException {
-
- this.protocolVersion = protocolVersion;
-
- // read params: ServerECDHParams
- int curveType = input.getInt8();
- ECParameterSpec parameters;
- // These parsing errors should never occur as we negotiated
- // the supported curves during the exchange of the Hello messages.
- if (curveType == CURVE_NAMED_CURVE) {
- curveId = input.getInt16();
- if (SupportedEllipticCurvesExtension.isSupported(curveId)
- == false) {
- throw new SSLHandshakeException(
- "Unsupported curveId: " + curveId);
- }
- String curveOid =
- SupportedEllipticCurvesExtension.getCurveOid(curveId);
- if (curveOid == null) {
- throw new SSLHandshakeException(
- "Unknown named curve: " + curveId);
- }
- parameters = JsseJce.getECParameterSpec(curveOid);
- if (parameters == null) {
- throw new SSLHandshakeException(
- "Unsupported curve: " + curveOid);
- }
- } else {
- throw new SSLHandshakeException(
- "Unsupported ECCurveType: " + curveType);
- }
- pointBytes = input.getBytes8();
-
- ECPoint point = JsseJce.decodePoint(pointBytes, parameters.getCurve());
- KeyFactory factory = JsseJce.getKeyFactory("EC");
- publicKey = (ECPublicKey)factory.generatePublic(
- new ECPublicKeySpec(point, parameters));
-
- if (signingKey == null) {
- // ECDH_anon
- return;
- }
-
- // read the signature and hash algorithm
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- int hash = input.getInt8(); // hash algorithm
- int signature = input.getInt8(); // signature algorithm
-
- preferableSignatureAlgorithm =
- SignatureAndHashAlgorithm.valueOf(hash, signature, 0);
-
- // Is it a local supported signature algorithm?
- if (!localSupportedSignAlgs.contains(
- preferableSignatureAlgorithm)) {
- throw new SSLHandshakeException(
- "Unsupported SignatureAndHashAlgorithm in " +
- "ServerKeyExchange message");
- }
- }
-
- // read the signature
- signatureBytes = input.getBytes16();
-
- // verify the signature
- Signature sig;
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- sig = JsseJce.getSignature(
- preferableSignatureAlgorithm.getAlgorithmName());
- } else {
- sig = getSignature(signingKey.getAlgorithm());
- }
- sig.initVerify(signingKey);
-
- updateSignature(sig, clntNonce, svrNonce);
-
- if (sig.verify(signatureBytes) == false ) {
- throw new SSLKeyException(
- "Invalid signature on ECDH server key exchange message");
- }
- }
-
- /*
- * Get the ephemeral EC public key encapsulated in this message.
- */
- ECPublicKey getPublicKey() {
- return publicKey;
- }
-
- private static Signature getSignature(String keyAlgorithm)
- throws NoSuchAlgorithmException {
- if (keyAlgorithm.equals("EC")) {
- return JsseJce.getSignature(JsseJce.SIGNATURE_ECDSA);
- } else if (keyAlgorithm.equals("RSA")) {
- return RSASignature.getInstance();
- } else {
- throw new NoSuchAlgorithmException("neither an RSA or a EC key");
- }
- }
-
- private void updateSignature(Signature sig, byte clntNonce[],
- byte svrNonce[]) throws SignatureException {
- sig.update(clntNonce);
- sig.update(svrNonce);
-
- sig.update((byte)CURVE_NAMED_CURVE);
- sig.update((byte)(curveId >> 8));
- sig.update((byte)curveId);
- sig.update((byte)pointBytes.length);
- sig.update(pointBytes);
- }
-
- int messageLength() {
- int sigLen = 0;
- if (signatureBytes != null) {
- sigLen = 2 + signatureBytes.length;
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- sigLen += SignatureAndHashAlgorithm.sizeInRecord();
- }
- }
-
- return 4 + pointBytes.length + sigLen;
- }
-
- void send(HandshakeOutStream s) throws IOException {
- s.putInt8(CURVE_NAMED_CURVE);
- s.putInt16(curveId);
- s.putBytes8(pointBytes);
-
- if (signatureBytes != null) {
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- s.putInt8(preferableSignatureAlgorithm.getHashValue());
- s.putInt8(preferableSignatureAlgorithm.getSignatureValue());
- }
-
- s.putBytes16(signatureBytes);
- }
- }
-
- void print(PrintStream s) throws IOException {
- s.println("*** ECDH ServerKeyExchange");
-
- if (debug != null && Debug.isOn("verbose")) {
- if (signatureBytes == null) {
- s.println("Anonymous");
- } else {
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- s.println("Signature Algorithm " +
- preferableSignatureAlgorithm.getAlgorithmName());
- }
- }
-
- s.println("Server key: " + publicKey);
- }
- }
-}
-
-static final class DistinguishedName {
-
- /*
- * DER encoded distinguished name.
- * TLS requires that its not longer than 65535 bytes.
- */
- byte name[];
-
- DistinguishedName(HandshakeInStream input) throws IOException {
- name = input.getBytes16();
- }
-
- DistinguishedName(X500Principal dn) {
- name = dn.getEncoded();
- }
-
- X500Principal getX500Principal() throws IOException {
- try {
- return new X500Principal(name);
- } catch (IllegalArgumentException e) {
- throw (SSLProtocolException)new SSLProtocolException(
- e.getMessage()).initCause(e);
- }
- }
-
- int length() {
- return 2 + name.length;
- }
-
- void send(HandshakeOutStream output) throws IOException {
- output.putBytes16(name);
- }
-
- void print(PrintStream output) throws IOException {
- X500Principal principal = new X500Principal(name);
- output.println("<" + principal.toString() + ">");
- }
-}
-
-/*
- * CertificateRequest ... SERVER --> CLIENT
- *
- * Authenticated servers may ask clients to authenticate themselves
- * in turn, using this message.
- *
- * Prior to TLS 1.2, the structure of the message is defined as:
- * struct {
- * ClientCertificateType certificate_types<1..2^8-1>;
- * DistinguishedName certificate_authorities<0..2^16-1>;
- * } CertificateRequest;
- *
- * In TLS 1.2, the structure is changed to:
- * struct {
- * ClientCertificateType certificate_types<1..2^8-1>;
- * SignatureAndHashAlgorithm
- * supported_signature_algorithms<2^16-1>;
- * DistinguishedName certificate_authorities<0..2^16-1>;
- * } CertificateRequest;
- *
- */
-static final
-class CertificateRequest extends HandshakeMessage
-{
- // enum ClientCertificateType
- static final int cct_rsa_sign = 1;
- static final int cct_dss_sign = 2;
- static final int cct_rsa_fixed_dh = 3;
- static final int cct_dss_fixed_dh = 4;
-
- // The existance of these two values is a bug in the SSL specification.
- // They are never used in the protocol.
- static final int cct_rsa_ephemeral_dh = 5;
- static final int cct_dss_ephemeral_dh = 6;
-
- // From RFC 4492 (ECC)
- static final int cct_ecdsa_sign = 64;
- static final int cct_rsa_fixed_ecdh = 65;
- static final int cct_ecdsa_fixed_ecdh = 66;
-
- private final static byte[] TYPES_NO_ECC = { cct_rsa_sign, cct_dss_sign };
- private final static byte[] TYPES_ECC =
- { cct_rsa_sign, cct_dss_sign, cct_ecdsa_sign };
-
- byte types []; // 1 to 255 types
- DistinguishedName authorities []; // 3 to 2^16 - 1
- // ... "3" because that's the smallest DER-encoded X500 DN
-
- // protocol version being established using this CertificateRequest message
- ProtocolVersion protocolVersion;
-
- // supported_signature_algorithms for TLS 1.2 or later
- private Collection<SignatureAndHashAlgorithm> algorithms;
-
- // length of supported_signature_algorithms
- private int algorithmsLen;
-
- CertificateRequest(X509Certificate ca[], KeyExchange keyExchange,
- Collection<SignatureAndHashAlgorithm> signAlgs,
- ProtocolVersion protocolVersion) throws IOException {
-
- this.protocolVersion = protocolVersion;
-
- // always use X500Principal
- authorities = new DistinguishedName[ca.length];
- for (int i = 0; i < ca.length; i++) {
- X500Principal x500Principal = ca[i].getSubjectX500Principal();
- authorities[i] = new DistinguishedName(x500Principal);
- }
- // we support RSA, DSS, and ECDSA client authentication and they
- // can be used with all ciphersuites. If this changes, the code
- // needs to be adapted to take keyExchange into account.
- // We only request ECDSA client auth if we have ECC crypto available.
- this.types = JsseJce.isEcAvailable() ? TYPES_ECC : TYPES_NO_ECC;
-
- // Use supported_signature_algorithms for TLS 1.2 or later.
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- if (signAlgs == null || signAlgs.isEmpty()) {
- throw new SSLProtocolException(
- "No supported signature algorithms");
- }
-
- algorithms = new ArrayList<SignatureAndHashAlgorithm>(signAlgs);
- algorithmsLen =
- SignatureAndHashAlgorithm.sizeInRecord() * algorithms.size();
- } else {
- algorithms = new ArrayList<SignatureAndHashAlgorithm>();
- algorithmsLen = 0;
- }
- }
-
- CertificateRequest(HandshakeInStream input,
- ProtocolVersion protocolVersion) throws IOException {
-
- this.protocolVersion = protocolVersion;
-
- // Read the certificate_types.
- types = input.getBytes8();
-
- // Read the supported_signature_algorithms for TLS 1.2 or later.
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- algorithmsLen = input.getInt16();
- if (algorithmsLen < 2) {
- throw new SSLProtocolException(
- "Invalid supported_signature_algorithms field");
- }
-
- algorithms = new ArrayList<SignatureAndHashAlgorithm>();
- int remains = algorithmsLen;
- int sequence = 0;
- while (remains > 1) { // needs at least two bytes
- int hash = input.getInt8(); // hash algorithm
- int signature = input.getInt8(); // signature algorithm
-
- SignatureAndHashAlgorithm algorithm =
- SignatureAndHashAlgorithm.valueOf(hash, signature,
- ++sequence);
- algorithms.add(algorithm);
- remains -= 2; // one byte for hash, one byte for signature
- }
-
- if (remains != 0) {
- throw new SSLProtocolException(
- "Invalid supported_signature_algorithms field");
- }
- } else {
- algorithms = new ArrayList<SignatureAndHashAlgorithm>();
- algorithmsLen = 0;
- }
-
- // read the certificate_authorities
- int len = input.getInt16();
- ArrayList<DistinguishedName> v = new ArrayList<>();
- while (len >= 3) {
- DistinguishedName dn = new DistinguishedName(input);
- v.add(dn);
- len -= dn.length();
- }
-
- if (len != 0) {
- throw new SSLProtocolException("Bad CertificateRequest DN length");
- }
-
- authorities = v.toArray(new DistinguishedName[v.size()]);
- }
-
- X500Principal[] getAuthorities() throws IOException {
- X500Principal[] ret = new X500Principal[authorities.length];
- for (int i = 0; i < authorities.length; i++) {
- ret[i] = authorities[i].getX500Principal();
- }
- return ret;
- }
-
- Collection<SignatureAndHashAlgorithm> getSignAlgorithms() {
- return algorithms;
- }
-
- @Override
- int messageType() {
- return ht_certificate_request;
- }
-
- @Override
- int messageLength() {
- int len = 1 + types.length + 2;
-
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- len += algorithmsLen + 2;
- }
-
- for (int i = 0; i < authorities.length; i++) {
- len += authorities[i].length();
- }
-
- return len;
- }
-
- @Override
- void send(HandshakeOutStream output) throws IOException {
- // put certificate_types
- output.putBytes8(types);
-
- // put supported_signature_algorithms
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- output.putInt16(algorithmsLen);
- for (SignatureAndHashAlgorithm algorithm : algorithms) {
- output.putInt8(algorithm.getHashValue()); // hash
- output.putInt8(algorithm.getSignatureValue()); // signature
- }
- }
-
- // put certificate_authorities
- int len = 0;
- for (int i = 0; i < authorities.length; i++) {
- len += authorities[i].length();
- }
-
- output.putInt16(len);
- for (int i = 0; i < authorities.length; i++) {
- authorities[i].send(output);
- }
- }
-
- @Override
- void print(PrintStream s) throws IOException {
- s.println("*** CertificateRequest");
-
- if (debug != null && Debug.isOn("verbose")) {
- s.print("Cert Types: ");
- for (int i = 0; i < types.length; i++) {
- switch (types[i]) {
- case cct_rsa_sign:
- s.print("RSA"); break;
- case cct_dss_sign:
- s.print("DSS"); break;
- case cct_rsa_fixed_dh:
- s.print("Fixed DH (RSA sig)"); break;
- case cct_dss_fixed_dh:
- s.print("Fixed DH (DSS sig)"); break;
- case cct_rsa_ephemeral_dh:
- s.print("Ephemeral DH (RSA sig)"); break;
- case cct_dss_ephemeral_dh:
- s.print("Ephemeral DH (DSS sig)"); break;
- case cct_ecdsa_sign:
- s.print("ECDSA"); break;
- case cct_rsa_fixed_ecdh:
- s.print("Fixed ECDH (RSA sig)"); break;
- case cct_ecdsa_fixed_ecdh:
- s.print("Fixed ECDH (ECDSA sig)"); break;
- default:
- s.print("Type-" + (types[i] & 0xff)); break;
- }
- if (i != types.length - 1) {
- s.print(", ");
- }
- }
- s.println();
-
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- StringBuffer buffer = new StringBuffer();
- boolean opened = false;
- for (SignatureAndHashAlgorithm signAlg : algorithms) {
- if (opened) {
- buffer.append(", " + signAlg.getAlgorithmName());
- } else {
- buffer.append(signAlg.getAlgorithmName());
- opened = true;
- }
- }
- s.println("Supported Signature Algorithms: " + buffer);
- }
-
- s.println("Cert Authorities:");
- if (authorities.length == 0) {
- s.println("<Empty>");
- } else {
- for (int i = 0; i < authorities.length; i++) {
- authorities[i].print(s);
- }
- }
- }
- }
-}
-
-
-/*
- * ServerHelloDone ... SERVER --> CLIENT
- *
- * When server's done sending its messages in response to the client's
- * "hello" (e.g. its own hello, certificate, key exchange message, perhaps
- * client certificate request) it sends this message to flag that it's
- * done that part of the handshake.
- */
-static final
-class ServerHelloDone extends HandshakeMessage
-{
- int messageType() { return ht_server_hello_done; }
-
- ServerHelloDone() { }
-
- ServerHelloDone(HandshakeInStream input)
- {
- // nothing to do
- }
-
- int messageLength()
- {
- return 0;
- }
-
- void send(HandshakeOutStream s) throws IOException
- {
- // nothing to send
- }
-
- void print(PrintStream s) throws IOException
- {
- s.println("*** ServerHelloDone");
- }
-}
-
-
-/*
- * CertificateVerify ... CLIENT --> SERVER
- *
- * Sent after client sends signature-capable certificates (e.g. not
- * Diffie-Hellman) to verify.
- */
-static final class CertificateVerify extends HandshakeMessage {
-
- // the signature bytes
- private byte[] signature;
-
- // protocol version being established using this ServerKeyExchange message
- ProtocolVersion protocolVersion;
-
- // the preferable signature algorithm used by this CertificateVerify message
- private SignatureAndHashAlgorithm preferableSignatureAlgorithm = null;
-
- /*
- * Create an RSA or DSA signed certificate verify message.
- */
- CertificateVerify(ProtocolVersion protocolVersion,
- HandshakeHash handshakeHash, PrivateKey privateKey,
- SecretKey masterSecret, SecureRandom sr,
- SignatureAndHashAlgorithm signAlgorithm)
- throws GeneralSecurityException {
-
- this.protocolVersion = protocolVersion;
-
- String algorithm = privateKey.getAlgorithm();
- Signature sig = null;
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- this.preferableSignatureAlgorithm = signAlgorithm;
- sig = JsseJce.getSignature(signAlgorithm.getAlgorithmName());
- } else {
- sig = getSignature(protocolVersion, algorithm);
- }
- sig.initSign(privateKey, sr);
- updateSignature(sig, protocolVersion, handshakeHash, algorithm,
- masterSecret);
- signature = sig.sign();
- }
-
- //
- // Unmarshal the signed data from the input stream.
- //
- CertificateVerify(HandshakeInStream input,
- Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
- ProtocolVersion protocolVersion) throws IOException {
-
- this.protocolVersion = protocolVersion;
-
- // read the signature and hash algorithm
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- int hashAlg = input.getInt8(); // hash algorithm
- int signAlg = input.getInt8(); // signature algorithm
-
- preferableSignatureAlgorithm =
- SignatureAndHashAlgorithm.valueOf(hashAlg, signAlg, 0);
-
- // Is it a local supported signature algorithm?
- if (!localSupportedSignAlgs.contains(
- preferableSignatureAlgorithm)) {
- throw new SSLHandshakeException(
- "Unsupported SignatureAndHashAlgorithm in " +
- "ServerKeyExchange message");
- }
- }
-
- // read the signature
- signature = input.getBytes16();
- }
-
- /*
- * Get the preferable signature algorithm used by this message
- */
- SignatureAndHashAlgorithm getPreferableSignatureAlgorithm() {
- return preferableSignatureAlgorithm;
- }
-
- /*
- * Verify a certificate verify message. Return the result of verification,
- * if there is a problem throw a GeneralSecurityException.
- */
- boolean verify(ProtocolVersion protocolVersion,
- HandshakeHash handshakeHash, PublicKey publicKey,
- SecretKey masterSecret) throws GeneralSecurityException {
- String algorithm = publicKey.getAlgorithm();
- Signature sig = null;
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- sig = JsseJce.getSignature(
- preferableSignatureAlgorithm.getAlgorithmName());
- } else {
- sig = getSignature(protocolVersion, algorithm);
- }
- sig.initVerify(publicKey);
- updateSignature(sig, protocolVersion, handshakeHash, algorithm,
- masterSecret);
- return sig.verify(signature);
- }
-
- /*
- * Get the Signature object appropriate for verification using the
- * given signature algorithm and protocol version.
- */
- private static Signature getSignature(ProtocolVersion protocolVersion,
- String algorithm) throws GeneralSecurityException {
- if (algorithm.equals("RSA")) {
- return RSASignature.getInternalInstance();
- } else if (algorithm.equals("DSA")) {
- return JsseJce.getSignature(JsseJce.SIGNATURE_RAWDSA);
- } else if (algorithm.equals("EC")) {
- return JsseJce.getSignature(JsseJce.SIGNATURE_RAWECDSA);
- } else {
- throw new SignatureException("Unrecognized algorithm: "
- + algorithm);
- }
- }
-
- /*
- * Update the Signature with the data appropriate for the given
- * signature algorithm and protocol version so that the object is
- * ready for signing or verifying.
- */
- private static void updateSignature(Signature sig,
- ProtocolVersion protocolVersion,
- HandshakeHash handshakeHash, String algorithm, SecretKey masterKey)
- throws SignatureException {
-
- if (algorithm.equals("RSA")) {
- if (protocolVersion.v < ProtocolVersion.TLS12.v) { // TLS1.1-
- MessageDigest md5Clone = handshakeHash.getMD5Clone();
- MessageDigest shaClone = handshakeHash.getSHAClone();
-
- if (protocolVersion.v < ProtocolVersion.TLS10.v) { // SSLv3
- updateDigest(md5Clone, MD5_pad1, MD5_pad2, masterKey);
- updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
- }
-
- // The signature must be an instance of RSASignature, need
- // to use these hashes directly.
- RSASignature.setHashes(sig, md5Clone, shaClone);
- } else { // TLS1.2+
- sig.update(handshakeHash.getAllHandshakeMessages());
- }
- } else { // DSA, ECDSA
- if (protocolVersion.v < ProtocolVersion.TLS12.v) { // TLS1.1-
- MessageDigest shaClone = handshakeHash.getSHAClone();
-
- if (protocolVersion.v < ProtocolVersion.TLS10.v) { // SSLv3
- updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
- }
-
- sig.update(shaClone.digest());
- } else { // TLS1.2+
- sig.update(handshakeHash.getAllHandshakeMessages());
- }
- }
- }
-
- /*
- * Update the MessageDigest for SSLv3 certificate verify or finished
- * message calculation. The digest must already have been updated with
- * all preceding handshake messages.
- * Used by the Finished class as well.
- */
- private static void updateDigest(MessageDigest md,
- byte[] pad1, byte[] pad2,
- SecretKey masterSecret) {
- // Digest the key bytes if available.
- // Otherwise (sensitive key), try digesting the key directly.
- // That is currently only implemented in SunPKCS11 using a private
- // reflection API, so we avoid that if possible.
- byte[] keyBytes = "RAW".equals(masterSecret.getFormat())
- ? masterSecret.getEncoded() : null;
- if (keyBytes != null) {
- md.update(keyBytes);
- } else {
- digestKey(md, masterSecret);
- }
- md.update(pad1);
- byte[] temp = md.digest();
-
- if (keyBytes != null) {
- md.update(keyBytes);
- } else {
- digestKey(md, masterSecret);
- }
- md.update(pad2);
- md.update(temp);
- }
-
- private final static Class delegate;
- private final static Field spiField;
-
- static {
- try {
- delegate = Class.forName("java.security.MessageDigest$Delegate");
- spiField = delegate.getDeclaredField("digestSpi");
- } catch (Exception e) {
- throw new RuntimeException("Reflection failed", e);
- }
- makeAccessible(spiField);
- }
-
- private static void makeAccessible(final AccessibleObject o) {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- o.setAccessible(true);
- return null;
- }
- });
- }
-
- // ConcurrentHashMap does not allow null values, use this marker object
- private final static Object NULL_OBJECT = new Object();
-
- // cache Method objects per Spi class
- // Note that this will prevent the Spi classes from being GC'd. We assume
- // that is not a problem.
- private final static Map<Class,Object> methodCache =
- new ConcurrentHashMap<>();
-
- private static void digestKey(MessageDigest md, SecretKey key) {
- try {
- // Verify that md is implemented via MessageDigestSpi, not
- // via JDK 1.1 style MessageDigest subclassing.
- if (md.getClass() != delegate) {
- throw new Exception("Digest is not a MessageDigestSpi");
- }
- MessageDigestSpi spi = (MessageDigestSpi)spiField.get(md);
- Class<?> clazz = spi.getClass();
- Object r = methodCache.get(clazz);
- if (r == null) {
- try {
- r = clazz.getDeclaredMethod("implUpdate", SecretKey.class);
- makeAccessible((Method)r);
- } catch (NoSuchMethodException e) {
- r = NULL_OBJECT;
- }
- methodCache.put(clazz, r);
- }
- if (r == NULL_OBJECT) {
- throw new Exception(
- "Digest does not support implUpdate(SecretKey)");
- }
- Method update = (Method)r;
- update.invoke(spi, key);
- } catch (Exception e) {
- throw new RuntimeException(
- "Could not obtain encoded key and "
- + "MessageDigest cannot digest key", e);
- }
- }
-
- @Override
- int messageType() {
- return ht_certificate_verify;
- }
-
- @Override
- int messageLength() {
- int temp = 2;
-
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- temp += SignatureAndHashAlgorithm.sizeInRecord();
- }
-
- return temp + signature.length;
- }
-
- @Override
- void send(HandshakeOutStream s) throws IOException {
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- s.putInt8(preferableSignatureAlgorithm.getHashValue());
- s.putInt8(preferableSignatureAlgorithm.getSignatureValue());
- }
-
- s.putBytes16(signature);
- }
-
- @Override
- void print(PrintStream s) throws IOException {
- s.println("*** CertificateVerify");
-
- if (debug != null && Debug.isOn("verbose")) {
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- s.println("Signature Algorithm " +
- preferableSignatureAlgorithm.getAlgorithmName());
- }
- }
- }
-}
-
-
-/*
- * FINISHED ... sent by both CLIENT and SERVER
- *
- * This is the FINISHED message as defined in the SSL and TLS protocols.
- * Both protocols define this handshake message slightly differently.
- * This class supports both formats.
- *
- * When handshaking is finished, each side sends a "change_cipher_spec"
- * record, then immediately sends a "finished" handshake message prepared
- * according to the newly adopted cipher spec.
- *
- * NOTE that until this is sent, no application data may be passed, unless
- * some non-default cipher suite has already been set up on this connection
- * connection (e.g. a previous handshake arranged one).
- */
-static final class Finished extends HandshakeMessage {
-
- // constant for a Finished message sent by the client
- final static int CLIENT = 1;
-
- // constant for a Finished message sent by the server
- final static int SERVER = 2;
-
- // enum Sender: "CLNT" and "SRVR"
- private static final byte[] SSL_CLIENT = { 0x43, 0x4C, 0x4E, 0x54 };
- private static final byte[] SSL_SERVER = { 0x53, 0x52, 0x56, 0x52 };
-
- /*
- * Contents of the finished message ("checksum"). For TLS, it
- * is 12 bytes long, for SSLv3 36 bytes.
- */
- private byte[] verifyData;
-
- /*
- * Current cipher suite we are negotiating. TLS 1.2 has
- * ciphersuite-defined PRF algorithms.
- */
- private ProtocolVersion protocolVersion;
- private CipherSuite cipherSuite;
-
- /*
- * Create a finished message to send to the remote peer.
- */
- Finished(ProtocolVersion protocolVersion, HandshakeHash handshakeHash,
- int sender, SecretKey master, CipherSuite cipherSuite) {
- this.protocolVersion = protocolVersion;
- this.cipherSuite = cipherSuite;
- verifyData = getFinished(handshakeHash, sender, master);
- }
-
- /*
- * Constructor that reads FINISHED message from stream.
- */
- Finished(ProtocolVersion protocolVersion, HandshakeInStream input,
- CipherSuite cipherSuite) throws IOException {
- this.protocolVersion = protocolVersion;
- this.cipherSuite = cipherSuite;
- int msgLen = (protocolVersion.v >= ProtocolVersion.TLS10.v) ? 12 : 36;
- verifyData = new byte[msgLen];
- input.read(verifyData);
- }
-
- /*
- * Verify that the hashes here are what would have been produced
- * according to a given set of inputs. This is used to ensure that
- * both client and server are fully in sync, and that the handshake
- * computations have been successful.
- */
- boolean verify(HandshakeHash handshakeHash, int sender, SecretKey master) {
- byte[] myFinished = getFinished(handshakeHash, sender, master);
- return Arrays.equals(myFinished, verifyData);
- }
-
- /*
- * Perform the actual finished message calculation.
- */
- private byte[] getFinished(HandshakeHash handshakeHash,
- int sender, SecretKey masterKey) {
- byte[] sslLabel;
- String tlsLabel;
- if (sender == CLIENT) {
- sslLabel = SSL_CLIENT;
- tlsLabel = "client finished";
- } else if (sender == SERVER) {
- sslLabel = SSL_SERVER;
- tlsLabel = "server finished";
- } else {
- throw new RuntimeException("Invalid sender: " + sender);
- }
-
- if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
- // TLS 1.0+
- try {
- byte [] seed;
- String prfAlg;
- PRF prf;
-
- // Get the KeyGenerator alg and calculate the seed.
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- // TLS 1.2
- seed = handshakeHash.getFinishedHash();
-
- prfAlg = "SunTls12Prf";
- prf = cipherSuite.prfAlg;
- } else {
- // TLS 1.0/1.1
- MessageDigest md5Clone = handshakeHash.getMD5Clone();
- MessageDigest shaClone = handshakeHash.getSHAClone();
- seed = new byte[36];
- md5Clone.digest(seed, 0, 16);
- shaClone.digest(seed, 16, 20);
-
- prfAlg = "SunTlsPrf";
- prf = P_NONE;
- }
-
- String prfHashAlg = prf.getPRFHashAlg();
- int prfHashLength = prf.getPRFHashLength();
- int prfBlockSize = prf.getPRFBlockSize();
-
- /*
- * RFC 5246/7.4.9 says that finished messages can
- * be ciphersuite-specific in both length/PRF hash
- * algorithm. If we ever run across a different
- * length, this call will need to be updated.
- */
- TlsPrfParameterSpec spec = new TlsPrfParameterSpec(
- masterKey, tlsLabel, seed, 12,
- prfHashAlg, prfHashLength, prfBlockSize);
-
- KeyGenerator kg = JsseJce.getKeyGenerator(prfAlg);
- kg.init(spec);
- SecretKey prfKey = kg.generateKey();
- if ("RAW".equals(prfKey.getFormat()) == false) {
- throw new ProviderException(
- "Invalid PRF output, format must be RAW");
- }
- byte[] finished = prfKey.getEncoded();
- return finished;
- } catch (GeneralSecurityException e) {
- throw new RuntimeException("PRF failed", e);
- }
- } else {
- // SSLv3
- MessageDigest md5Clone = handshakeHash.getMD5Clone();
- MessageDigest shaClone = handshakeHash.getSHAClone();
- updateDigest(md5Clone, sslLabel, MD5_pad1, MD5_pad2, masterKey);
- updateDigest(shaClone, sslLabel, SHA_pad1, SHA_pad2, masterKey);
- byte[] finished = new byte[36];
- try {
- md5Clone.digest(finished, 0, 16);
- shaClone.digest(finished, 16, 20);
- } catch (DigestException e) {
- // cannot occur
- throw new RuntimeException("Digest failed", e);
- }
- return finished;
- }
- }
-
- /*
- * Update the MessageDigest for SSLv3 finished message calculation.
- * The digest must already have been updated with all preceding handshake
- * messages. This operation is almost identical to the certificate verify
- * hash, reuse that code.
- */
- private static void updateDigest(MessageDigest md, byte[] sender,
- byte[] pad1, byte[] pad2, SecretKey masterSecret) {
- md.update(sender);
- CertificateVerify.updateDigest(md, pad1, pad2, masterSecret);
- }
-
- // get the verify_data of the finished message
- byte[] getVerifyData() {
- return verifyData;
- }
-
- @Override
- int messageType() { return ht_finished; }
-
- @Override
- int messageLength() {
- return verifyData.length;
- }
-
- @Override
- void send(HandshakeOutStream out) throws IOException {
- out.write(verifyData);
- }
-
- @Override
- void print(PrintStream s) throws IOException {
- s.println("*** Finished");
- if (debug != null && Debug.isOn("verbose")) {
- Debug.println(s, "verify_data", verifyData);
- s.println("***");
- }
- }
-}
-
-//
-// END of nested classes
-//
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/HandshakeOutStream.java b/ojluni/src/main/java/sun/security/ssl/HandshakeOutStream.java
deleted file mode 100755
index 25aeed6..0000000
--- a/ojluni/src/main/java/sun/security/ssl/HandshakeOutStream.java
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.OutputStream;
-import java.io.IOException;
-import java.security.MessageDigest;
-
-/**
- * Output stream for handshake data. This is used only internally
- * to the SSL classes.
- *
- * MT note: one thread at a time is presumed be writing handshake
- * messages, but (after initial connection setup) it's possible to
- * have other threads reading/writing application data. It's the
- * SSLSocketImpl class that synchronizes record writes.
- *
- * @author David Brownell
- */
-public class HandshakeOutStream extends OutputStream {
-
- private SSLSocketImpl socket;
- private SSLEngineImpl engine;
-
- OutputRecord r;
-
- HandshakeOutStream(ProtocolVersion protocolVersion,
- ProtocolVersion helloVersion, HandshakeHash handshakeHash,
- SSLSocketImpl socket) {
- this.socket = socket;
- r = new OutputRecord(Record.ct_handshake);
- init(protocolVersion, helloVersion, handshakeHash);
- }
-
- HandshakeOutStream(ProtocolVersion protocolVersion,
- ProtocolVersion helloVersion, HandshakeHash handshakeHash,
- SSLEngineImpl engine) {
- this.engine = engine;
- r = new EngineOutputRecord(Record.ct_handshake, engine);
- init(protocolVersion, helloVersion, handshakeHash);
- }
-
- private void init(ProtocolVersion protocolVersion,
- ProtocolVersion helloVersion, HandshakeHash handshakeHash) {
- r.setVersion(protocolVersion);
- r.setHelloVersion(helloVersion);
- r.setHandshakeHash(handshakeHash);
- }
-
-
- /*
- * Update the handshake data hashes ... mostly for use after a
- * client cert has been sent, so the cert verify message can be
- * constructed correctly yet without forcing extra I/O. In all
- * other cases, automatic hash calculation suffices.
- */
- void doHashes() {
- r.doHashes();
- }
-
- /*
- * Write some data out onto the stream ... buffers as much as possible.
- * Hashes are updated automatically if something gets flushed to the
- * network (e.g. a big cert message etc).
- */
- public void write(byte buf[], int off, int len) throws IOException {
- while (len > 0) {
- int howmuch = Math.min(len, r.availableDataBytes());
-
- if (howmuch == 0) {
- flush();
- } else {
- r.write(buf, off, howmuch);
- off += howmuch;
- len -= howmuch;
- }
- }
- }
-
- /*
- * write-a-byte
- */
- public void write(int i) throws IOException {
- if (r.availableDataBytes() < 1) {
- flush();
- }
- r.write(i);
- }
-
- public void flush() throws IOException {
- if (socket != null) {
- try {
- socket.writeRecord(r);
- } catch (IOException e) {
- // Had problems writing; check if there was an
- // alert from peer. If alert received, waitForClose
- // will throw an exception for the alert
- socket.waitForClose(true);
-
- // No alert was received, just rethrow exception
- throw e;
- }
- } else { // engine != null
- /*
- * Even if record might be empty, flush anyway in case
- * there is a finished handshake message that we need
- * to queue.
- */
- engine.writeRecord((EngineOutputRecord)r);
- }
- }
-
- /*
- * Tell the OutputRecord that a finished message was
- * contained either in this record or the one immeiately
- * preceeding it. We need to reliably pass back notifications
- * that a finish message occured.
- */
- void setFinishedMsg() {
- assert(socket == null);
-
- ((EngineOutputRecord)r).setFinishedMsg();
- }
-
- /*
- * Put integers encoded in standard 8, 16, 24, and 32 bit
- * big endian formats. Note that OutputStream.write(int) only
- * writes the least significant 8 bits and ignores the rest.
- */
-
- void putInt8(int i) throws IOException {
- checkOverflow(i, Record.OVERFLOW_OF_INT08);
- r.write(i);
- }
-
- void putInt16(int i) throws IOException {
- checkOverflow(i, Record.OVERFLOW_OF_INT16);
- if (r.availableDataBytes() < 2) {
- flush();
- }
- r.write(i >> 8);
- r.write(i);
- }
-
- void putInt24(int i) throws IOException {
- checkOverflow(i, Record.OVERFLOW_OF_INT24);
- if (r.availableDataBytes() < 3) {
- flush();
- }
- r.write(i >> 16);
- r.write(i >> 8);
- r.write(i);
- }
-
- void putInt32(int i) throws IOException {
- if (r.availableDataBytes() < 4) {
- flush();
- }
- r.write(i >> 24);
- r.write(i >> 16);
- r.write(i >> 8);
- r.write(i);
- }
-
- /*
- * Put byte arrays with length encoded as 8, 16, 24 bit
- * integers in big-endian format.
- */
- void putBytes8(byte b[]) throws IOException {
- if (b == null) {
- putInt8(0);
- return;
- } else {
- checkOverflow(b.length, Record.OVERFLOW_OF_INT08);
- }
- putInt8(b.length);
- write(b, 0, b.length);
- }
-
- public void putBytes16(byte b[]) throws IOException {
- if (b == null) {
- putInt16(0);
- return;
- } else {
- checkOverflow(b.length, Record.OVERFLOW_OF_INT16);
- }
- putInt16(b.length);
- write(b, 0, b.length);
- }
-
- void putBytes24(byte b[]) throws IOException {
- if (b == null) {
- putInt24(0);
- return;
- } else {
- checkOverflow(b.length, Record.OVERFLOW_OF_INT24);
- }
- putInt24(b.length);
- write(b, 0, b.length);
- }
-
- private void checkOverflow(int length, int overflow) {
- if (length >= overflow) {
- // internal_error alert will be triggered
- throw new RuntimeException(
- "Field length overflow, the field length (" +
- length + ") should be less than " + overflow);
- }
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/Handshaker.java b/ojluni/src/main/java/sun/security/ssl/Handshaker.java
deleted file mode 100755
index 2f1d01b..0000000
--- a/ojluni/src/main/java/sun/security/ssl/Handshaker.java
+++ /dev/null
@@ -1,1384 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.util.*;
-import java.security.*;
-import java.security.NoSuchAlgorithmException;
-import java.security.AccessController;
-import java.security.AlgorithmConstraints;
-import java.security.AccessControlContext;
-import java.security.PrivilegedExceptionAction;
-import java.security.PrivilegedActionException;
-
-import javax.crypto.*;
-import javax.crypto.spec.*;
-
-import javax.net.ssl.*;
-import sun.misc.HexDumpEncoder;
-
-import sun.security.internal.spec.*;
-import sun.security.internal.interfaces.TlsMasterSecret;
-
-import sun.security.ssl.HandshakeMessage.*;
-import sun.security.ssl.CipherSuite.*;
-
-import static sun.security.ssl.CipherSuite.PRF.*;
-
-/**
- * Handshaker ... processes handshake records from an SSL V3.0
- * data stream, handling all the details of the handshake protocol.
- *
- * Note that the real protocol work is done in two subclasses, the base
- * class just provides the control flow and key generation framework.
- *
- * @author David Brownell
- */
-abstract class Handshaker {
-
- // protocol version being established using this Handshaker
- ProtocolVersion protocolVersion;
-
- // the currently active protocol version during a renegotiation
- ProtocolVersion activeProtocolVersion;
-
- // security parameters for secure renegotiation.
- boolean secureRenegotiation;
- byte[] clientVerifyData;
- byte[] serverVerifyData;
-
- // Is it an initial negotiation or a renegotiation?
- boolean isInitialHandshake;
-
- // List of enabled protocols
- private ProtocolList enabledProtocols;
-
- // List of enabled CipherSuites
- private CipherSuiteList enabledCipherSuites;
-
- // The endpoint identification protocol
- String identificationProtocol;
-
- // The cryptographic algorithm constraints
- private AlgorithmConstraints algorithmConstraints = null;
-
- // Local supported signature and algorithms
- Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs;
-
- // Peer supported signature and algorithms
- Collection<SignatureAndHashAlgorithm> peerSupportedSignAlgs;
-
- /*
-
- /*
- * List of active protocols
- *
- * Active protocols is a subset of enabled protocols, and will
- * contain only those protocols that have vaild cipher suites
- * enabled.
- */
- private ProtocolList activeProtocols;
-
- /*
- * List of active cipher suites
- *
- * Active cipher suites is a subset of enabled cipher suites, and will
- * contain only those cipher suites available for the active protocols.
- */
- private CipherSuiteList activeCipherSuites;
-
- private boolean isClient;
- private boolean needCertVerify;
-
- SSLSocketImpl conn = null;
- SSLEngineImpl engine = null;
-
- HandshakeHash handshakeHash;
- HandshakeInStream input;
- HandshakeOutStream output;
- int state;
- SSLContextImpl sslContext;
- RandomCookie clnt_random, svr_random;
- SSLSessionImpl session;
-
- // current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL
- CipherSuite cipherSuite;
-
- // current key exchange. Never null, initially K_NULL
- KeyExchange keyExchange;
-
- /* True if this session is being resumed (fast handshake) */
- boolean resumingSession;
-
- /* True if it's OK to start a new SSL session */
- boolean enableNewSession;
-
- // Temporary storage for the individual keys. Set by
- // calculateConnectionKeys() and cleared once the ciphers are
- // activated.
- private SecretKey clntWriteKey, svrWriteKey;
- private IvParameterSpec clntWriteIV, svrWriteIV;
- private SecretKey clntMacSecret, svrMacSecret;
-
- /*
- * Delegated task subsystem data structures.
- *
- * If thrown is set, we need to propagate this back immediately
- * on entry into processMessage().
- *
- * Data is protected by the SSLEngine.this lock.
- */
- private volatile boolean taskDelegated = false;
- private volatile DelegatedTask delegatedTask = null;
- private volatile Exception thrown = null;
-
- // Could probably use a java.util.concurrent.atomic.AtomicReference
- // here instead of using this lock. Consider changing.
- private Object thrownLock = new Object();
-
- /* Class and subclass dynamic debugging support */
- static final Debug debug = Debug.getInstance("ssl");
-
- // By default, disable the unsafe legacy session renegotiation
- static final boolean allowUnsafeRenegotiation = Debug.getBooleanProperty(
- "sun.security.ssl.allowUnsafeRenegotiation", false);
-
- // For maximum interoperability and backward compatibility, RFC 5746
- // allows server (or client) to accept ClientHello (or ServerHello)
- // message without the secure renegotiation_info extension or SCSV.
- //
- // For maximum security, RFC 5746 also allows server (or client) to
- // reject such message with a fatal "handshake_failure" alert.
- //
- // By default, allow such legacy hello messages.
- static final boolean allowLegacyHelloMessages = Debug.getBooleanProperty(
- "sun.security.ssl.allowLegacyHelloMessages", true);
-
- // need to dispose the object when it is invalidated
- boolean invalidated;
-
- Handshaker(SSLSocketImpl c, SSLContextImpl context,
- ProtocolList enabledProtocols, boolean needCertVerify,
- boolean isClient, ProtocolVersion activeProtocolVersion,
- boolean isInitialHandshake, boolean secureRenegotiation,
- byte[] clientVerifyData, byte[] serverVerifyData) {
- this.conn = c;
- init(context, enabledProtocols, needCertVerify, isClient,
- activeProtocolVersion, isInitialHandshake, secureRenegotiation,
- clientVerifyData, serverVerifyData);
- }
-
- Handshaker(SSLEngineImpl engine, SSLContextImpl context,
- ProtocolList enabledProtocols, boolean needCertVerify,
- boolean isClient, ProtocolVersion activeProtocolVersion,
- boolean isInitialHandshake, boolean secureRenegotiation,
- byte[] clientVerifyData, byte[] serverVerifyData) {
- this.engine = engine;
- init(context, enabledProtocols, needCertVerify, isClient,
- activeProtocolVersion, isInitialHandshake, secureRenegotiation,
- clientVerifyData, serverVerifyData);
- }
-
- private void init(SSLContextImpl context, ProtocolList enabledProtocols,
- boolean needCertVerify, boolean isClient,
- ProtocolVersion activeProtocolVersion,
- boolean isInitialHandshake, boolean secureRenegotiation,
- byte[] clientVerifyData, byte[] serverVerifyData) {
-
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println(
- "Allow unsafe renegotiation: " + allowUnsafeRenegotiation +
- "\nAllow legacy hello messages: " + allowLegacyHelloMessages +
- "\nIs initial handshake: " + isInitialHandshake +
- "\nIs secure renegotiation: " + secureRenegotiation);
- }
-
- this.sslContext = context;
- this.isClient = isClient;
- this.needCertVerify = needCertVerify;
- this.activeProtocolVersion = activeProtocolVersion;
- this.isInitialHandshake = isInitialHandshake;
- this.secureRenegotiation = secureRenegotiation;
- this.clientVerifyData = clientVerifyData;
- this.serverVerifyData = serverVerifyData;
- enableNewSession = true;
- invalidated = false;
-
- setCipherSuite(CipherSuite.C_NULL);
- setEnabledProtocols(enabledProtocols);
-
- if (conn != null) {
- algorithmConstraints = new SSLAlgorithmConstraints(conn, true);
- } else { // engine != null
- algorithmConstraints = new SSLAlgorithmConstraints(engine, true);
- }
-
-
- //
- // In addition to the connection state machine, controlling
- // how the connection deals with the different sorts of records
- // that get sent (notably handshake transitions!), there's
- // also a handshaking state machine that controls message
- // sequencing.
- //
- // It's a convenient artifact of the protocol that this can,
- // with only a couple of minor exceptions, be driven by the
- // type constant for the last message seen: except for the
- // client's cert verify, those constants are in a convenient
- // order to drastically simplify state machine checking.
- //
- state = -2; // initialized but not activated
- }
-
- /*
- * Reroutes calls to the SSLSocket or SSLEngine (*SE).
- *
- * We could have also done it by extra classes
- * and letting them override, but this seemed much
- * less involved.
- */
- void fatalSE(byte b, String diagnostic) throws IOException {
- fatalSE(b, diagnostic, null);
- }
-
- void fatalSE(byte b, Throwable cause) throws IOException {
- fatalSE(b, null, cause);
- }
-
- void fatalSE(byte b, String diagnostic, Throwable cause)
- throws IOException {
- if (conn != null) {
- conn.fatal(b, diagnostic, cause);
- } else {
- engine.fatal(b, diagnostic, cause);
- }
- }
-
- void warningSE(byte b) {
- if (conn != null) {
- conn.warning(b);
- } else {
- engine.warning(b);
- }
- }
-
- String getRawHostnameSE() {
- if (conn != null) {
- return conn.getRawHostname();
- } else {
- return engine.getPeerHost();
- }
- }
-
- String getHostSE() {
- if (conn != null) {
- return conn.getHost();
- } else {
- return engine.getPeerHost();
- }
- }
-
- String getHostAddressSE() {
- if (conn != null) {
- return conn.getInetAddress().getHostAddress();
- } else {
- /*
- * This is for caching only, doesn't matter that's is really
- * a hostname. The main thing is that it doesn't do
- * a reverse DNS lookup, potentially slowing things down.
- */
- return engine.getPeerHost();
- }
- }
-
- boolean isLoopbackSE() {
- if (conn != null) {
- return conn.getInetAddress().isLoopbackAddress();
- } else {
- return false;
- }
- }
-
- int getPortSE() {
- if (conn != null) {
- return conn.getPort();
- } else {
- return engine.getPeerPort();
- }
- }
-
- int getLocalPortSE() {
- if (conn != null) {
- return conn.getLocalPort();
- } else {
- return -1;
- }
- }
-
- AccessControlContext getAccSE() {
- if (conn != null) {
- return conn.getAcc();
- } else {
- return engine.getAcc();
- }
- }
-
- private void setVersionSE(ProtocolVersion protocolVersion) {
- if (conn != null) {
- conn.setVersion(protocolVersion);
- } else {
- engine.setVersion(protocolVersion);
- }
- }
-
- /**
- * Set the active protocol version and propagate it to the SSLSocket
- * and our handshake streams. Called from ClientHandshaker
- * and ServerHandshaker with the negotiated protocol version.
- */
- void setVersion(ProtocolVersion protocolVersion) {
- this.protocolVersion = protocolVersion;
- setVersionSE(protocolVersion);
-
- output.r.setVersion(protocolVersion);
- }
-
- /**
- * Set the enabled protocols. Called from the constructor or
- * SSLSocketImpl/SSLEngineImpl.setEnabledProtocols() (if the
- * handshake is not yet in progress).
- */
- void setEnabledProtocols(ProtocolList enabledProtocols) {
- activeCipherSuites = null;
- activeProtocols = null;
-
- this.enabledProtocols = enabledProtocols;
- }
-
- /**
- * Set the enabled cipher suites. Called from
- * SSLSocketImpl/SSLEngineImpl.setEnabledCipherSuites() (if the
- * handshake is not yet in progress).
- */
- void setEnabledCipherSuites(CipherSuiteList enabledCipherSuites) {
- activeCipherSuites = null;
- activeProtocols = null;
- this.enabledCipherSuites = enabledCipherSuites;
- }
-
- /**
- * Set the algorithm constraints. Called from the constructor or
- * SSLSocketImpl/SSLEngineImpl.setAlgorithmConstraints() (if the
- * handshake is not yet in progress).
- */
- void setAlgorithmConstraints(AlgorithmConstraints algorithmConstraints) {
- activeCipherSuites = null;
- activeProtocols = null;
-
- this.algorithmConstraints =
- new SSLAlgorithmConstraints(algorithmConstraints);
- this.localSupportedSignAlgs = null;
- }
-
- Collection<SignatureAndHashAlgorithm> getLocalSupportedSignAlgs() {
- if (localSupportedSignAlgs == null) {
- localSupportedSignAlgs =
- SignatureAndHashAlgorithm.getSupportedAlgorithms(
- algorithmConstraints);
- }
-
- return localSupportedSignAlgs;
- }
-
- void setPeerSupportedSignAlgs(
- Collection<SignatureAndHashAlgorithm> algorithms) {
- peerSupportedSignAlgs =
- new ArrayList<SignatureAndHashAlgorithm>(algorithms);
- }
-
- Collection<SignatureAndHashAlgorithm> getPeerSupportedSignAlgs() {
- return peerSupportedSignAlgs;
- }
-
-
- /**
- * Set the identification protocol. Called from the constructor or
- * SSLSocketImpl/SSLEngineImpl.setIdentificationProtocol() (if the
- * handshake is not yet in progress).
- */
- void setIdentificationProtocol(String protocol) {
- this.identificationProtocol = protocol;
- }
-
- /**
- * Prior to handshaking, activate the handshake and initialize the version,
- * input stream and output stream.
- */
- void activate(ProtocolVersion helloVersion) throws IOException {
- if (activeProtocols == null) {
- activeProtocols = getActiveProtocols();
- }
-
- if (activeProtocols.collection().isEmpty() ||
- activeProtocols.max.v == ProtocolVersion.NONE.v) {
- throw new SSLHandshakeException("No appropriate protocol");
- }
-
- if (activeCipherSuites == null) {
- activeCipherSuites = getActiveCipherSuites();
- }
-
- if (activeCipherSuites.collection().isEmpty()) {
- throw new SSLHandshakeException("No appropriate cipher suite");
- }
-
- // temporary protocol version until the actual protocol version
- // is negotiated in the Hello exchange. This affects the record
- // version we sent with the ClientHello.
- if (!isInitialHandshake) {
- protocolVersion = activeProtocolVersion;
- } else {
- protocolVersion = activeProtocols.max;
- }
-
- if (helloVersion == null || helloVersion.v == ProtocolVersion.NONE.v) {
- helloVersion = activeProtocols.helloVersion;
- }
-
- // We accumulate digests of the handshake messages so that
- // we can read/write CertificateVerify and Finished messages,
- // getting assurance against some particular active attacks.
- Set<String> localSupportedHashAlgorithms =
- SignatureAndHashAlgorithm.getHashAlgorithmNames(
- getLocalSupportedSignAlgs());
- handshakeHash = new HandshakeHash(!isClient, needCertVerify,
- localSupportedHashAlgorithms);
-
- // Generate handshake input/output stream.
- input = new HandshakeInStream(handshakeHash);
- if (conn != null) {
- output = new HandshakeOutStream(protocolVersion, helloVersion,
- handshakeHash, conn);
- conn.getAppInputStream().r.setHandshakeHash(handshakeHash);
- conn.getAppInputStream().r.setHelloVersion(helloVersion);
- conn.getAppOutputStream().r.setHelloVersion(helloVersion);
- } else {
- output = new HandshakeOutStream(protocolVersion, helloVersion,
- handshakeHash, engine);
- engine.inputRecord.setHandshakeHash(handshakeHash);
- engine.inputRecord.setHelloVersion(helloVersion);
- engine.outputRecord.setHelloVersion(helloVersion);
- }
-
- // move state to activated
- state = -1;
- }
-
- /**
- * Set cipherSuite and keyExchange to the given CipherSuite.
- * Does not perform any verification that this is a valid selection,
- * this must be done before calling this method.
- */
- void setCipherSuite(CipherSuite s) {
- this.cipherSuite = s;
- this.keyExchange = s.keyExchange;
- }
-
- /**
- * Check if the given ciphersuite is enabled and available.
- * Does not check if the required server certificates are available.
- */
- boolean isNegotiable(CipherSuite s) {
- if (activeCipherSuites == null) {
- activeCipherSuites = getActiveCipherSuites();
- }
-
- return activeCipherSuites.contains(s) && s.isNegotiable();
- }
-
- /**
- * Check if the given protocol version is enabled and available.
- */
- boolean isNegotiable(ProtocolVersion protocolVersion) {
- if (activeProtocols == null) {
- activeProtocols = getActiveProtocols();
- }
-
- return activeProtocols.contains(protocolVersion);
- }
-
- /**
- * Select a protocol version from the list. Called from
- * ServerHandshaker to negotiate protocol version.
- *
- * Return the lower of the protocol version suggested in the
- * clien hello and the highest supported by the server.
- */
- ProtocolVersion selectProtocolVersion(ProtocolVersion protocolVersion) {
- if (activeProtocols == null) {
- activeProtocols = getActiveProtocols();
- }
-
- return activeProtocols.selectProtocolVersion(protocolVersion);
- }
-
- /**
- * Get the active cipher suites.
- *
- * In TLS 1.1, many weak or vulnerable cipher suites were obsoleted,
- * such as TLS_RSA_EXPORT_WITH_RC4_40_MD5. The implementation MUST NOT
- * negotiate these cipher suites in TLS 1.1 or later mode.
- *
- * Therefore, when the active protocols only include TLS 1.1 or later,
- * the client cannot request to negotiate those obsoleted cipher
- * suites. That is, the obsoleted suites should not be included in the
- * client hello. So we need to create a subset of the enabled cipher
- * suites, the active cipher suites, which does not contain obsoleted
- * cipher suites of the minimum active protocol.
- *
- * Return empty list instead of null if no active cipher suites.
- */
- CipherSuiteList getActiveCipherSuites() {
- if (activeCipherSuites == null) {
- if (activeProtocols == null) {
- activeProtocols = getActiveProtocols();
- }
-
- ArrayList<CipherSuite> suites = new ArrayList<>();
- if (!(activeProtocols.collection().isEmpty()) &&
- activeProtocols.min.v != ProtocolVersion.NONE.v) {
- for (CipherSuite suite : enabledCipherSuites.collection()) {
- if (suite.obsoleted > activeProtocols.min.v &&
- suite.supported <= activeProtocols.max.v) {
- if (algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- suite.name, null)) {
- suites.add(suite);
- }
- } else if (debug != null && Debug.isOn("verbose")) {
- if (suite.obsoleted <= activeProtocols.min.v) {
- System.out.println(
- "Ignoring obsoleted cipher suite: " + suite);
- } else {
- System.out.println(
- "Ignoring unsupported cipher suite: " + suite);
- }
- }
- }
- }
- activeCipherSuites = new CipherSuiteList(suites);
- }
-
- return activeCipherSuites;
- }
-
- /*
- * Get the active protocol versions.
- *
- * In TLS 1.1, many weak or vulnerable cipher suites were obsoleted,
- * such as TLS_RSA_EXPORT_WITH_RC4_40_MD5. The implementation MUST NOT
- * negotiate these cipher suites in TLS 1.1 or later mode.
- *
- * For example, if "TLS_RSA_EXPORT_WITH_RC4_40_MD5" is the
- * only enabled cipher suite, the client cannot request TLS 1.1 or
- * later, even though TLS 1.1 or later is enabled. We need to create a
- * subset of the enabled protocols, called the active protocols, which
- * contains protocols appropriate to the list of enabled Ciphersuites.
- *
- * Return empty list instead of null if no active protocol versions.
- */
- ProtocolList getActiveProtocols() {
- if (activeProtocols == null) {
- ArrayList<ProtocolVersion> protocols = new ArrayList<>(4);
- for (ProtocolVersion protocol : enabledProtocols.collection()) {
- boolean found = false;
- for (CipherSuite suite : enabledCipherSuites.collection()) {
- if (suite.isAvailable() && suite.obsoleted > protocol.v &&
- suite.supported <= protocol.v) {
- if (algorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- suite.name, null)) {
- protocols.add(protocol);
- found = true;
- break;
- } else if (debug != null && Debug.isOn("verbose")) {
- System.out.println(
- "Ignoring disabled cipher suite: " + suite +
- " for " + protocol);
- }
- } else if (debug != null && Debug.isOn("verbose")) {
- System.out.println(
- "Ignoring unsupported cipher suite: " + suite +
- " for " + protocol);
- }
- }
- if (!found && (debug != null) && Debug.isOn("handshake")) {
- System.out.println(
- "No available cipher suite for " + protocol);
- }
- }
- activeProtocols = new ProtocolList(protocols);
- }
-
- return activeProtocols;
- }
-
- /**
- * As long as handshaking has not activated, we can
- * change whether session creations are allowed.
- *
- * Callers should do their own checking if handshaking
- * has activated.
- */
- void setEnableSessionCreation(boolean newSessions) {
- enableNewSession = newSessions;
- }
-
- /**
- * Create a new read cipher and return it to caller.
- */
- CipherBox newReadCipher() throws NoSuchAlgorithmException {
- BulkCipher cipher = cipherSuite.cipher;
- CipherBox box;
- if (isClient) {
- box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
- sslContext.getSecureRandom(), false);
- svrWriteKey = null;
- svrWriteIV = null;
- } else {
- box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
- sslContext.getSecureRandom(), false);
- clntWriteKey = null;
- clntWriteIV = null;
- }
- return box;
- }
-
- /**
- * Create a new write cipher and return it to caller.
- */
- CipherBox newWriteCipher() throws NoSuchAlgorithmException {
- BulkCipher cipher = cipherSuite.cipher;
- CipherBox box;
- if (isClient) {
- box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV,
- sslContext.getSecureRandom(), true);
- clntWriteKey = null;
- clntWriteIV = null;
- } else {
- box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV,
- sslContext.getSecureRandom(), true);
- svrWriteKey = null;
- svrWriteIV = null;
- }
- return box;
- }
-
- /**
- * Create a new read MAC and return it to caller.
- */
- MAC newReadMAC() throws NoSuchAlgorithmException, InvalidKeyException {
- MacAlg macAlg = cipherSuite.macAlg;
- MAC mac;
- if (isClient) {
- mac = macAlg.newMac(protocolVersion, svrMacSecret);
- svrMacSecret = null;
- } else {
- mac = macAlg.newMac(protocolVersion, clntMacSecret);
- clntMacSecret = null;
- }
- return mac;
- }
-
- /**
- * Create a new write MAC and return it to caller.
- */
- MAC newWriteMAC() throws NoSuchAlgorithmException, InvalidKeyException {
- MacAlg macAlg = cipherSuite.macAlg;
- MAC mac;
- if (isClient) {
- mac = macAlg.newMac(protocolVersion, clntMacSecret);
- clntMacSecret = null;
- } else {
- mac = macAlg.newMac(protocolVersion, svrMacSecret);
- svrMacSecret = null;
- }
- return mac;
- }
-
- /*
- * Returns true iff the handshake sequence is done, so that
- * this freshly created session can become the current one.
- */
- boolean isDone() {
- return state == HandshakeMessage.ht_finished;
- }
-
-
- /*
- * Returns the session which was created through this
- * handshake sequence ... should be called after isDone()
- * returns true.
- */
- SSLSessionImpl getSession() {
- return session;
- }
-
- /*
- * Set the handshake session
- */
- void setHandshakeSessionSE(SSLSessionImpl handshakeSession) {
- if (conn != null) {
- conn.setHandshakeSession(handshakeSession);
- } else {
- engine.setHandshakeSession(handshakeSession);
- }
- }
-
- /*
- * Returns true if renegotiation is in use for this connection.
- */
- boolean isSecureRenegotiation() {
- return secureRenegotiation;
- }
-
- /*
- * Returns the verify_data from the Finished message sent by the client.
- */
- byte[] getClientVerifyData() {
- return clientVerifyData;
- }
-
- /*
- * Returns the verify_data from the Finished message sent by the server.
- */
- byte[] getServerVerifyData() {
- return serverVerifyData;
- }
-
- /*
- * This routine is fed SSL handshake records when they become available,
- * and processes messages found therein.
- */
- void process_record(InputRecord r, boolean expectingFinished)
- throws IOException {
-
- checkThrown();
-
- /*
- * Store the incoming handshake data, then see if we can
- * now process any completed handshake messages
- */
- input.incomingRecord(r);
-
- /*
- * We don't need to create a separate delegatable task
- * for finished messages.
- */
- if ((conn != null) || expectingFinished) {
- processLoop();
- } else {
- delegateTask(new PrivilegedExceptionAction<Void>() {
- public Void run() throws Exception {
- processLoop();
- return null;
- }
- });
- }
- }
-
- /*
- * On input, we hash messages one at a time since servers may need
- * to access an intermediate hash to validate a CertificateVerify
- * message.
- *
- * Note that many handshake messages can come in one record (and often
- * do, to reduce network resource utilization), and one message can also
- * require multiple records (e.g. very large Certificate messages).
- */
- void processLoop() throws IOException {
-
- // need to read off 4 bytes at least to get the handshake
- // message type and length.
- while (input.available() >= 4) {
- byte messageType;
- int messageLen;
-
- /*
- * See if we can read the handshake message header, and
- * then the entire handshake message. If not, wait till
- * we can read and process an entire message.
- */
- input.mark(4);
-
- messageType = (byte)input.getInt8();
- messageLen = input.getInt24();
-
- if (input.available() < messageLen) {
- input.reset();
- return;
- }
-
- /*
- * Process the messsage. We require
- * that processMessage() consumes the entire message. In
- * lieu of explicit error checks (how?!) we assume that the
- * data will look like garbage on encoding/processing errors,
- * and that other protocol code will detect such errors.
- *
- * Note that digesting is normally deferred till after the
- * message has been processed, though to process at least the
- * client's Finished message (i.e. send the server's) we need
- * to acccelerate that digesting.
- *
- * Also, note that hello request messages are never hashed;
- * that includes the hello request header, too.
- */
- if (messageType == HandshakeMessage.ht_hello_request) {
- input.reset();
- processMessage(messageType, messageLen);
- input.ignore(4 + messageLen);
- } else {
- input.mark(messageLen);
- processMessage(messageType, messageLen);
- input.digestNow();
- }
- }
- }
-
-
- /**
- * Returns true iff the handshaker has been activated.
- *
- * In activated state, the handshaker may not send any messages out.
- */
- boolean activated() {
- return state >= -1;
- }
-
- /**
- * Returns true iff the handshaker has sent any messages.
- */
- boolean started() {
- return state >= 0; // 0: HandshakeMessage.ht_hello_request
- // 1: HandshakeMessage.ht_client_hello
- }
-
-
- /*
- * Used to kickstart the negotiation ... either writing a
- * ClientHello or a HelloRequest as appropriate, whichever
- * the subclass returns. NOP if handshaking's already started.
- */
- void kickstart() throws IOException {
- if (state >= 0) {
- return;
- }
-
- HandshakeMessage m = getKickstartMessage();
-
- if (debug != null && Debug.isOn("handshake")) {
- m.print(System.out);
- }
- m.write(output);
- output.flush();
-
- state = m.messageType();
- }
-
- /**
- * Both client and server modes can start handshaking; but the
- * message they send to do so is different.
- */
- abstract HandshakeMessage getKickstartMessage() throws SSLException;
-
- /*
- * Client and Server side protocols are each driven though this
- * call, which processes a single message and drives the appropriate
- * side of the protocol state machine (depending on the subclass).
- */
- abstract void processMessage(byte messageType, int messageLen)
- throws IOException;
-
- /*
- * Most alerts in the protocol relate to handshaking problems.
- * Alerts are detected as the connection reads data.
- */
- abstract void handshakeAlert(byte description) throws SSLProtocolException;
-
- /*
- * Sends a change cipher spec message and updates the write side
- * cipher state so that future messages use the just-negotiated spec.
- */
- void sendChangeCipherSpec(Finished mesg, boolean lastMessage)
- throws IOException {
-
- output.flush(); // i.e. handshake data
-
- /*
- * The write cipher state is protected by the connection write lock
- * so we must grab it while making the change. We also
- * make sure no writes occur between sending the ChangeCipherSpec
- * message, installing the new cipher state, and sending the
- * Finished message.
- *
- * We already hold SSLEngine/SSLSocket "this" by virtue
- * of this being called from the readRecord code.
- */
- OutputRecord r;
- if (conn != null) {
- r = new OutputRecord(Record.ct_change_cipher_spec);
- } else {
- r = new EngineOutputRecord(Record.ct_change_cipher_spec, engine);
- }
-
- r.setVersion(protocolVersion);
- r.write(1); // single byte of data
-
- if (conn != null) {
- conn.writeLock.lock();
- try {
- conn.writeRecord(r);
- conn.changeWriteCiphers();
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
- mesg.write(output);
- output.flush();
- } finally {
- conn.writeLock.unlock();
- }
- } else {
- synchronized (engine.writeLock) {
- engine.writeRecord((EngineOutputRecord)r);
- engine.changeWriteCiphers();
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
- mesg.write(output);
-
- if (lastMessage) {
- output.setFinishedMsg();
- }
- output.flush();
- }
- }
- }
-
- /*
- * Single access point to key calculation logic. Given the
- * pre-master secret and the nonces from client and server,
- * produce all the keying material to be used.
- */
- void calculateKeys(SecretKey preMasterSecret, ProtocolVersion version) {
- SecretKey master = calculateMasterSecret(preMasterSecret, version);
- session.setMasterSecret(master);
- calculateConnectionKeys(master);
- }
-
-
- /*
- * Calculate the master secret from its various components. This is
- * used for key exchange by all cipher suites.
- *
- * The master secret is the catenation of three MD5 hashes, each
- * consisting of the pre-master secret and a SHA1 hash. Those three
- * SHA1 hashes are of (different) constant strings, the pre-master
- * secret, and the nonces provided by the client and the server.
- */
- private SecretKey calculateMasterSecret(SecretKey preMasterSecret,
- ProtocolVersion requestedVersion) {
-
- if (debug != null && Debug.isOn("keygen")) {
- HexDumpEncoder dump = new HexDumpEncoder();
-
- System.out.println("SESSION KEYGEN:");
-
- System.out.println("PreMaster Secret:");
- printHex(dump, preMasterSecret.getEncoded());
-
- // Nonces are dumped with connection keygen, no
- // benefit to doing it twice
- }
-
- // What algs/params do we need to use?
- String masterAlg;
- PRF prf;
-
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- masterAlg = "SunTls12MasterSecret";
- prf = cipherSuite.prfAlg;
- } else {
- masterAlg = "SunTlsMasterSecret";
- prf = P_NONE;
- }
-
- String prfHashAlg = prf.getPRFHashAlg();
- int prfHashLength = prf.getPRFHashLength();
- int prfBlockSize = prf.getPRFBlockSize();
-
- TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec(
- preMasterSecret, protocolVersion.major, protocolVersion.minor,
- clnt_random.random_bytes, svr_random.random_bytes,
- prfHashAlg, prfHashLength, prfBlockSize);
-
- SecretKey masterSecret;
- try {
- KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg);
- kg.init(spec);
- masterSecret = kg.generateKey();
- } catch (GeneralSecurityException e) {
- // For RSA premaster secrets, do not signal a protocol error
- // due to the Bleichenbacher attack. See comments further down.
- if (!preMasterSecret.getAlgorithm().equals(
- "TlsRsaPremasterSecret")) {
- throw new ProviderException(e);
- }
-
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println("RSA master secret generation error:");
- e.printStackTrace(System.out);
- }
-
- if (requestedVersion != null) {
- preMasterSecret =
- RSAClientKeyExchange.generateDummySecret(requestedVersion);
- } else {
- preMasterSecret =
- RSAClientKeyExchange.generateDummySecret(protocolVersion);
- }
-
- // recursive call with new premaster secret
- return calculateMasterSecret(preMasterSecret, null);
- }
-
- // if no version check requested (client side handshake), or version
- // information is not available (not an RSA premaster secret),
- // return master secret immediately.
- if ((requestedVersion == null) ||
- !(masterSecret instanceof TlsMasterSecret)) {
- return masterSecret;
- }
-
- // we have checked the ClientKeyExchange message when reading TLS
- // record, the following check is necessary to ensure that
- // JCE provider does not ignore the checking, or the previous
- // checking process bypassed the premaster secret version checking.
- TlsMasterSecret tlsKey = (TlsMasterSecret)masterSecret;
- int major = tlsKey.getMajorVersion();
- int minor = tlsKey.getMinorVersion();
- if ((major < 0) || (minor < 0)) {
- return masterSecret;
- }
-
- // check if the premaster secret version is ok
- // the specification says that it must be the maximum version supported
- // by the client from its ClientHello message. However, many
- // implementations send the negotiated version, so accept both
- // for SSL v3.0 and TLS v1.0.
- // NOTE that we may be comparing two unsupported version numbers, which
- // is why we cannot use object reference equality in this special case.
- ProtocolVersion premasterVersion =
- ProtocolVersion.valueOf(major, minor);
- boolean versionMismatch = (premasterVersion.v != requestedVersion.v);
-
- /*
- * we never checked the client_version in server side
- * for TLS v1.0 and SSL v3.0. For compatibility, we
- * maintain this behavior.
- */
- if (versionMismatch && requestedVersion.v <= ProtocolVersion.TLS10.v) {
- versionMismatch = (premasterVersion.v != protocolVersion.v);
- }
-
- if (versionMismatch == false) {
- // check passed, return key
- return masterSecret;
- }
-
- // Due to the Bleichenbacher attack, do not signal a protocol error.
- // Generate a random premaster secret and continue with the handshake,
- // which will fail when verifying the finished messages.
- // For more information, see comments in PreMasterSecret.
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println("RSA PreMasterSecret version error: expected"
- + protocolVersion + " or " + requestedVersion + ", decrypted: "
- + premasterVersion);
- }
- preMasterSecret =
- RSAClientKeyExchange.generateDummySecret(requestedVersion);
-
- // recursive call with new premaster secret
- return calculateMasterSecret(preMasterSecret, null);
- }
-
- /*
- * Calculate the keys needed for this connection, once the session's
- * master secret has been calculated. Uses the master key and nonces;
- * the amount of keying material generated is a function of the cipher
- * suite that's been negotiated.
- *
- * This gets called both on the "full handshake" (where we exchanged
- * a premaster secret and started a new session) as well as on the
- * "fast handshake" (where we just resumed a pre-existing session).
- */
- void calculateConnectionKeys(SecretKey masterKey) {
- /*
- * For both the read and write sides of the protocol, we use the
- * master to generate MAC secrets and cipher keying material. Block
- * ciphers need initialization vectors, which we also generate.
- *
- * First we figure out how much keying material is needed.
- */
- int hashSize = cipherSuite.macAlg.size;
- boolean is_exportable = cipherSuite.exportable;
- BulkCipher cipher = cipherSuite.cipher;
- int expandedKeySize = is_exportable ? cipher.expandedKeySize : 0;
-
- // Which algs/params do we need to use?
- String keyMaterialAlg;
- PRF prf;
-
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- keyMaterialAlg = "SunTls12KeyMaterial";
- prf = cipherSuite.prfAlg;
- } else {
- keyMaterialAlg = "SunTlsKeyMaterial";
- prf = P_NONE;
- }
-
- String prfHashAlg = prf.getPRFHashAlg();
- int prfHashLength = prf.getPRFHashLength();
- int prfBlockSize = prf.getPRFBlockSize();
-
- TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec(
- masterKey, protocolVersion.major, protocolVersion.minor,
- clnt_random.random_bytes, svr_random.random_bytes,
- cipher.algorithm, cipher.keySize, expandedKeySize,
- cipher.ivSize, hashSize,
- prfHashAlg, prfHashLength, prfBlockSize);
-
- try {
- KeyGenerator kg = JsseJce.getKeyGenerator(keyMaterialAlg);
- kg.init(spec);
- TlsKeyMaterialSpec keySpec = (TlsKeyMaterialSpec)kg.generateKey();
-
- clntWriteKey = keySpec.getClientCipherKey();
- svrWriteKey = keySpec.getServerCipherKey();
-
- // Return null if IVs are not supposed to be generated.
- // e.g. TLS 1.1+.
- clntWriteIV = keySpec.getClientIv();
- svrWriteIV = keySpec.getServerIv();
-
- clntMacSecret = keySpec.getClientMacKey();
- svrMacSecret = keySpec.getServerMacKey();
- } catch (GeneralSecurityException e) {
- throw new ProviderException(e);
- }
-
- //
- // Dump the connection keys as they're generated.
- //
- if (debug != null && Debug.isOn("keygen")) {
- synchronized (System.out) {
- HexDumpEncoder dump = new HexDumpEncoder();
-
- System.out.println("CONNECTION KEYGEN:");
-
- // Inputs:
- System.out.println("Client Nonce:");
- printHex(dump, clnt_random.random_bytes);
- System.out.println("Server Nonce:");
- printHex(dump, svr_random.random_bytes);
- System.out.println("Master Secret:");
- printHex(dump, masterKey.getEncoded());
-
- // Outputs:
- System.out.println("Client MAC write Secret:");
- printHex(dump, clntMacSecret.getEncoded());
- System.out.println("Server MAC write Secret:");
- printHex(dump, svrMacSecret.getEncoded());
-
- if (clntWriteKey != null) {
- System.out.println("Client write key:");
- printHex(dump, clntWriteKey.getEncoded());
- System.out.println("Server write key:");
- printHex(dump, svrWriteKey.getEncoded());
- } else {
- System.out.println("... no encryption keys used");
- }
-
- if (clntWriteIV != null) {
- System.out.println("Client write IV:");
- printHex(dump, clntWriteIV.getIV());
- System.out.println("Server write IV:");
- printHex(dump, svrWriteIV.getIV());
- } else {
- if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
- System.out.println(
- "... no IV derived for this protocol");
- } else {
- System.out.println("... no IV used for this cipher");
- }
- }
- System.out.flush();
- }
- }
- }
-
- private static void printHex(HexDumpEncoder dump, byte[] bytes) {
- if (bytes == null) {
- System.out.println("(key bytes not available)");
- } else {
- try {
- dump.encodeBuffer(bytes, System.out);
- } catch (IOException e) {
- // just for debugging, ignore this
- }
- }
- }
-
- /**
- * Throw an SSLException with the specified message and cause.
- * Shorthand until a new SSLException constructor is added.
- * This method never returns.
- */
- static void throwSSLException(String msg, Throwable cause)
- throws SSLException {
- SSLException e = new SSLException(msg);
- e.initCause(cause);
- throw e;
- }
-
-
- /*
- * Implement a simple task delegator.
- *
- * We are currently implementing this as a single delegator, may
- * try for parallel tasks later. Client Authentication could
- * benefit from this, where ClientKeyExchange/CertificateVerify
- * could be carried out in parallel.
- */
- class DelegatedTask<E> implements Runnable {
-
- private PrivilegedExceptionAction<E> pea;
-
- DelegatedTask(PrivilegedExceptionAction<E> pea) {
- this.pea = pea;
- }
-
- public void run() {
- synchronized (engine) {
- try {
- AccessController.doPrivileged(pea, engine.getAcc());
- } catch (PrivilegedActionException pae) {
- thrown = pae.getException();
- } catch (RuntimeException rte) {
- thrown = rte;
- }
- delegatedTask = null;
- taskDelegated = false;
- }
- }
- }
-
- private <T> void delegateTask(PrivilegedExceptionAction<T> pea) {
- delegatedTask = new DelegatedTask<T>(pea);
- taskDelegated = false;
- thrown = null;
- }
-
- DelegatedTask getTask() {
- if (!taskDelegated) {
- taskDelegated = true;
- return delegatedTask;
- } else {
- return null;
- }
- }
-
- /*
- * See if there are any tasks which need to be delegated
- *
- * Locked by SSLEngine.this.
- */
- boolean taskOutstanding() {
- return (delegatedTask != null);
- }
-
- /*
- * The previous caller failed for some reason, report back the
- * Exception. We won't worry about Error's.
- *
- * Locked by SSLEngine.this.
- */
- void checkThrown() throws SSLException {
- synchronized (thrownLock) {
- if (thrown != null) {
-
- String msg = thrown.getMessage();
-
- if (msg == null) {
- msg = "Delegated task threw Exception/Error";
- }
-
- /*
- * See what the underlying type of exception is. We should
- * throw the same thing. Chain thrown to the new exception.
- */
- Exception e = thrown;
- thrown = null;
-
- if (e instanceof RuntimeException) {
- throw (RuntimeException)
- new RuntimeException(msg).initCause(e);
- } else if (e instanceof SSLHandshakeException) {
- throw (SSLHandshakeException)
- new SSLHandshakeException(msg).initCause(e);
- } else if (e instanceof SSLKeyException) {
- throw (SSLKeyException)
- new SSLKeyException(msg).initCause(e);
- } else if (e instanceof SSLPeerUnverifiedException) {
- throw (SSLPeerUnverifiedException)
- new SSLPeerUnverifiedException(msg).initCause(e);
- } else if (e instanceof SSLProtocolException) {
- throw (SSLProtocolException)
- new SSLProtocolException(msg).initCause(e);
- } else {
- /*
- * If it's SSLException or any other Exception,
- * we'll wrap it in an SSLException.
- */
- throw (SSLException)
- new SSLException(msg).initCause(e);
- }
- }
- }
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/HelloExtensions.java b/ojluni/src/main/java/sun/security/ssl/HelloExtensions.java
deleted file mode 100755
index 9db6927..0000000
--- a/ojluni/src/main/java/sun/security/ssl/HelloExtensions.java
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.*;
-
-import java.security.spec.ECParameterSpec;
-
-import javax.net.ssl.SSLProtocolException;
-
-/**
- * This file contains all the classes relevant to TLS Extensions for the
- * ClientHello and ServerHello messages. The extension mechanism and
- * several extensions are defined in RFC 3546. Additional extensions are
- * defined in the ECC RFC 4492.
- *
- * Currently, only the two ECC extensions are fully supported.
- *
- * The classes contained in this file are:
- * . HelloExtensions: a List of extensions as used in the client hello
- * and server hello messages.
- * . ExtensionType: an enum style class for the extension type
- * . HelloExtension: abstract base class for all extensions. All subclasses
- * must be immutable.
- *
- * . UnknownExtension: used to represent all parsed extensions that we do not
- * explicitly support.
- * . ServerNameExtension: the server_name extension.
- * . SignatureAlgorithmsExtension: the signature_algorithms extension.
- * . SupportedEllipticCurvesExtension: the ECC supported curves extension.
- * . SupportedEllipticPointFormatsExtension: the ECC supported point formats
- * (compressed/uncompressed) extension.
- *
- * @since 1.6
- * @author Andreas Sterbenz
- */
-final class HelloExtensions {
-
- private List<HelloExtension> extensions;
- private int encodedLength;
-
- HelloExtensions() {
- extensions = Collections.emptyList();
- }
-
- HelloExtensions(HandshakeInStream s) throws IOException {
- int len = s.getInt16();
- extensions = new ArrayList<HelloExtension>();
- encodedLength = len + 2;
- while (len > 0) {
- int type = s.getInt16();
- int extlen = s.getInt16();
- ExtensionType extType = ExtensionType.get(type);
- HelloExtension extension;
- if (extType == ExtensionType.EXT_SERVER_NAME) {
- extension = new ServerNameExtension(s, extlen);
- } else if (extType == ExtensionType.EXT_SIGNATURE_ALGORITHMS) {
- extension = new SignatureAlgorithmsExtension(s, extlen);
- } else if (extType == ExtensionType.EXT_ELLIPTIC_CURVES) {
- extension = new SupportedEllipticCurvesExtension(s, extlen);
- } else if (extType == ExtensionType.EXT_EC_POINT_FORMATS) {
- extension =
- new SupportedEllipticPointFormatsExtension(s, extlen);
- } else if (extType == ExtensionType.EXT_RENEGOTIATION_INFO) {
- extension = new RenegotiationInfoExtension(s, extlen);
- } else {
- extension = new UnknownExtension(s, extlen, extType);
- }
- extensions.add(extension);
- len -= extlen + 4;
- }
- if (len != 0) {
- throw new SSLProtocolException(
- "Error parsing extensions: extra data");
- }
- }
-
- // Return the List of extensions. Must not be modified by the caller.
- List<HelloExtension> list() {
- return extensions;
- }
-
- void add(HelloExtension ext) {
- if (extensions.isEmpty()) {
- extensions = new ArrayList<HelloExtension>();
- }
- extensions.add(ext);
- encodedLength = -1;
- }
-
- HelloExtension get(ExtensionType type) {
- for (HelloExtension ext : extensions) {
- if (ext.type == type) {
- return ext;
- }
- }
- return null;
- }
-
- int length() {
- if (encodedLength >= 0) {
- return encodedLength;
- }
- if (extensions.isEmpty()) {
- encodedLength = 0;
- } else {
- encodedLength = 2;
- for (HelloExtension ext : extensions) {
- encodedLength += ext.length();
- }
- }
- return encodedLength;
- }
-
- void send(HandshakeOutStream s) throws IOException {
- int length = length();
- if (length == 0) {
- return;
- }
- s.putInt16(length - 2);
- for (HelloExtension ext : extensions) {
- ext.send(s);
- }
- }
-
- void print(PrintStream s) throws IOException {
- for (HelloExtension ext : extensions) {
- s.println(ext.toString());
- }
- }
-}
-
-final class ExtensionType {
-
- final int id;
- final String name;
-
- private ExtensionType(int id, String name) {
- this.id = id;
- this.name = name;
- }
-
- public String toString() {
- return name;
- }
-
- static List<ExtensionType> knownExtensions = new ArrayList<>(9);
-
- static ExtensionType get(int id) {
- for (ExtensionType ext : knownExtensions) {
- if (ext.id == id) {
- return ext;
- }
- }
- return new ExtensionType(id, "type_" + id);
- }
-
- private static ExtensionType e(int id, String name) {
- ExtensionType ext = new ExtensionType(id, name);
- knownExtensions.add(ext);
- return ext;
- }
-
- // extensions defined in RFC 3546
- final static ExtensionType EXT_SERVER_NAME =
- e(0x0000, "server_name"); // IANA registry value: 0
- final static ExtensionType EXT_MAX_FRAGMENT_LENGTH =
- e(0x0001, "max_fragment_length"); // IANA registry value: 1
- final static ExtensionType EXT_CLIENT_CERTIFICATE_URL =
- e(0x0002, "client_certificate_url"); // IANA registry value: 2
- final static ExtensionType EXT_TRUSTED_CA_KEYS =
- e(0x0003, "trusted_ca_keys"); // IANA registry value: 3
- final static ExtensionType EXT_TRUNCATED_HMAC =
- e(0x0004, "truncated_hmac"); // IANA registry value: 4
- final static ExtensionType EXT_STATUS_REQUEST =
- e(0x0005, "status_request"); // IANA registry value: 5
-
- // extensions defined in RFC 4681
- final static ExtensionType EXT_USER_MAPPING =
- e(0x0006, "user_mapping"); // IANA registry value: 6
-
- // extensions defined in RFC 5081
- final static ExtensionType EXT_CERT_TYPE =
- e(0x0009, "cert_type"); // IANA registry value: 9
-
- // extensions defined in RFC 4492 (ECC)
- final static ExtensionType EXT_ELLIPTIC_CURVES =
- e(0x000A, "elliptic_curves"); // IANA registry value: 10
- final static ExtensionType EXT_EC_POINT_FORMATS =
- e(0x000B, "ec_point_formats"); // IANA registry value: 11
-
- // extensions defined in RFC 5054
- final static ExtensionType EXT_SRP =
- e(0x000C, "srp"); // IANA registry value: 12
-
- // extensions defined in RFC 5246
- final static ExtensionType EXT_SIGNATURE_ALGORITHMS =
- e(0x000D, "signature_algorithms"); // IANA registry value: 13
-
- // extensions defined in RFC 5746
- final static ExtensionType EXT_RENEGOTIATION_INFO =
- e(0xff01, "renegotiation_info"); // IANA registry value: 65281
-}
-
-abstract class HelloExtension {
-
- final ExtensionType type;
-
- HelloExtension(ExtensionType type) {
- this.type = type;
- }
-
- // Length of the encoded extension, including the type and length fields
- abstract int length();
-
- abstract void send(HandshakeOutStream s) throws IOException;
-
- public abstract String toString();
-
-}
-
-final class UnknownExtension extends HelloExtension {
-
- private final byte[] data;
-
- UnknownExtension(HandshakeInStream s, int len, ExtensionType type)
- throws IOException {
- super(type);
- data = new byte[len];
- // s.read() does not handle 0-length arrays.
- if (len != 0) {
- s.read(data);
- }
- }
-
- int length() {
- return 4 + data.length;
- }
-
- void send(HandshakeOutStream s) throws IOException {
- s.putInt16(type.id);
- s.putBytes16(data);
- }
-
- public String toString() {
- return "Unsupported extension " + type + ", data: " +
- Debug.toString(data);
- }
-}
-
-/*
- * [RFC4366] To facilitate secure connections to servers that host multiple
- * 'virtual' servers at a single underlying network address, clients MAY
- * include an extension of type "server_name" in the (extended) client hello.
- * The "extension_data" field of this extension SHALL contain "ServerNameList"
- * where:
- *
- * struct {
- * NameType name_type;
- * select (name_type) {
- * case host_name: HostName;
- * } name;
- * } ServerName;
- *
- * enum {
- * host_name(0), (255)
- * } NameType;
- *
- * opaque HostName<1..2^16-1>;
- *
- * struct {
- * ServerName server_name_list<1..2^16-1>
- * } ServerNameList;
- */
-final class ServerNameExtension extends HelloExtension {
-
- final static int NAME_HOST_NAME = 0;
-
- private List<ServerName> names;
- private int listLength; // ServerNameList length
-
- ServerNameExtension(List<String> hostnames) throws IOException {
- super(ExtensionType.EXT_SERVER_NAME);
-
- listLength = 0;
- names = new ArrayList<ServerName>(hostnames.size());
- for (String hostname : hostnames) {
- if (hostname != null && hostname.length() != 0) {
- // we only support DNS hostname now.
- ServerName serverName =
- new ServerName(NAME_HOST_NAME, hostname);
- names.add(serverName);
- listLength += serverName.length;
- }
- }
-
- // As we only support DNS hostname now, the hostname list must
- // not contain more than one hostname
- if (names.size() > 1) {
- throw new SSLProtocolException(
- "The ServerNameList MUST NOT contain more than " +
- "one name of the same name_type");
- }
-
- // We only need to add "server_name" extension in ClientHello unless
- // we support SNI in server side in the future. It is possible that
- // the SNI is empty in ServerHello. As we don't support SNI in
- // ServerHello now, we will throw exception for empty list for now.
- if (listLength == 0) {
- throw new SSLProtocolException(
- "The ServerNameList cannot be empty");
- }
- }
-
- ServerNameExtension(HandshakeInStream s, int len)
- throws IOException {
- super(ExtensionType.EXT_SERVER_NAME);
-
- int remains = len;
- if (len >= 2) { // "server_name" extension in ClientHello
- listLength = s.getInt16(); // ServerNameList length
- if (listLength == 0 || listLength + 2 != len) {
- throw new SSLProtocolException(
- "Invalid " + type + " extension");
- }
-
- remains -= 2;
- names = new ArrayList<ServerName>();
- while (remains > 0) {
- ServerName name = new ServerName(s);
- names.add(name);
- remains -= name.length;
-
- // we may need to check the duplicated ServerName type
- }
- } else if (len == 0) { // "server_name" extension in ServerHello
- listLength = 0;
- names = Collections.<ServerName>emptyList();
- }
-
- if (remains != 0) {
- throw new SSLProtocolException("Invalid server_name extension");
- }
- }
-
- static class ServerName {
- final int length;
- final int type;
- final byte[] data;
- final String hostname;
-
- ServerName(int type, String hostname) throws IOException {
- this.type = type; // NameType
- this.hostname = hostname;
- this.data = hostname.getBytes("UTF8"); // HostName
- this.length = data.length + 3; // NameType: 1 byte
- // HostName length: 2 bytes
- }
-
- ServerName(HandshakeInStream s) throws IOException {
- type = s.getInt8(); // NameType
- data = s.getBytes16(); // HostName (length read in getBytes16)
- length = data.length + 3; // NameType: 1 byte
- // HostName length: 2 bytes
- if (type == NAME_HOST_NAME) {
- hostname = new String(data, "UTF8");
- } else {
- hostname = null;
- }
- }
-
- public String toString() {
- if (type == NAME_HOST_NAME) {
- return "host_name: " + hostname;
- } else {
- return "unknown-" + type + ": " + Debug.toString(data);
- }
- }
- }
-
- int length() {
- return listLength == 0 ? 4 : 6 + listLength;
- }
-
- void send(HandshakeOutStream s) throws IOException {
- s.putInt16(type.id);
- s.putInt16(listLength + 2);
- if (listLength != 0) {
- s.putInt16(listLength);
-
- for (ServerName name : names) {
- s.putInt8(name.type); // NameType
- s.putBytes16(name.data); // HostName
- }
- }
- }
-
- public String toString() {
- StringBuffer buffer = new StringBuffer();
- for (ServerName name : names) {
- buffer.append("[" + name + "]");
- }
-
- return "Extension " + type + ", server_name: " + buffer;
- }
-}
-
-final class SupportedEllipticCurvesExtension extends HelloExtension {
-
- // the extension value to send in the ClientHello message
- static final SupportedEllipticCurvesExtension DEFAULT;
-
- private static final boolean fips;
-
- static {
- int[] ids;
- fips = SunJSSE.isFIPS();
- if (fips == false) {
- ids = new int[] {
- // NIST curves first
- // prefer NIST P-256, rest in order of increasing key length
- 23, 1, 3, 19, 21, 6, 7, 9, 10, 24, 11, 12, 25, 13, 14,
- // non-NIST curves
- 15, 16, 17, 2, 18, 4, 5, 20, 8, 22,
- };
- } else {
- ids = new int[] {
- // same as above, but allow only NIST curves in FIPS mode
- 23, 1, 3, 19, 21, 6, 7, 9, 10, 24, 11, 12, 25, 13, 14,
- };
- }
- DEFAULT = new SupportedEllipticCurvesExtension(ids);
- }
-
- private final int[] curveIds;
-
- private SupportedEllipticCurvesExtension(int[] curveIds) {
- super(ExtensionType.EXT_ELLIPTIC_CURVES);
- this.curveIds = curveIds;
- }
-
- SupportedEllipticCurvesExtension(HandshakeInStream s, int len)
- throws IOException {
- super(ExtensionType.EXT_ELLIPTIC_CURVES);
- int k = s.getInt16();
- if (((len & 1) != 0) || (k + 2 != len)) {
- throw new SSLProtocolException("Invalid " + type + " extension");
- }
- curveIds = new int[k >> 1];
- for (int i = 0; i < curveIds.length; i++) {
- curveIds[i] = s.getInt16();
- }
- }
-
- boolean contains(int index) {
- for (int curveId : curveIds) {
- if (index == curveId) {
- return true;
- }
- }
- return false;
- }
-
- // Return a reference to the internal curveIds array.
- // The caller must NOT modify the contents.
- int[] curveIds() {
- return curveIds;
- }
-
- int length() {
- return 6 + (curveIds.length << 1);
- }
-
- void send(HandshakeOutStream s) throws IOException {
- s.putInt16(type.id);
- int k = curveIds.length << 1;
- s.putInt16(k + 2);
- s.putInt16(k);
- for (int curveId : curveIds) {
- s.putInt16(curveId);
- }
- }
-
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("Extension " + type + ", curve names: {");
- boolean first = true;
- for (int curveId : curveIds) {
- if (first) {
- first = false;
- } else {
- sb.append(", ");
- }
- // first check if it is a known named curve, then try other cases.
- String oid = getCurveOid(curveId);
- if (oid != null) {
- ECParameterSpec spec = JsseJce.getECParameterSpec(oid);
- // this toString() output will look nice for the current
- // implementation of the ECParameterSpec class in the Sun
- // provider, but may not look good for other implementations.
- if (spec != null) {
- sb.append(spec.toString().split(" ")[0]);
- } else {
- sb.append(oid);
- }
- } else if (curveId == ARBITRARY_PRIME) {
- sb.append("arbitrary_explicit_prime_curves");
- } else if (curveId == ARBITRARY_CHAR2) {
- sb.append("arbitrary_explicit_char2_curves");
- } else {
- sb.append("unknown curve " + curveId);
- }
- }
- sb.append("}");
- return sb.toString();
- }
-
- // Test whether we support the curve with the given index.
- static boolean isSupported(int index) {
- if ((index <= 0) || (index >= NAMED_CURVE_OID_TABLE.length)) {
- return false;
- }
- if (fips == false) {
- // in non-FIPS mode, we support all valid indices
- return true;
- }
- return DEFAULT.contains(index);
- }
-
- static int getCurveIndex(ECParameterSpec params) {
- String oid = JsseJce.getNamedCurveOid(params);
- if (oid == null) {
- return -1;
- }
- Integer n = curveIndices.get(oid);
- return (n == null) ? -1 : n;
- }
-
- static String getCurveOid(int index) {
- if ((index > 0) && (index < NAMED_CURVE_OID_TABLE.length)) {
- return NAMED_CURVE_OID_TABLE[index];
- }
- return null;
- }
-
- private final static int ARBITRARY_PRIME = 0xff01;
- private final static int ARBITRARY_CHAR2 = 0xff02;
-
- // See sun.security.ec.NamedCurve for the OIDs
- private final static String[] NAMED_CURVE_OID_TABLE = new String[] {
- null, // (0) unused
- "1.3.132.0.1", // (1) sect163k1, NIST K-163
- "1.3.132.0.2", // (2) sect163r1
- "1.3.132.0.15", // (3) sect163r2, NIST B-163
- "1.3.132.0.24", // (4) sect193r1
- "1.3.132.0.25", // (5) sect193r2
- "1.3.132.0.26", // (6) sect233k1, NIST K-233
- "1.3.132.0.27", // (7) sect233r1, NIST B-233
- "1.3.132.0.3", // (8) sect239k1
- "1.3.132.0.16", // (9) sect283k1, NIST K-283
- "1.3.132.0.17", // (10) sect283r1, NIST B-283
- "1.3.132.0.36", // (11) sect409k1, NIST K-409
- "1.3.132.0.37", // (12) sect409r1, NIST B-409
- "1.3.132.0.38", // (13) sect571k1, NIST K-571
- "1.3.132.0.39", // (14) sect571r1, NIST B-571
- "1.3.132.0.9", // (15) secp160k1
- "1.3.132.0.8", // (16) secp160r1
- "1.3.132.0.30", // (17) secp160r2
- "1.3.132.0.31", // (18) secp192k1
- "1.2.840.10045.3.1.1", // (19) secp192r1, NIST P-192
- "1.3.132.0.32", // (20) secp224k1
- "1.3.132.0.33", // (21) secp224r1, NIST P-224
- "1.3.132.0.10", // (22) secp256k1
- "1.2.840.10045.3.1.7", // (23) secp256r1, NIST P-256
- "1.3.132.0.34", // (24) secp384r1, NIST P-384
- "1.3.132.0.35", // (25) secp521r1, NIST P-521
- };
-
- private final static Map<String,Integer> curveIndices;
-
- static {
- curveIndices = new HashMap<String,Integer>();
- for (int i = 1; i < NAMED_CURVE_OID_TABLE.length; i++) {
- curveIndices.put(NAMED_CURVE_OID_TABLE[i], i);
- }
- }
-
-}
-
-final class SupportedEllipticPointFormatsExtension extends HelloExtension {
-
- final static int FMT_UNCOMPRESSED = 0;
- final static int FMT_ANSIX962_COMPRESSED_PRIME = 1;
- final static int FMT_ANSIX962_COMPRESSED_CHAR2 = 2;
-
- static final HelloExtension DEFAULT =
- new SupportedEllipticPointFormatsExtension(
- new byte[] {FMT_UNCOMPRESSED});
-
- private final byte[] formats;
-
- private SupportedEllipticPointFormatsExtension(byte[] formats) {
- super(ExtensionType.EXT_EC_POINT_FORMATS);
- this.formats = formats;
- }
-
- SupportedEllipticPointFormatsExtension(HandshakeInStream s, int len)
- throws IOException {
- super(ExtensionType.EXT_EC_POINT_FORMATS);
- formats = s.getBytes8();
- // RFC 4492 says uncompressed points must always be supported.
- // Check just to make sure.
- boolean uncompressed = false;
- for (int format : formats) {
- if (format == FMT_UNCOMPRESSED) {
- uncompressed = true;
- break;
- }
- }
- if (uncompressed == false) {
- throw new SSLProtocolException
- ("Peer does not support uncompressed points");
- }
- }
-
- int length() {
- return 5 + formats.length;
- }
-
- void send(HandshakeOutStream s) throws IOException {
- s.putInt16(type.id);
- s.putInt16(formats.length + 1);
- s.putBytes8(formats);
- }
-
- private static String toString(byte format) {
- int f = format & 0xff;
- switch (f) {
- case FMT_UNCOMPRESSED:
- return "uncompressed";
- case FMT_ANSIX962_COMPRESSED_PRIME:
- return "ansiX962_compressed_prime";
- case FMT_ANSIX962_COMPRESSED_CHAR2:
- return "ansiX962_compressed_char2";
- default:
- return "unknown-" + f;
- }
- }
-
- public String toString() {
- List<String> list = new ArrayList<>();
- for (byte format : formats) {
- list.add(toString(format));
- }
- return "Extension " + type + ", formats: " + list;
- }
-}
-
-/*
- * For secure renegotiation, RFC5746 defines a new TLS extension,
- * "renegotiation_info" (with extension type 0xff01), which contains a
- * cryptographic binding to the enclosing TLS connection (if any) for
- * which the renegotiation is being performed. The "extension data"
- * field of this extension contains a "RenegotiationInfo" structure:
- *
- * struct {
- * opaque renegotiated_connection<0..255>;
- * } RenegotiationInfo;
- */
-final class RenegotiationInfoExtension extends HelloExtension {
- private final byte[] renegotiated_connection;
-
- RenegotiationInfoExtension(byte[] clientVerifyData,
- byte[] serverVerifyData) {
- super(ExtensionType.EXT_RENEGOTIATION_INFO);
-
- if (clientVerifyData.length != 0) {
- renegotiated_connection =
- new byte[clientVerifyData.length + serverVerifyData.length];
- System.arraycopy(clientVerifyData, 0, renegotiated_connection,
- 0, clientVerifyData.length);
-
- if (serverVerifyData.length != 0) {
- System.arraycopy(serverVerifyData, 0, renegotiated_connection,
- clientVerifyData.length, serverVerifyData.length);
- }
- } else {
- // ignore both the client and server verify data.
- renegotiated_connection = new byte[0];
- }
- }
-
- RenegotiationInfoExtension(HandshakeInStream s, int len)
- throws IOException {
- super(ExtensionType.EXT_RENEGOTIATION_INFO);
-
- // check the extension length
- if (len < 1) {
- throw new SSLProtocolException("Invalid " + type + " extension");
- }
-
- int renegoInfoDataLen = s.getInt8();
- if (renegoInfoDataLen + 1 != len) { // + 1 = the byte we just read
- throw new SSLProtocolException("Invalid " + type + " extension");
- }
-
- renegotiated_connection = new byte[renegoInfoDataLen];
- if (renegoInfoDataLen != 0) {
- s.read(renegotiated_connection, 0, renegoInfoDataLen);
- }
- }
-
-
- // Length of the encoded extension, including the type and length fields
- int length() {
- return 5 + renegotiated_connection.length;
- }
-
- void send(HandshakeOutStream s) throws IOException {
- s.putInt16(type.id);
- s.putInt16(renegotiated_connection.length + 1);
- s.putBytes8(renegotiated_connection);
- }
-
- boolean isEmpty() {
- return renegotiated_connection.length == 0;
- }
-
- byte[] getRenegotiatedConnection() {
- return renegotiated_connection;
- }
-
- public String toString() {
- return "Extension " + type + ", renegotiated_connection: " +
- (renegotiated_connection.length == 0 ? "<empty>" :
- Debug.toString(renegotiated_connection));
- }
-
-}
-
-/*
- * [RFC5246] The client uses the "signature_algorithms" extension to
- * indicate to the server which signature/hash algorithm pairs may be
- * used in digital signatures. The "extension_data" field of this
- * extension contains a "supported_signature_algorithms" value.
- *
- * enum {
- * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
- * sha512(6), (255)
- * } HashAlgorithm;
- *
- * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
- * SignatureAlgorithm;
- *
- * struct {
- * HashAlgorithm hash;
- * SignatureAlgorithm signature;
- * } SignatureAndHashAlgorithm;
- *
- * SignatureAndHashAlgorithm
- * supported_signature_algorithms<2..2^16-2>;
- */
-final class SignatureAlgorithmsExtension extends HelloExtension {
-
- private Collection<SignatureAndHashAlgorithm> algorithms;
- private int algorithmsLen; // length of supported_signature_algorithms
-
- SignatureAlgorithmsExtension(
- Collection<SignatureAndHashAlgorithm> signAlgs) {
-
- super(ExtensionType.EXT_SIGNATURE_ALGORITHMS);
-
- algorithms = new ArrayList<SignatureAndHashAlgorithm>(signAlgs);
- algorithmsLen =
- SignatureAndHashAlgorithm.sizeInRecord() * algorithms.size();
- }
-
- SignatureAlgorithmsExtension(HandshakeInStream s, int len)
- throws IOException {
- super(ExtensionType.EXT_SIGNATURE_ALGORITHMS);
-
- algorithmsLen = s.getInt16();
- if (algorithmsLen == 0 || algorithmsLen + 2 != len) {
- throw new SSLProtocolException("Invalid " + type + " extension");
- }
-
- algorithms = new ArrayList<SignatureAndHashAlgorithm>();
- int remains = algorithmsLen;
- int sequence = 0;
- while (remains > 1) { // needs at least two bytes
- int hash = s.getInt8(); // hash algorithm
- int signature = s.getInt8(); // signature algorithm
-
- SignatureAndHashAlgorithm algorithm =
- SignatureAndHashAlgorithm.valueOf(hash, signature, ++sequence);
- algorithms.add(algorithm);
- remains -= 2; // one byte for hash, one byte for signature
- }
-
- if (remains != 0) {
- throw new SSLProtocolException("Invalid server_name extension");
- }
- }
-
- Collection<SignatureAndHashAlgorithm> getSignAlgorithms() {
- return algorithms;
- }
-
- @Override
- int length() {
- return 6 + algorithmsLen;
- }
-
- @Override
- void send(HandshakeOutStream s) throws IOException {
- s.putInt16(type.id);
- s.putInt16(algorithmsLen + 2);
- s.putInt16(algorithmsLen);
-
- for (SignatureAndHashAlgorithm algorithm : algorithms) {
- s.putInt8(algorithm.getHashValue()); // HashAlgorithm
- s.putInt8(algorithm.getSignatureValue()); // SignatureAlgorithm
- }
- }
-
- @Override
- public String toString() {
- StringBuffer buffer = new StringBuffer();
- boolean opened = false;
- for (SignatureAndHashAlgorithm signAlg : algorithms) {
- if (opened) {
- buffer.append(", " + signAlg.getAlgorithmName());
- } else {
- buffer.append(signAlg.getAlgorithmName());
- opened = true;
- }
- }
-
- return "Extension " + type + ", signature_algorithms: " + buffer;
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/InputRecord.java b/ojluni/src/main/java/sun/security/ssl/InputRecord.java
deleted file mode 100755
index f714488..0000000
--- a/ojluni/src/main/java/sun/security/ssl/InputRecord.java
+++ /dev/null
@@ -1,833 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.nio.*;
-import java.net.SocketException;
-import java.net.SocketTimeoutException;
-
-import javax.crypto.BadPaddingException;
-
-import javax.net.ssl.*;
-
-import sun.misc.HexDumpEncoder;
-
-
-/**
- * SSL 3.0 records, as pulled off a TCP stream. Input records are
- * basically buffers tied to a particular input stream ... a layer
- * above this must map these records into the model of a continuous
- * stream of data.
- *
- * Since this returns SSL 3.0 records, it's the layer that needs to
- * map SSL 2.0 style handshake records into SSL 3.0 ones for those
- * "old" clients that interop with both V2 and V3 servers. Not as
- * pretty as might be desired.
- *
- * NOTE: During handshaking, each message must be hashed to support
- * verification that the handshake process wasn't compromised.
- *
- * @author David Brownell
- */
-class InputRecord extends ByteArrayInputStream implements Record {
-
- private HandshakeHash handshakeHash;
- private int lastHashed;
- boolean formatVerified = true; // SSLv2 ruled out?
- private boolean isClosed;
- private boolean appDataValid;
-
- // The ClientHello version to accept. If set to ProtocolVersion.SSL20Hello
- // and the first message we read is a ClientHello in V2 format, we convert
- // it to V3. Otherwise we throw an exception when encountering a V2 hello.
- private ProtocolVersion helloVersion;
-
- /* Class and subclass dynamic debugging support */
- static final Debug debug = Debug.getInstance("ssl");
-
- /* The existing record length */
- private int exlen;
-
- /* V2 handshake message */
- private byte v2Buf[];
-
- /*
- * Construct the record to hold the maximum sized input record.
- * Data will be filled in separately.
- */
- InputRecord() {
- super(new byte[maxRecordSize]);
- setHelloVersion(ProtocolVersion.DEFAULT_HELLO);
- pos = headerSize;
- count = headerSize;
- lastHashed = count;
- exlen = 0;
- v2Buf = null;
- }
-
- void setHelloVersion(ProtocolVersion helloVersion) {
- this.helloVersion = helloVersion;
- }
-
- ProtocolVersion getHelloVersion() {
- return helloVersion;
- }
-
- /*
- * Enable format checks if initial handshaking hasn't completed
- */
- void enableFormatChecks() {
- formatVerified = false;
- }
-
- // return whether the data in this record is valid, decrypted data
- boolean isAppDataValid() {
- return appDataValid;
- }
-
- void setAppDataValid(boolean value) {
- appDataValid = value;
- }
-
- /*
- * Return the content type of the record.
- */
- byte contentType() {
- return buf[0];
- }
-
- /*
- * For handshaking, we need to be able to hash every byte above the
- * record marking layer. This is where we're guaranteed to see those
- * bytes, so this is where we can hash them ... especially in the
- * case of hashing the initial V2 message!
- */
- void setHandshakeHash(HandshakeHash handshakeHash) {
- this.handshakeHash = handshakeHash;
- }
-
- HandshakeHash getHandshakeHash() {
- return handshakeHash;
- }
-
- void decrypt(MAC signer, CipherBox box) throws BadPaddingException {
-
- BadPaddingException reservedBPE = null;
- int tagLen = signer.MAClen();
- int cipheredLength = count - headerSize;
-
- if (!box.isNullCipher()) {
- // sanity check length of the ciphertext
- if (!box.sanityCheck(tagLen, cipheredLength)) {
- throw new BadPaddingException(
- "ciphertext sanity check failed");
- }
-
- try {
- // Note that the CipherBox.decrypt() does not change
- // the capacity of the buffer.
- count = headerSize +
- box.decrypt(buf, headerSize, cipheredLength, tagLen);
- } catch (BadPaddingException bpe) {
- // RFC 2246 states that decryption_failed should be used
- // for this purpose. However, that allows certain attacks,
- // so we just send bad record MAC. We also need to make
- // sure to always check the MAC to avoid a timing attack
- // for the same issue. See paper by Vaudenay et al and the
- // update in RFC 4346/5246.
- //
- // Failover to message authentication code checking.
- reservedBPE = bpe;
- }
- }
-
- if (tagLen != 0) {
- int macOffset = count - tagLen;
- int contentLen = macOffset - headerSize;
-
- // Note that although it is not necessary, we run the same MAC
- // computation and comparison on the payload for both stream
- // cipher and CBC block cipher.
- if (contentLen < 0) {
- // negative data length, something is wrong
- if (reservedBPE == null) {
- reservedBPE = new BadPaddingException("bad record");
- }
-
- // set offset of the dummy MAC
- macOffset = headerSize + cipheredLength - tagLen;
- contentLen = macOffset - headerSize;
- }
-
- count -= tagLen; // Set the count before any MAC checking
- // exception occurs, so that the following
- // process can read the actual decrypted
- // content (minus the MAC) in the fragment
- // if necessary.
-
- // Run MAC computation and comparison on the payload.
- if (checkMacTags(contentType(),
- buf, headerSize, contentLen, signer, false)) {
- if (reservedBPE == null) {
- reservedBPE = new BadPaddingException("bad record MAC");
- }
- }
-
- // Run MAC computation and comparison on the remainder.
- //
- // It is only necessary for CBC block cipher. It is used to get a
- // constant time of MAC computation and comparison on each record.
- if (box.isCBCMode()) {
- int remainingLen = calculateRemainingLen(
- signer, cipheredLength, contentLen);
-
- // NOTE: remainingLen may be bigger (less than 1 block of the
- // hash algorithm of the MAC) than the cipheredLength. However,
- // We won't need to worry about it because we always use a
- // maximum buffer for every record. We need a change here if
- // we use small buffer size in the future.
- if (remainingLen > buf.length) {
- // unlikely to happen, just a placehold
- throw new RuntimeException(
- "Internal buffer capacity error");
- }
-
- // Won't need to worry about the result on the remainder. And
- // then we won't need to worry about what's actual data to
- // check MAC tag on. We start the check from the header of the
- // buffer so that we don't need to construct a new byte buffer.
- checkMacTags(contentType(), buf, 0, remainingLen, signer, true);
- }
- }
-
- // Is it a failover?
- if (reservedBPE != null) {
- throw reservedBPE;
- }
- }
-
- /*
- * Run MAC computation and comparison
- *
- * Please DON'T change the content of the byte buffer parameter!
- */
- static boolean checkMacTags(byte contentType, byte[] buffer,
- int offset, int contentLen, MAC signer, boolean isSimulated) {
-
- int tagLen = signer.MAClen();
- byte[] hash = signer.compute(
- contentType, buffer, offset, contentLen, isSimulated);
- if (hash == null || tagLen != hash.length) {
- // Something is wrong with MAC implementation.
- throw new RuntimeException("Internal MAC error");
- }
-
- int[] results = compareMacTags(buffer, offset + contentLen, hash);
- return (results[0] != 0);
- }
-
- /*
- * A constant-time comparison of the MAC tags.
- *
- * Please DON'T change the content of the byte buffer parameter!
- */
- private static int[] compareMacTags(
- byte[] buffer, int offset, byte[] tag) {
-
- // An array of hits is used to prevent Hotspot optimization for
- // the purpose of a constant-time check.
- int[] results = {0, 0}; // {missed #, matched #}
-
- // The caller ensures there are enough bytes available in the buffer.
- // So we won't need to check the length of the buffer.
- for (int i = 0; i < tag.length; i++) {
- if (buffer[offset + i] != tag[i]) {
- results[0]++; // mismatched bytes
- } else {
- results[1]++; // matched bytes
- }
- }
-
- return results;
- }
-
- /*
- * Calculate the length of a dummy buffer to run MAC computation
- * and comparison on the remainder.
- *
- * The caller MUST ensure that the fullLen is not less than usedLen.
- */
- static int calculateRemainingLen(
- MAC signer, int fullLen, int usedLen) {
-
- int blockLen = signer.hashBlockLen();
- int minimalPaddingLen = signer.minimalPaddingLen();
-
- // (blockLen - minimalPaddingLen) is the maximum message size of
- // the last block of hash function operation. See FIPS 180-4, or
- // MD5 specification.
- fullLen += 13 - (blockLen - minimalPaddingLen);
- usedLen += 13 - (blockLen - minimalPaddingLen);
-
- // Note: fullLen is always not less than usedLen, and blockLen
- // is always bigger than minimalPaddingLen, so we don't worry
- // about negative values. 0x01 is added to the result to ensure
- // that the return value is positive. The extra one byte does
- // not impact the overall MAC compression function evaluations.
- return 0x01 + (int)(Math.ceil(fullLen/(1.0d * blockLen)) -
- Math.ceil(usedLen/(1.0d * blockLen))) * signer.hashBlockLen();
- }
-
- /*
- * Well ... hello_request messages are _never_ hashed since we can't
- * know when they'd appear in the sequence.
- */
- void ignore(int bytes) {
- if (bytes > 0) {
- pos += bytes;
- lastHashed = pos;
- }
- }
-
- /*
- * We hash the (plaintext) we've processed, but only on demand.
- *
- * There is one place where we want to access the hash in the middle
- * of a record: client cert message gets hashed, and part of the
- * same record is the client cert verify message which uses that hash.
- * So we track how much we've read and hashed.
- */
- void doHashes() {
- int len = pos - lastHashed;
-
- if (len > 0) {
- hashInternal(buf, lastHashed, len);
- lastHashed = pos;
- }
- }
-
- /*
- * Need a helper function so we can hash the V2 hello correctly
- */
- private void hashInternal(byte databuf [], int offset, int len) {
- if (debug != null && Debug.isOn("data")) {
- try {
- HexDumpEncoder hd = new HexDumpEncoder();
-
- System.out.println("[read] MD5 and SHA1 hashes: len = "
- + len);
- hd.encodeBuffer(new ByteArrayInputStream(databuf, offset, len),
- System.out);
- } catch (IOException e) { }
- }
- handshakeHash.update(databuf, offset, len);
- }
-
-
- /*
- * Handshake messages may cross record boundaries. We "queue"
- * these in big buffers if we need to cope with this problem.
- * This is not anticipated to be a common case; if this turns
- * out to be wrong, this can readily be sped up.
- */
- void queueHandshake(InputRecord r) throws IOException {
- int len;
-
- /*
- * Hash any data that's read but unhashed.
- */
- doHashes();
-
- /*
- * Move any unread data to the front of the buffer,
- * flagging it all as unhashed.
- */
- if (pos > headerSize) {
- len = count - pos;
- if (len != 0) {
- System.arraycopy(buf, pos, buf, headerSize, len);
- }
- pos = headerSize;
- lastHashed = pos;
- count = headerSize + len;
- }
-
- /*
- * Grow "buf" if needed
- */
- len = r.available() + count;
- if (buf.length < len) {
- byte newbuf [];
-
- newbuf = new byte [len];
- System.arraycopy(buf, 0, newbuf, 0, count);
- buf = newbuf;
- }
-
- /*
- * Append the new buffer to this one.
- */
- System.arraycopy(r.buf, r.pos, buf, count, len - count);
- count = len;
-
- /*
- * Adjust lastHashed; important for now with clients which
- * send SSL V2 client hellos. This will go away eventually,
- * by buffer code cleanup.
- */
- len = r.lastHashed - r.pos;
- if (pos == headerSize) {
- lastHashed += len;
- } else {
- throw new SSLProtocolException("?? confused buffer hashing ??");
- }
- // we've read the record, advance the pointers
- r.pos = r.count;
- }
-
-
- /**
- * Prevent any more data from being read into this record,
- * and flag the record as holding no data.
- */
- public void close() {
- appDataValid = false;
- isClosed = true;
- mark = 0;
- pos = 0;
- count = 0;
- }
-
-
- /*
- * We may need to send this SSL v2 "No Cipher" message back, if we
- * are faced with an SSLv2 "hello" that's not saying "I talk v3".
- * It's the only one documented in the V2 spec as a fatal error.
- */
- private static final byte[] v2NoCipher = {
- (byte)0x80, (byte)0x03, // unpadded 3 byte record
- (byte)0x00, // ... error message
- (byte)0x00, (byte)0x01 // ... NO_CIPHER error
- };
-
- private int readFully(InputStream s, byte b[], int off, int len)
- throws IOException {
- int n = 0;
- while (n < len) {
- int readLen = s.read(b, off + n, len - n);
- if (readLen < 0) {
- return readLen;
- }
-
- if (debug != null && Debug.isOn("packet")) {
- try {
- HexDumpEncoder hd = new HexDumpEncoder();
- ByteBuffer bb = ByteBuffer.wrap(b, off + n, readLen);
-
- System.out.println("[Raw read]: length = " +
- bb.remaining());
- hd.encodeBuffer(bb, System.out);
- } catch (IOException e) { }
- }
-
- n += readLen;
- exlen += readLen;
- }
-
- return n;
- }
-
- /*
- * Read the SSL V3 record ... first time around, check to see if it
- * really IS a V3 record. Handle SSL V2 clients which can talk V3.0,
- * as well as real V3 record format; otherwise report an error.
- */
- void read(InputStream s, OutputStream o) throws IOException {
- if (isClosed) {
- return;
- }
-
- /*
- * For SSL it really _is_ an error if the other end went away
- * so ungracefully as to not shut down cleanly.
- */
- if(exlen < headerSize) {
- int really = readFully(s, buf, exlen, headerSize - exlen);
- if (really < 0) {
- throw new EOFException("SSL peer shut down incorrectly");
- }
-
- pos = headerSize;
- count = headerSize;
- lastHashed = pos;
- }
-
- /*
- * The first record might use some other record marking convention,
- * typically SSL v2 header. (PCT could also be detected here.)
- * This case is currently common -- Navigator 3.0 usually works
- * this way, as do IE 3.0 and other products.
- */
- if (!formatVerified) {
- formatVerified = true;
- /*
- * The first record must either be a handshake record or an
- * alert message. If it's not, it is either invalid or an
- * SSLv2 message.
- */
- if (buf[0] != ct_handshake && buf[0] != ct_alert) {
- handleUnknownRecord(s, o);
- } else {
- readV3Record(s, o);
- }
- } else { // formatVerified == true
- readV3Record(s, o);
- }
- }
-
- /**
- * Read a SSL/TLS record. Throw an IOException if the format is invalid.
- */
- private void readV3Record(InputStream s, OutputStream o)
- throws IOException {
- ProtocolVersion recordVersion = ProtocolVersion.valueOf(buf[1], buf[2]);
- // Check if too old (currently not possible)
- // or if the major version does not match.
- // The actual version negotiation is in the handshaker classes
- if ((recordVersion.v < ProtocolVersion.MIN.v)
- || (recordVersion.major > ProtocolVersion.MAX.major)) {
- throw new SSLException(
- "Unsupported record version " + recordVersion);
- }
-
- /*
- * Get and check length, then the data.
- */
- int contentLen = ((buf[3] & 0x0ff) << 8) + (buf[4] & 0xff);
-
- /*
- * Check for upper bound.
- */
- if (contentLen < 0 || contentLen > maxLargeRecordSize - headerSize) {
- throw new SSLProtocolException("Bad InputRecord size"
- + ", count = " + contentLen
- + ", buf.length = " + buf.length);
- }
-
- /*
- * Grow "buf" if needed. Since buf is maxRecordSize by default,
- * this only occurs when we receive records which violate the
- * SSL specification. This is a workaround for a Microsoft SSL bug.
- */
- if (contentLen > buf.length - headerSize) {
- byte[] newbuf = new byte[contentLen + headerSize];
- System.arraycopy(buf, 0, newbuf, 0, headerSize);
- buf = newbuf;
- }
-
- if (exlen < contentLen + headerSize) {
- int really = readFully(
- s, buf, exlen, contentLen + headerSize - exlen);
- if (really < 0) {
- throw new SSLException("SSL peer shut down incorrectly");
- }
- }
-
- // now we've got a complete record.
- count = contentLen + headerSize;
- exlen = 0;
-
- if (debug != null && Debug.isOn("record")) {
- if (count < 0 || count > (maxRecordSize - headerSize)) {
- System.out.println(Thread.currentThread().getName()
- + ", Bad InputRecord size" + ", count = " + count);
- }
- System.out.println(Thread.currentThread().getName()
- + ", READ: " + recordVersion + " "
- + contentName(contentType()) + ", length = " + available());
- }
- /*
- * then caller decrypts, verifies, and uncompresses
- */
- }
-
- /**
- * Deal with unknown records. Called if the first data we read on this
- * connection does not look like an SSL/TLS record. It could a SSLv2
- * message, or just garbage.
- */
- private void handleUnknownRecord(InputStream s, OutputStream o)
- throws IOException {
- /*
- * No? Oh well; does it look like a V2 "ClientHello"?
- * That'd be an unpadded handshake message; we don't
- * bother checking length just now.
- */
- if (((buf[0] & 0x080) != 0) && buf[2] == 1) {
- /*
- * if the user has disabled SSLv2Hello (using
- * setEnabledProtocol) then throw an
- * exception
- */
- if (helloVersion != ProtocolVersion.SSL20Hello) {
- throw new SSLHandshakeException("SSLv2Hello is disabled");
- }
-
- ProtocolVersion recordVersion =
- ProtocolVersion.valueOf(buf[3], buf[4]);
-
- if (recordVersion == ProtocolVersion.SSL20Hello) {
- /*
- * Looks like a V2 client hello, but not one saying
- * "let's talk SSLv3". So we send an SSLv2 error
- * message, one that's treated as fatal by clients.
- * (Otherwise we'll hang.)
- */
- try {
- writeBuffer(o, v2NoCipher, 0, v2NoCipher.length);
- } catch (Exception e) {
- /* NOTHING */
- }
- throw new SSLException("Unsupported SSL v2.0 ClientHello");
- }
-
- /*
- * If we can map this into a V3 ClientHello, read and
- * hash the rest of the V2 handshake, turn it into a
- * V3 ClientHello message, and pass it up.
- */
- int len = ((buf[0] & 0x7f) << 8) +
- (buf[1] & 0xff) - 3;
- if (v2Buf == null) {
- v2Buf = new byte[len];
- }
- if (exlen < len + headerSize) {
- int really = readFully(
- s, v2Buf, exlen - headerSize, len + headerSize - exlen);
- if (really < 0) {
- throw new EOFException("SSL peer shut down incorrectly");
- }
- }
-
- // now we've got a complete record.
- exlen = 0;
-
- hashInternal(buf, 2, 3);
- hashInternal(v2Buf, 0, len);
- V2toV3ClientHello(v2Buf);
- v2Buf = null;
- lastHashed = count;
-
- if (debug != null && Debug.isOn("record")) {
- System.out.println(
- Thread.currentThread().getName()
- + ", READ: SSL v2, contentType = "
- + contentName(contentType())
- + ", translated length = " + available());
- }
- return;
-
- } else {
- /*
- * Does it look like a V2 "ServerHello"?
- */
- if (((buf [0] & 0x080) != 0) && buf [2] == 4) {
- throw new SSLException(
- "SSL V2.0 servers are not supported.");
- }
-
- /*
- * If this is a V2 NoCipher message then this means
- * the other server doesn't support V3. Otherwise, we just
- * don't understand what it's saying.
- */
- for (int i = 0; i < v2NoCipher.length; i++) {
- if (buf[i] != v2NoCipher[i]) {
- throw new SSLException(
- "Unrecognized SSL message, plaintext connection?");
- }
- }
-
- throw new SSLException("SSL V2.0 servers are not supported.");
- }
- }
-
- /*
- * Actually do the write here. For SSLEngine's HS data,
- * we'll override this method and let it take the appropriate
- * action.
- */
- void writeBuffer(OutputStream s, byte [] buf, int off, int len)
- throws IOException {
- s.write(buf, 0, len);
- s.flush();
- }
-
- /*
- * Support "old" clients which are capable of SSL V3.0 protocol ... for
- * example, Navigator 3.0 clients. The V2 message is in the header and
- * the bytes passed as parameter. This routine translates the V2 message
- * into an equivalent V3 one.
- */
- private void V2toV3ClientHello(byte v2Msg []) throws SSLException
- {
- int i;
-
- /*
- * Build the first part of the V3 record header from the V2 one
- * that's now buffered up. (Lengths are fixed up later).
- */
- buf [0] = ct_handshake;
- buf [1] = buf [3]; // V3.x
- buf[2] = buf[4];
- // header [3..4] for handshake message length
- // count = 5;
-
- /*
- * Store the generic V3 handshake header: 4 bytes
- */
- buf [5] = 1; // HandshakeMessage.ht_client_hello
- // buf [6..8] for length of ClientHello (int24)
- // count += 4;
-
- /*
- * ClientHello header starts with SSL version
- */
- buf [9] = buf [1];
- buf [10] = buf [2];
- // count += 2;
- count = 11;
-
- /*
- * Start parsing the V2 message ...
- */
- int cipherSpecLen, sessionIdLen, nonceLen;
-
- cipherSpecLen = ((v2Msg [0] & 0xff) << 8) + (v2Msg [1] & 0xff);
- sessionIdLen = ((v2Msg [2] & 0xff) << 8) + (v2Msg [3] & 0xff);
- nonceLen = ((v2Msg [4] & 0xff) << 8) + (v2Msg [5] & 0xff);
-
- /*
- * Copy Random value/nonce ... if less than the 32 bytes of
- * a V3 "Random", right justify and zero pad to the left. Else
- * just take the last 32 bytes.
- */
- int offset = 6 + cipherSpecLen + sessionIdLen;
-
- if (nonceLen < 32) {
- for (i = 0; i < (32 - nonceLen); i++)
- buf [count++] = 0;
- System.arraycopy(v2Msg, offset, buf, count, nonceLen);
- count += nonceLen;
- } else {
- System.arraycopy(v2Msg, offset + (nonceLen - 32),
- buf, count, 32);
- count += 32;
- }
-
- /*
- * Copy Session ID (only one byte length!)
- */
- offset -= sessionIdLen;
- buf [count++] = (byte) sessionIdLen;
-
- System.arraycopy(v2Msg, offset, buf, count, sessionIdLen);
- count += sessionIdLen;
-
- /*
- * Copy and translate cipher suites ... V2 specs with first byte zero
- * are really V3 specs (in the last 2 bytes), just copy those and drop
- * the other ones. Preference order remains unchanged.
- *
- * Example: Netscape Navigator 3.0 (exportable) says:
- *
- * 0/3, SSL_RSA_EXPORT_WITH_RC4_40_MD5
- * 0/6, SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5
- *
- * Microsoft Internet Explorer 3.0 (exportable) supports only
- *
- * 0/3, SSL_RSA_EXPORT_WITH_RC4_40_MD5
- */
- int j;
-
- offset -= cipherSpecLen;
- j = count + 2;
-
- for (i = 0; i < cipherSpecLen; i += 3) {
- if (v2Msg [offset + i] != 0)
- continue;
- buf [j++] = v2Msg [offset + i + 1];
- buf [j++] = v2Msg [offset + i + 2];
- }
-
- j -= count + 2;
- buf [count++] = (byte) (j >>> 8);
- buf [count++] = (byte) j;
- count += j;
-
- /*
- * Append compression methods (default/null only)
- */
- buf [count++] = 1;
- buf [count++] = 0; // Session.compression_null
-
- /*
- * Fill in lengths of the messages we synthesized (nested:
- * V3 handshake message within V3 record) and then return
- */
- buf [3] = (byte) (count - headerSize);
- buf [4] = (byte) ((count - headerSize) >>> 8);
-
- buf [headerSize + 1] = 0;
- buf [headerSize + 2] = (byte) (((count - headerSize) - 4) >>> 8);
- buf [headerSize + 3] = (byte) ((count - headerSize) - 4);
-
- pos = headerSize;
- }
-
- /**
- * Return a description for the given content type. This method should be
- * in Record, but since that is an interface this is not possible.
- * Called from InputRecord and OutputRecord.
- */
- static String contentName(int contentType) {
- switch (contentType) {
- case ct_change_cipher_spec:
- return "Change Cipher Spec";
- case ct_alert:
- return "Alert";
- case ct_handshake:
- return "Handshake";
- case ct_application_data:
- return "Application Data";
- default:
- return "contentType = " + contentType;
- }
- }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/JsseJce.java b/ojluni/src/main/java/sun/security/ssl/JsseJce.java
deleted file mode 100755
index d91b8f4..0000000
--- a/ojluni/src/main/java/sun/security/ssl/JsseJce.java
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.util.*;
-import java.math.BigInteger;
-
-import java.security.*;
-import java.security.interfaces.RSAPublicKey;
-import java.security.spec.RSAPublicKeySpec;
-import java.security.spec.*;
-
-import javax.crypto.*;
-
-// explicit import to override the Provider class in this package
-import java.security.Provider;
-
-// need internal Sun classes for FIPS tricks
-import sun.security.jca.Providers;
-import sun.security.jca.ProviderList;
-
-import sun.security.ec.ECParameters;
-import sun.security.ec.NamedCurve;
-
-import static sun.security.ssl.SunJSSE.cryptoProvider;
-
-/**
- * This class contains a few static methods for interaction with the JCA/JCE
- * to obtain implementations, etc.
- *
- * @author Andreas Sterbenz
- */
-final class JsseJce {
-
- private final static Debug debug = Debug.getInstance("ssl");
-
- private final static ProviderList fipsProviderList;
-
- // Flag indicating whether EC crypto is available.
- // If null, then we have not checked yet.
- // If yes, then all the EC based crypto we need is available.
- private static Boolean ecAvailable;
-
- // Flag indicating whether Kerberos crypto is available.
- // If true, then all the Kerberos-based crypto we need is available.
- private final static boolean kerberosAvailable;
- static {
- boolean temp;
- try {
- AccessController.doPrivileged(
- new PrivilegedExceptionAction<Void>() {
- public Void run() throws Exception {
- // Test for Kerberos using the bootstrap class loader
- Class.forName("sun.security.krb5.PrincipalName", true,
- null);
- return null;
- }
- });
- temp = true;
-
- } catch (Exception e) {
- temp = false;
- }
- kerberosAvailable = temp;
- }
-
- static {
- // force FIPS flag initialization
- // Because isFIPS() is synchronized and cryptoProvider is not modified
- // after it completes, this also eliminates the need for any further
- // synchronization when accessing cryptoProvider
- if (SunJSSE.isFIPS() == false) {
- fipsProviderList = null;
- } else {
- // Setup a ProviderList that can be used by the trust manager
- // during certificate chain validation. All the crypto must be
- // from the FIPS provider, but we also allow the required
- // certificate related services from the SUN provider.
- Provider sun = Security.getProvider("SUN");
- if (sun == null) {
- throw new RuntimeException
- ("FIPS mode: SUN provider must be installed");
- }
- Provider sunCerts = new SunCertificates(sun);
- fipsProviderList = ProviderList.newList(cryptoProvider, sunCerts);
- }
- }
-
- private static final class SunCertificates extends Provider {
- SunCertificates(final Provider p) {
- super("SunCertificates", 1.0d, "SunJSSE internal");
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- // copy certificate related services from the Sun provider
- for (Map.Entry<Object,Object> entry : p.entrySet()) {
- String key = (String)entry.getKey();
- if (key.startsWith("CertPathValidator.")
- || key.startsWith("CertPathBuilder.")
- || key.startsWith("CertStore.")
- || key.startsWith("CertificateFactory.")) {
- put(key, entry.getValue());
- }
- }
- return null;
- }
- });
- }
- }
-
- /**
- * JCE transformation string for RSA with PKCS#1 v1.5 padding.
- * Can be used for encryption, decryption, signing, verifying.
- */
- final static String CIPHER_RSA_PKCS1 = "RSA/ECB/PKCS1Padding";
- /**
- * JCE transformation string for the stream cipher RC4.
- */
- final static String CIPHER_RC4 = "RC4";
- /**
- * JCE transformation string for DES in CBC mode without padding.
- */
- final static String CIPHER_DES = "DES/CBC/NoPadding";
- /**
- * JCE transformation string for (3-key) Triple DES in CBC mode
- * without padding.
- */
- final static String CIPHER_3DES = "DESede/CBC/NoPadding";
- /**
- * JCE transformation string for AES in CBC mode
- * without padding.
- */
- final static String CIPHER_AES = "AES/CBC/NoPadding";
- /**
- * JCA identifier string for DSA, i.e. a DSA with SHA-1.
- */
- final static String SIGNATURE_DSA = "DSA";
- /**
- * JCA identifier string for ECDSA, i.e. a ECDSA with SHA-1.
- */
- final static String SIGNATURE_ECDSA = "SHA1withECDSA";
- /**
- * JCA identifier string for Raw DSA, i.e. a DSA signature without
- * hashing where the application provides the SHA-1 hash of the data.
- * Note that the standard name is "NONEwithDSA" but we use "RawDSA"
- * for compatibility.
- */
- final static String SIGNATURE_RAWDSA = "RawDSA";
- /**
- * JCA identifier string for Raw ECDSA, i.e. a DSA signature without
- * hashing where the application provides the SHA-1 hash of the data.
- */
- final static String SIGNATURE_RAWECDSA = "NONEwithECDSA";
- /**
- * JCA identifier string for Raw RSA, i.e. a RSA PKCS#1 v1.5 signature
- * without hashing where the application provides the hash of the data.
- * Used for RSA client authentication with a 36 byte hash.
- */
- final static String SIGNATURE_RAWRSA = "NONEwithRSA";
- /**
- * JCA identifier string for the SSL/TLS style RSA Signature. I.e.
- * an signature using RSA with PKCS#1 v1.5 padding signing a
- * concatenation of an MD5 and SHA-1 digest.
- */
- final static String SIGNATURE_SSLRSA = "MD5andSHA1withRSA";
-
- private JsseJce() {
- // no instantiation of this class
- }
-
- synchronized static boolean isEcAvailable() {
- if (ecAvailable == null) {
- try {
- JsseJce.getSignature(SIGNATURE_ECDSA);
- JsseJce.getSignature(SIGNATURE_RAWECDSA);
- JsseJce.getKeyAgreement("ECDH");
- JsseJce.getKeyFactory("EC");
- JsseJce.getKeyPairGenerator("EC");
- ecAvailable = true;
- } catch (Exception e) {
- ecAvailable = false;
- }
- }
- return ecAvailable;
- }
-
- synchronized static void clearEcAvailable() {
- ecAvailable = null;
- }
-
- static boolean isKerberosAvailable() {
- return kerberosAvailable;
- }
-
- /**
- * Return an JCE cipher implementation for the specified algorithm.
- */
- static Cipher getCipher(String transformation)
- throws NoSuchAlgorithmException {
- try {
- if (cryptoProvider == null) {
- return Cipher.getInstance(transformation);
- } else {
- return Cipher.getInstance(transformation, cryptoProvider);
- }
- } catch (NoSuchPaddingException e) {
- throw new NoSuchAlgorithmException(e);
- }
- }
-
- /**
- * Return an JCA signature implementation for the specified algorithm.
- * The algorithm string should be one of the constants defined
- * in this class.
- */
- static Signature getSignature(String algorithm)
- throws NoSuchAlgorithmException {
- if (cryptoProvider == null) {
- return Signature.getInstance(algorithm);
- } else {
- // reference equality
- if (algorithm == SIGNATURE_SSLRSA) {
- // The SunPKCS11 provider currently does not support this
- // special algorithm. We allow a fallback in this case because
- // the SunJSSE implementation does the actual crypto using
- // a NONEwithRSA signature obtained from the cryptoProvider.
- if (cryptoProvider.getService("Signature", algorithm) == null) {
- // Calling Signature.getInstance() and catching the
- // exception would be cleaner, but exceptions are a little
- // expensive. So we check directly via getService().
- try {
- return Signature.getInstance(algorithm, "SunJSSE");
- } catch (NoSuchProviderException e) {
- throw new NoSuchAlgorithmException(e);
- }
- }
- }
- return Signature.getInstance(algorithm, cryptoProvider);
- }
- }
-
- static KeyGenerator getKeyGenerator(String algorithm)
- throws NoSuchAlgorithmException {
- if (cryptoProvider == null) {
- return KeyGenerator.getInstance(algorithm);
- } else {
- return KeyGenerator.getInstance(algorithm, cryptoProvider);
- }
- }
-
- static KeyPairGenerator getKeyPairGenerator(String algorithm)
- throws NoSuchAlgorithmException {
- if (cryptoProvider == null) {
- return KeyPairGenerator.getInstance(algorithm);
- } else {
- return KeyPairGenerator.getInstance(algorithm, cryptoProvider);
- }
- }
-
- static KeyAgreement getKeyAgreement(String algorithm)
- throws NoSuchAlgorithmException {
- if (cryptoProvider == null) {
- return KeyAgreement.getInstance(algorithm);
- } else {
- return KeyAgreement.getInstance(algorithm, cryptoProvider);
- }
- }
-
- static Mac getMac(String algorithm)
- throws NoSuchAlgorithmException {
- if (cryptoProvider == null) {
- return Mac.getInstance(algorithm);
- } else {
- return Mac.getInstance(algorithm, cryptoProvider);
- }
- }
-
- static KeyFactory getKeyFactory(String algorithm)
- throws NoSuchAlgorithmException {
- if (cryptoProvider == null) {
- return KeyFactory.getInstance(algorithm);
- } else {
- return KeyFactory.getInstance(algorithm, cryptoProvider);
- }
- }
-
- static SecureRandom getSecureRandom() throws KeyManagementException {
- if (cryptoProvider == null) {
- return new SecureRandom();
- }
- // Try "PKCS11" first. If that is not supported, iterate through
- // the provider and return the first working implementation.
- try {
- return SecureRandom.getInstance("PKCS11", cryptoProvider);
- } catch (NoSuchAlgorithmException e) {
- // ignore
- }
- for (Provider.Service s : cryptoProvider.getServices()) {
- if (s.getType().equals("SecureRandom")) {
- try {
- return SecureRandom.getInstance(s.getAlgorithm(), cryptoProvider);
- } catch (NoSuchAlgorithmException ee) {
- // ignore
- }
- }
- }
- throw new KeyManagementException("FIPS mode: no SecureRandom "
- + " implementation found in provider " + cryptoProvider.getName());
- }
-
- static MessageDigest getMD5() {
- return getMessageDigest("MD5");
- }
-
- static MessageDigest getSHA() {
- return getMessageDigest("SHA");
- }
-
- static MessageDigest getMessageDigest(String algorithm) {
- try {
- if (cryptoProvider == null) {
- return MessageDigest.getInstance(algorithm);
- } else {
- return MessageDigest.getInstance(algorithm, cryptoProvider);
- }
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException
- ("Algorithm " + algorithm + " not available", e);
- }
- }
-
- static int getRSAKeyLength(PublicKey key) {
- BigInteger modulus;
- if (key instanceof RSAPublicKey) {
- modulus = ((RSAPublicKey)key).getModulus();
- } else {
- RSAPublicKeySpec spec = getRSAPublicKeySpec(key);
- modulus = spec.getModulus();
- }
- return modulus.bitLength();
- }
-
- static RSAPublicKeySpec getRSAPublicKeySpec(PublicKey key) {
- if (key instanceof RSAPublicKey) {
- RSAPublicKey rsaKey = (RSAPublicKey)key;
- return new RSAPublicKeySpec(rsaKey.getModulus(),
- rsaKey.getPublicExponent());
- }
- try {
- KeyFactory factory = JsseJce.getKeyFactory("RSA");
- return factory.getKeySpec(key, RSAPublicKeySpec.class);
- } catch (Exception e) {
- throw (RuntimeException)new RuntimeException().initCause(e);
- }
- }
-
- static ECParameterSpec getECParameterSpec(String namedCurveOid) {
- return NamedCurve.getECParameterSpec(namedCurveOid);
- }
-
- static String getNamedCurveOid(ECParameterSpec params) {
- return ECParameters.getCurveName(params);
- }
-
- static ECPoint decodePoint(byte[] encoded, EllipticCurve curve)
- throws java.io.IOException {
- return ECParameters.decodePoint(encoded, curve);
- }
-
- static byte[] encodePoint(ECPoint point, EllipticCurve curve) {
- return ECParameters.encodePoint(point, curve);
- }
-
- // In FIPS mode, set thread local providers; otherwise a no-op.
- // Must be paired with endFipsProvider.
- static Object beginFipsProvider() {
- if (fipsProviderList == null) {
- return null;
- } else {
- return Providers.beginThreadProviderList(fipsProviderList);
- }
- }
-
- static void endFipsProvider(Object o) {
- if (fipsProviderList != null) {
- Providers.endThreadProviderList((ProviderList)o);
- }
- }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/KerberosClientKeyExchange.java b/ojluni/src/main/java/sun/security/ssl/KerberosClientKeyExchange.java
deleted file mode 100755
index 339f94b..0000000
--- a/ojluni/src/main/java/sun/security/ssl/KerberosClientKeyExchange.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.security.AccessController;
-import java.security.AccessControlContext;
-import java.security.Principal;
-import java.security.PrivilegedAction;
-import java.security.SecureRandom;
-import javax.crypto.SecretKey;
-
-/**
- * A helper class that calls the KerberosClientKeyExchange implementation.
- */
-public class KerberosClientKeyExchange extends HandshakeMessage {
-
- private static final String IMPL_CLASS =
- "sun.security.ssl.krb5.KerberosClientKeyExchangeImpl";
-
- private static final Class<?> implClass = AccessController.doPrivileged(
- new PrivilegedAction<Class<?>>() {
- public Class<?> run() {
- try {
- return Class.forName(IMPL_CLASS, true, null);
- } catch (ClassNotFoundException cnf) {
- return null;
- }
- }
- }
- );
- private final KerberosClientKeyExchange impl = createImpl();
-
- private KerberosClientKeyExchange createImpl() {
- if (getClass() == KerberosClientKeyExchange.class) {
- try {
- return (KerberosClientKeyExchange)implClass.newInstance();
- } catch (InstantiationException e) {
- throw new AssertionError(e);
- } catch (IllegalAccessException e) {
- throw new AssertionError(e);
- }
- }
- return null;
- }
-
- public KerberosClientKeyExchange() {
- // empty
- }
-
- public KerberosClientKeyExchange(String serverName, boolean isLoopback,
- AccessControlContext acc, ProtocolVersion protocolVersion,
- SecureRandom rand) throws IOException {
-
- if (impl != null) {
- init(serverName, isLoopback, acc, protocolVersion, rand);
- } else {
- throw new IllegalStateException("Kerberos is unavailable");
- }
- }
-
- public KerberosClientKeyExchange(ProtocolVersion protocolVersion,
- ProtocolVersion clientVersion, SecureRandom rand,
- HandshakeInStream input, SecretKey[] serverKeys) throws IOException {
-
- if (impl != null) {
- init(protocolVersion, clientVersion, rand, input, serverKeys);
- } else {
- throw new IllegalStateException("Kerberos is unavailable");
- }
- }
-
- @Override
- int messageType() {
- return ht_client_key_exchange;
- }
-
- @Override
- public int messageLength() {
- return impl.messageLength();
- }
-
- @Override
- public void send(HandshakeOutStream s) throws IOException {
- impl.send(s);
- }
-
- @Override
- public void print(PrintStream p) throws IOException {
- impl.print(p);
- }
-
- public void init(String serverName, boolean isLoopback,
- AccessControlContext acc, ProtocolVersion protocolVersion,
- SecureRandom rand) throws IOException {
-
- if (impl != null) {
- impl.init(serverName, isLoopback, acc, protocolVersion, rand);
- }
- }
-
- public void init(ProtocolVersion protocolVersion,
- ProtocolVersion clientVersion, SecureRandom rand,
- HandshakeInStream input, SecretKey[] serverKeys) throws IOException {
-
- if (impl != null) {
- impl.init(protocolVersion, clientVersion, rand, input, serverKeys);
- }
- }
-
- public byte[] getUnencryptedPreMasterSecret() {
- return impl.getUnencryptedPreMasterSecret();
- }
-
- public Principal getPeerPrincipal(){
- return impl.getPeerPrincipal();
- }
-
- public Principal getLocalPrincipal(){
- return impl.getLocalPrincipal();
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/Krb5Helper.java b/ojluni/src/main/java/sun/security/ssl/Krb5Helper.java
deleted file mode 100755
index d1bbe83..0000000
--- a/ojluni/src/main/java/sun/security/ssl/Krb5Helper.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.Permission;
-import java.security.Principal;
-import java.security.PrivilegedAction;
-import javax.crypto.SecretKey;
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginException;
-
-/**
- * A helper class for Kerberos APIs.
- */
-public final class Krb5Helper {
-
- private Krb5Helper() { }
-
- // loads Krb5Proxy implementation class if available
- private static final String IMPL_CLASS =
- "sun.security.ssl.krb5.Krb5ProxyImpl";
-
- private static final Krb5Proxy proxy =
- AccessController.doPrivileged(new PrivilegedAction<Krb5Proxy>() {
- public Krb5Proxy run() {
- try {
- Class<?> c = Class.forName(IMPL_CLASS, true, null);
- return (Krb5Proxy)c.newInstance();
- } catch (ClassNotFoundException cnf) {
- return null;
- } catch (InstantiationException e) {
- throw new AssertionError(e);
- } catch (IllegalAccessException e) {
- throw new AssertionError(e);
- }
- }});
-
- /**
- * Returns true if Kerberos is available.
- */
- public static boolean isAvailable() {
- return proxy != null;
- }
-
- private static void ensureAvailable() {
- if (proxy == null)
- throw new AssertionError("Kerberos should have been available");
- }
-
- /**
- * Returns the Subject associated with client-side of the SSL socket.
- */
- public static Subject getClientSubject(AccessControlContext acc)
- throws LoginException {
- ensureAvailable();
- return proxy.getClientSubject(acc);
- }
-
- /**
- * Returns the Subject associated with server-side of the SSL socket.
- */
- public static Subject getServerSubject(AccessControlContext acc)
- throws LoginException {
- ensureAvailable();
- return proxy.getServerSubject(acc);
- }
-
- /**
- * Returns the KerberosKeys for the default server-side principal.
- */
- public static SecretKey[] getServerKeys(AccessControlContext acc)
- throws LoginException {
- ensureAvailable();
- return proxy.getServerKeys(acc);
- }
-
- /**
- * Returns the server-side principal name associated with the KerberosKey.
- */
- public static String getServerPrincipalName(SecretKey kerberosKey) {
- ensureAvailable();
- return proxy.getServerPrincipalName(kerberosKey);
- }
-
- /**
- * Returns the hostname embedded in the principal name.
- */
- public static String getPrincipalHostName(Principal principal) {
- ensureAvailable();
- return proxy.getPrincipalHostName(principal);
- }
-
- /**
- * Returns a ServicePermission for the principal name and action.
- */
- public static Permission getServicePermission(String principalName,
- String action) {
- ensureAvailable();
- return proxy.getServicePermission(principalName, action);
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/Krb5Proxy.java b/ojluni/src/main/java/sun/security/ssl/Krb5Proxy.java
deleted file mode 100755
index 14a1501..0000000
--- a/ojluni/src/main/java/sun/security/ssl/Krb5Proxy.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.security.AccessControlContext;
-import java.security.Permission;
-import java.security.Principal;
-import javax.crypto.SecretKey;
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginException;
-
-/**
- * An interface to a subset of the Kerberos APIs to avoid a static dependency
- * on the types defined by these APIs.
- */
-public interface Krb5Proxy {
-
- /**
- * Returns the Subject associated with the client-side of the SSL socket.
- */
- Subject getClientSubject(AccessControlContext acc) throws LoginException;
-
- /**
- * Returns the Subject associated with the server-side of the SSL socket.
- */
- Subject getServerSubject(AccessControlContext acc) throws LoginException;
-
-
- /**
- * Returns the KerberosKeys for the default server-side principal.
- */
- SecretKey[] getServerKeys(AccessControlContext acc) throws LoginException;
-
- /**
- * Returns the server-side principal name associated with the KerberosKey.
- */
- String getServerPrincipalName(SecretKey kerberosKey);
-
- /**
- * Returns the hostname embedded in the principal name.
- */
- String getPrincipalHostName(Principal principal);
-
- /**
- * Returns a ServicePermission for the principal name and action.
- */
- Permission getServicePermission(String principalName, String action);
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/MAC.java b/ojluni/src/main/java/sun/security/ssl/MAC.java
deleted file mode 100755
index e491cc3..0000000
--- a/ojluni/src/main/java/sun/security/ssl/MAC.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.security.InvalidKeyException;
-import java.security.NoSuchAlgorithmException;
-
-import java.nio.ByteBuffer;
-
-import javax.crypto.Mac;
-import javax.crypto.SecretKey;
-
-import sun.security.ssl.CipherSuite.MacAlg;
-import static sun.security.ssl.CipherSuite.*;
-
-/**
- * This class computes the "Message Authentication Code" (MAC) for each
- * SSL message. This is essentially a shared-secret signature, used to
- * provide integrity protection for SSL messages. The MAC is actually
- * one of several keyed hashes, as associated with the cipher suite and
- * protocol version. (SSL v3.0 uses one construct, TLS uses another.)
- * <P>
- * NOTE: MAC computation is the only place in the SSL protocol that the
- * sequence number is used. It's also reset to zero with each change of
- * a cipher spec, so this is the only place this state is needed.
- *
- * @author David Brownell
- * @author Andreas Sterbenz
- */
-final class MAC {
-
- final static MAC NULL = new MAC();
-
- // Value of the null MAC is fixed
- private static final byte nullMAC[] = new byte[0];
-
- // internal identifier for the MAC algorithm
- private final MacAlg macAlg;
-
- // stuff defined by the kind of MAC algorithm
- private final int macSize;
-
- // JCE Mac object
- private final Mac mac;
-
- // byte array containing the additional information we MAC in each record
- // (see below)
- private final byte[] block;
-
- // sequence number + record type + + record length
- private static final int BLOCK_SIZE_SSL = 8 + 1 + 2;
-
- // sequence number + record type + protocol version + record length
- private static final int BLOCK_SIZE_TLS = 8 + 1 + 2 + 2;
-
- // offset of record type in block
- private static final int BLOCK_OFFSET_TYPE = 8;
-
- // offset of protocol version number in block (TLS only)
- private static final int BLOCK_OFFSET_VERSION = 8 + 1;
-
- private MAC() {
- macSize = 0;
- macAlg = M_NULL;
- mac = null;
- block = null;
- }
-
- /**
- * Set up, configured for the given SSL/TLS MAC type and version.
- */
- MAC(MacAlg macAlg, ProtocolVersion protocolVersion, SecretKey key)
- throws NoSuchAlgorithmException, InvalidKeyException {
- this.macAlg = macAlg;
- this.macSize = macAlg.size;
-
- String algorithm;
- boolean tls = (protocolVersion.v >= ProtocolVersion.TLS10.v);
-
- if (macAlg == M_MD5) {
- algorithm = tls ? "HmacMD5" : "SslMacMD5";
- } else if (macAlg == M_SHA) {
- algorithm = tls ? "HmacSHA1" : "SslMacSHA1";
- } else if (macAlg == M_SHA256) {
- algorithm = "HmacSHA256"; // TLS 1.2+
- } else if (macAlg == M_SHA384) {
- algorithm = "HmacSHA384"; // TLS 1.2+
- } else {
- throw new RuntimeException("Unknown Mac " + macAlg);
- }
-
- mac = JsseJce.getMac(algorithm);
- mac.init(key);
-
- if (tls) {
- block = new byte[BLOCK_SIZE_TLS];
- block[BLOCK_OFFSET_VERSION] = protocolVersion.major;
- block[BLOCK_OFFSET_VERSION+1] = protocolVersion.minor;
- } else {
- block = new byte[BLOCK_SIZE_SSL];
- }
- }
-
- /**
- * Returns the length of the MAC.
- */
- int MAClen() {
- return macSize;
- }
-
- /**
- * Returns the hash function block length of the MAC alorithm.
- */
- int hashBlockLen() {
- return macAlg.hashBlockSize;
- }
-
- /**
- * Returns the hash function minimal padding length of the MAC alorithm.
- */
- int minimalPaddingLen() {
- return macAlg.minimalPaddingSize;
- }
-
- /**
- * Computes and returns the MAC for the data in this byte array.
- *
- * @param type record type
- * @param buf compressed record on which the MAC is computed
- * @param offset start of compressed record data
- * @param len the size of the compressed record
- * @param isSimulated if true, simulate the the MAC computation
- */
- final byte[] compute(byte type, byte buf[],
- int offset, int len, boolean isSimulated) {
- return compute(type, null, buf, offset, len, isSimulated);
- }
-
- /**
- * Compute and returns the MAC for the remaining data
- * in this ByteBuffer.
- *
- * On return, the bb position == limit, and limit will
- * have not changed.
- *
- * @param type record type
- * @param bb a ByteBuffer in which the position and limit
- * demarcate the data to be MAC'd.
- * @param isSimulated if true, simulate the the MAC computation
- */
- final byte[] compute(byte type, ByteBuffer bb, boolean isSimulated) {
- return compute(type, bb, null, 0, bb.remaining(), isSimulated);
- }
-
- /**
- * Check whether the sequence number is close to wrap
- *
- * Sequence numbers are of type uint64 and may not exceed 2^64-1.
- * Sequence numbers do not wrap. When the sequence number is near
- * to wrap, we need to close the connection immediately.
- */
- final boolean seqNumOverflow() {
- /*
- * Conservatively, we don't allow more records to be generated
- * when there are only 2^8 sequence numbers left.
- */
- return (block != null && mac != null &&
- block[0] == (byte)0xFF && block[1] == (byte)0xFF &&
- block[2] == (byte)0xFF && block[3] == (byte)0xFF &&
- block[4] == (byte)0xFF && block[5] == (byte)0xFF &&
- block[6] == (byte)0xFF);
- }
-
- /*
- * Check whether to renew the sequence number
- *
- * Sequence numbers are of type uint64 and may not exceed 2^64-1.
- * Sequence numbers do not wrap. If a TLS
- * implementation would need to wrap a sequence number, it must
- * renegotiate instead.
- */
- final boolean seqNumIsHuge() {
- /*
- * Conservatively, we should ask for renegotiation when there are
- * only 2^48 sequence numbers left.
- */
- return (block != null && mac != null &&
- block[0] == (byte)0xFF && block[1] == (byte)0xFF);
- }
-
- // increment the sequence number in the block array
- // it is a 64-bit number stored in big-endian format
- private void incrementSequenceNumber() {
- int k = 7;
- while ((k >= 0) && (++block[k] == 0)) {
- k--;
- }
- }
-
- /*
- * Compute based on either buffer type, either bb.position/limit
- * or buf/offset/len.
- */
- private byte[] compute(byte type, ByteBuffer bb, byte[] buf,
- int offset, int len, boolean isSimulated) {
-
- if (macSize == 0) {
- return nullMAC;
- }
-
- // MUST NOT increase the sequence number for a simulated computation.
- if (!isSimulated) {
- block[BLOCK_OFFSET_TYPE] = type;
- block[block.length - 2] = (byte)(len >> 8);
- block[block.length - 1] = (byte)(len );
-
- mac.update(block);
- incrementSequenceNumber();
- }
-
- // content
- if (bb != null) {
- mac.update(bb);
- } else {
- mac.update(buf, offset, len);
- }
-
- return mac.doFinal();
- }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/OutputRecord.java b/ojluni/src/main/java/sun/security/ssl/OutputRecord.java
deleted file mode 100755
index 012816d..0000000
--- a/ojluni/src/main/java/sun/security/ssl/OutputRecord.java
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.nio.*;
-import java.util.Arrays;
-
-import javax.net.ssl.SSLException;
-import sun.misc.HexDumpEncoder;
-
-
-/**
- * SSL 3.0 records, as written to a TCP stream.
- *
- * Each record has a message area that starts out with data supplied by the
- * application. It may grow/shrink due to compression and will be modified
- * in place for mac-ing and encryption.
- *
- * Handshake records have additional needs, notably accumulation of a set
- * of hashes which are used to establish that handshaking was done right.
- * Handshake records usually have several handshake messages each, and we
- * need message-level control over what's hashed.
- *
- * @author David Brownell
- */
-class OutputRecord extends ByteArrayOutputStream implements Record {
-
- private HandshakeHash handshakeHash;
- private int lastHashed;
- private boolean firstMessage;
- final private byte contentType;
-
- // current protocol version, sent as record version
- ProtocolVersion protocolVersion;
-
- // version for the ClientHello message. Only relevant if this is a
- // client handshake record. If set to ProtocolVersion.SSL20Hello,
- // the V3 client hello is converted to V2 format.
- private ProtocolVersion helloVersion;
-
- /* Class and subclass dynamic debugging support */
- static final Debug debug = Debug.getInstance("ssl");
-
- /*
- * Default constructor makes a record supporting the maximum
- * SSL record size. It allocates the header bytes directly.
- *
- * @param type the content type for the record
- */
- OutputRecord(byte type, int size) {
- super(size);
- this.protocolVersion = ProtocolVersion.DEFAULT;
- this.helloVersion = ProtocolVersion.DEFAULT_HELLO;
- firstMessage = true;
- count = headerSize;
- contentType = type;
- lastHashed = count;
- }
-
- OutputRecord(byte type) {
- this(type, recordSize(type));
- }
-
- /**
- * Get the size of the buffer we need for records of the specified
- * type.
- */
- private static int recordSize(byte type) {
- if ((type == ct_change_cipher_spec) || (type == ct_alert)) {
- return maxAlertRecordSize;
- } else {
- return maxRecordSize;
- }
- }
-
- /*
- * Updates the SSL version of this record.
- */
- synchronized void setVersion(ProtocolVersion protocolVersion) {
- this.protocolVersion = protocolVersion;
- }
-
- /*
- * Updates helloVersion of this record.
- */
- synchronized void setHelloVersion(ProtocolVersion helloVersion) {
- this.helloVersion = helloVersion;
- }
-
- /*
- * Reset the record so that it can be refilled, starting
- * immediately after the header.
- */
- public synchronized void reset() {
- super.reset();
- count = headerSize;
- lastHashed = count;
- }
-
- /*
- * For handshaking, we need to be able to hash every byte above the
- * record marking layer. This is where we're guaranteed to see those
- * bytes, so this is where we can hash them.
- */
- void setHandshakeHash(HandshakeHash handshakeHash) {
- assert(contentType == ct_handshake);
- this.handshakeHash = handshakeHash;
- }
-
- /*
- * We hash (the plaintext) on demand. There is one place where
- * we want to access the hash in the middle of a record: client
- * cert message gets hashed, and part of the same record is the
- * client cert verify message which uses that hash. So we track
- * how much of each record we've hashed so far.
- */
- void doHashes() {
- int len = count - lastHashed;
-
- if (len > 0) {
- hashInternal(buf, lastHashed, len);
- lastHashed = count;
- }
- }
-
- /*
- * Need a helper function so we can hash the V2 hello correctly
- */
- private void hashInternal(byte buf [], int offset, int len) {
- if (debug != null && Debug.isOn("data")) {
- try {
- HexDumpEncoder hd = new HexDumpEncoder();
-
- System.out.println("[write] MD5 and SHA1 hashes: len = "
- + len);
- hd.encodeBuffer(new ByteArrayInputStream(buf,
- lastHashed, len), System.out);
- } catch (IOException e) { }
- }
-
- handshakeHash.update(buf, lastHashed, len);
- lastHashed = count;
- }
-
- /*
- * Return true iff the record is empty -- to avoid doing the work
- * of sending empty records over the network.
- */
- boolean isEmpty() {
- return count == headerSize;
- }
-
- /*
- * Return true if the record is of a given alert.
- */
- boolean isAlert(byte description) {
- // An alert is defined with a two bytes struct,
- // {byte level, byte description}, following after the header bytes.
- if (count > (headerSize + 1) && contentType == ct_alert) {
- return buf[headerSize + 1] == description;
- }
-
- return false;
- }
-
- /*
- * Compute the MAC and append it to this record. In case we
- * are automatically flushing a handshake stream, make sure we
- * have hashed the message first.
- */
- void addMAC(MAC signer) throws IOException {
- //
- // when we support compression, hashing can't go here
- // since it'll need to be done on the uncompressed data,
- // and the MAC applies to the compressed data.
- //
- if (contentType == ct_handshake) {
- doHashes();
- }
- if (signer.MAClen() != 0) {
- byte[] hash = signer.compute(contentType, buf,
- headerSize, count - headerSize, false);
- write(hash);
- }
- }
-
- /*
- * Encrypt ... length may grow due to block cipher padding
- */
- void encrypt(CipherBox box) {
- int len = count - headerSize;
- count = headerSize + box.encrypt(buf, headerSize, len);
- }
-
-
- /*
- * Tell how full the buffer is ... for filling it with application or
- * handshake data.
- */
- final int availableDataBytes() {
- int dataSize = count - headerSize;
- return maxDataSize - dataSize;
- }
-
- /*
- * Increases the capacity if necessary to ensure that it can hold
- * at least the number of elements specified by the minimum
- * capacity argument.
- *
- * Note that the increased capacity is only can be used for held
- * record buffer. Please DO NOT update the availableDataBytes()
- * according to the expended buffer capacity.
- *
- * @see availableDataBytes()
- */
- private void ensureCapacity(int minCapacity) {
- // overflow-conscious code
- if (minCapacity > buf.length) {
- buf = Arrays.copyOf(buf, minCapacity);
- }
- }
-
- /*
- * Return the type of SSL record that's buffered here.
- */
- final byte contentType() {
- return contentType;
- }
-
- /*
- * Write the record out on the stream. Note that you must have (in
- * order) compressed the data, appended the MAC, and encrypted it in
- * order for the record to be understood by the other end. (Some of
- * those steps will be null early in handshaking.)
- *
- * Note that this does no locking for the connection, it's required
- * that synchronization be done elsewhere. Also, this does its work
- * in a single low level write, for efficiency.
- */
- void write(OutputStream s, boolean holdRecord,
- ByteArrayOutputStream heldRecordBuffer) throws IOException {
- /*
- * Don't emit content-free records. (Even change cipher spec
- * messages have a byte of data!)
- */
- if (count == headerSize) {
- return;
- }
-
- int length = count - headerSize;
- // "should" really never write more than about 14 Kb...
- if (length < 0) {
- throw new SSLException("output record size too small: "
- + length);
- }
-
- if (debug != null
- && (Debug.isOn("record") || Debug.isOn("handshake"))) {
- if ((debug != null && Debug.isOn("record"))
- || contentType() == ct_change_cipher_spec)
- System.out.println(Thread.currentThread().getName()
- // v3.0/v3.1 ...
- + ", WRITE: " + protocolVersion
- + " " + InputRecord.contentName(contentType())
- + ", length = " + length);
- }
-
- /*
- * If this is the initial ClientHello on this connection and
- * we're not trying to resume a (V3) session then send a V2
- * ClientHello instead so we can detect V2 servers cleanly.
- */
- if (firstMessage && useV2Hello()) {
- byte[] v3Msg = new byte[length - 4];
- System.arraycopy(buf, headerSize + 4, v3Msg, 0, v3Msg.length);
- V3toV2ClientHello(v3Msg);
- handshakeHash.reset();
- lastHashed = 2;
- doHashes();
- if (debug != null && Debug.isOn("record")) {
- System.out.println(
- Thread.currentThread().getName()
- + ", WRITE: SSLv2 client hello message"
- + ", length = " + (count - 2)); // 2 byte SSLv2 header
- }
- } else {
- /*
- * Fill out the header, write it and the message.
- */
- buf[0] = contentType;
- buf[1] = protocolVersion.major;
- buf[2] = protocolVersion.minor;
- buf[3] = (byte)(length >> 8);
- buf[4] = (byte)(length);
- }
- firstMessage = false;
-
- /*
- * The upper levels may want us to delay sending this packet so
- * multiple TLS Records can be sent in one (or more) TCP packets.
- * If so, add this packet to the heldRecordBuffer.
- *
- * NOTE: all writes have been synchronized by upper levels.
- */
- int debugOffset = 0;
- if (holdRecord) {
- /*
- * If holdRecord is true, we must have a heldRecordBuffer.
- *
- * Don't worry about the override of writeBuffer(), because
- * when holdRecord is true, the implementation in this class
- * will be used.
- */
- writeBuffer(heldRecordBuffer, buf, 0, count, debugOffset);
- } else {
- // It's time to send, do we have buffered data?
- // May or may not have a heldRecordBuffer.
- if (heldRecordBuffer != null && heldRecordBuffer.size() > 0) {
- int heldLen = heldRecordBuffer.size();
-
- // Ensure the capacity of this buffer.
- ensureCapacity(count + heldLen);
-
- // Slide everything in the buffer to the right.
- System.arraycopy(buf, 0, buf, heldLen, count);
-
- // Prepend the held record to the buffer.
- System.arraycopy(
- heldRecordBuffer.toByteArray(), 0, buf, 0, heldLen);
- count += heldLen;
-
- // Clear the held buffer.
- heldRecordBuffer.reset();
-
- // The held buffer has been dumped, set the debug dump offset.
- debugOffset = heldLen;
- }
- writeBuffer(s, buf, 0, count, debugOffset);
- }
-
- reset();
- }
-
- /*
- * Actually do the write here. For SSLEngine's HS data,
- * we'll override this method and let it take the appropriate
- * action.
- */
- void writeBuffer(OutputStream s, byte [] buf, int off, int len,
- int debugOffset) throws IOException {
-
- s.write(buf, off, len);
- s.flush();
-
- // Output only the record from the specified debug offset.
- if (debug != null && Debug.isOn("packet")) {
- try {
- HexDumpEncoder hd = new HexDumpEncoder();
- ByteBuffer bb = ByteBuffer.wrap(
- buf, off + debugOffset, len - debugOffset);
-
- System.out.println("[Raw write]: length = " +
- bb.remaining());
- hd.encodeBuffer(bb, System.out);
- } catch (IOException e) { }
- }
- }
-
- /*
- * Return whether the buffer contains a ClientHello message that should
- * be converted to V2 format.
- */
- private boolean useV2Hello() {
- return firstMessage
- && (helloVersion == ProtocolVersion.SSL20Hello)
- && (contentType == ct_handshake)
- && (buf[5] == HandshakeMessage.ht_client_hello)
- && (buf[headerSize + 4+2+32] == 0); // V3 session ID is empty
- }
-
- /*
- * Detect "old" servers which are capable of SSL V2.0 protocol ... for
- * example, Netscape Commerce 1.0 servers. The V3 message is in the
- * header and the bytes passed as parameter. This routine translates
- * the V3 message into an equivalent V2 one.
- *
- * Note that the translation will strip off all hello extensions as
- * SSL V2.0 does not support hello extension.
- */
- private void V3toV2ClientHello(byte v3Msg []) throws SSLException {
- int v3SessionIdLenOffset = 2 + 32; // version + nonce
- int v3SessionIdLen = v3Msg[v3SessionIdLenOffset];
- int v3CipherSpecLenOffset = v3SessionIdLenOffset + 1 + v3SessionIdLen;
- int v3CipherSpecLen = ((v3Msg[v3CipherSpecLenOffset] & 0xff) << 8) +
- (v3Msg[v3CipherSpecLenOffset + 1] & 0xff);
- int cipherSpecs = v3CipherSpecLen / 2; // 2 bytes each in V3
-
- /*
- * Copy over the cipher specs. We don't care about actually translating
- * them for use with an actual V2 server since we only talk V3.
- * Therefore, just copy over the V3 cipher spec values with a leading
- * 0.
- */
- int v3CipherSpecOffset = v3CipherSpecLenOffset + 2; // skip length
- int v2CipherSpecLen = 0;
- count = 11;
- boolean containsRenegoInfoSCSV = false;
- for (int i = 0; i < cipherSpecs; i++) {
- byte byte1, byte2;
-
- byte1 = v3Msg[v3CipherSpecOffset++];
- byte2 = v3Msg[v3CipherSpecOffset++];
- v2CipherSpecLen += V3toV2CipherSuite(byte1, byte2);
- if (!containsRenegoInfoSCSV &&
- byte1 == (byte)0x00 && byte2 == (byte)0xFF) {
- containsRenegoInfoSCSV = true;
- }
- }
-
- if (!containsRenegoInfoSCSV) {
- v2CipherSpecLen += V3toV2CipherSuite((byte)0x00, (byte)0xFF);
- }
-
- /*
- * Build the first part of the V3 record header from the V2 one
- * that's now buffered up. (Lengths are fixed up later).
- */
- buf[2] = HandshakeMessage.ht_client_hello;
- buf[3] = v3Msg[0]; // major version
- buf[4] = v3Msg[1]; // minor version
- buf[5] = (byte)(v2CipherSpecLen >>> 8);
- buf[6] = (byte)v2CipherSpecLen;
- buf[7] = 0;
- buf[8] = 0; // always no session
- buf[9] = 0;
- buf[10] = 32; // nonce length (always 32 in V3)
-
- /*
- * Copy in the nonce.
- */
- System.arraycopy(v3Msg, 2, buf, count, 32);
- count += 32;
-
- /*
- * Set the length of the message.
- */
- count -= 2; // don't include length field itself
- buf[0] = (byte)(count >>> 8);
- buf[0] |= 0x80;
- buf[1] = (byte)(count);
- count += 2;
- }
-
- /*
- * Mappings from V3 cipher suite encodings to their pure V2 equivalents.
- * This is taken from the SSL V3 specification, Appendix E.
- */
- private static int[] V3toV2CipherMap1 =
- {-1, -1, -1, 0x02, 0x01, -1, 0x04, 0x05, -1, 0x06, 0x07};
- private static int[] V3toV2CipherMap3 =
- {-1, -1, -1, 0x80, 0x80, -1, 0x80, 0x80, -1, 0x40, 0xC0};
-
- /*
- * See which matching pure-V2 cipher specs we need to include.
- * We are including these not because we are actually prepared
- * to talk V2 but because the Oracle Web Server insists on receiving
- * at least 1 "pure V2" cipher suite that it supports and returns an
- * illegal_parameter alert unless one is present. Rather than mindlessly
- * claiming to implement all documented pure V2 cipher suites the code below
- * just claims to implement the V2 cipher suite that is "equivalent"
- * in terms of cipher algorithm & exportability with the actual V3 cipher
- * suite that we do support.
- */
- private int V3toV2CipherSuite(byte byte1, byte byte2) {
- buf[count++] = 0;
- buf[count++] = byte1;
- buf[count++] = byte2;
-
- if (((byte2 & 0xff) > 0xA) ||
- (V3toV2CipherMap1[byte2] == -1)) {
- return 3;
- }
-
- buf[count++] = (byte)V3toV2CipherMap1[byte2];
- buf[count++] = 0;
- buf[count++] = (byte)V3toV2CipherMap3[byte2];
-
- return 6;
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/ProtocolList.java b/ojluni/src/main/java/sun/security/ssl/ProtocolList.java
deleted file mode 100755
index a57a9bd..0000000
--- a/ojluni/src/main/java/sun/security/ssl/ProtocolList.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.util.*;
-
-/**
- * A list of ProtocolVersions. Also maintains the list of supported protocols.
- * Instances of this class are immutable. Some member variables are final
- * and can be accessed directly without method accessors.
- *
- * @author Andreas Sterbenz
- * @since 1.4.1
- */
-final class ProtocolList {
-
- // the sorted protocol version list
- private final ArrayList<ProtocolVersion> protocols;
-
- private String[] protocolNames;
-
- // the minimum and maximum ProtocolVersions in this list
- final ProtocolVersion min, max;
-
- // the format for the hello version to use
- final ProtocolVersion helloVersion;
-
- ProtocolList(String[] names) {
- this(convert(names));
- }
-
- ProtocolList(ArrayList<ProtocolVersion> versions) {
- this.protocols = versions;
-
- if ((protocols.size() == 1) &&
- protocols.contains(ProtocolVersion.SSL20Hello)) {
- throw new IllegalArgumentException("SSLv2Hello cannot be " +
- "enabled unless at least one other supported version " +
- "is also enabled.");
- }
-
- if (protocols.size() != 0) {
- Collections.sort(protocols);
- min = protocols.get(0);
- max = protocols.get(protocols.size() - 1);
- helloVersion = protocols.get(0);
- } else {
- min = ProtocolVersion.NONE;
- max = ProtocolVersion.NONE;
- helloVersion = ProtocolVersion.NONE;
- }
- }
-
- private static ArrayList<ProtocolVersion> convert(String[] names) {
- if (names == null) {
- throw new IllegalArgumentException("Protocols may not be null");
- }
-
- ArrayList<ProtocolVersion> versions = new ArrayList<>(3);
- for (int i = 0; i < names.length; i++ ) {
- ProtocolVersion version = ProtocolVersion.valueOf(names[i]);
- if (versions.contains(version) == false) {
- versions.add(version);
- }
- }
-
- return versions;
- }
-
- /**
- * Return whether this list contains the specified protocol version.
- * SSLv2Hello is not a real protocol version we support, we always
- * return false for it.
- */
- boolean contains(ProtocolVersion protocolVersion) {
- if (protocolVersion == ProtocolVersion.SSL20Hello) {
- return false;
- }
- return protocols.contains(protocolVersion);
- }
-
- /**
- * Return a reference to the internal Collection of CipherSuites.
- * The Collection MUST NOT be modified.
- */
- Collection<ProtocolVersion> collection() {
- return protocols;
- }
-
- /**
- * Select a protocol version from the list.
- *
- * Return the lower of the protocol version of that suggested by
- * the <code>protocolVersion</code> and the highest version of this
- * protocol list, or null if no protocol version is available.
- *
- * The method is used by TLS server to negotiated the protocol
- * version between client suggested protocol version in the
- * client hello and protocol versions supported by the server.
- */
- ProtocolVersion selectProtocolVersion(ProtocolVersion protocolVersion) {
- ProtocolVersion selectedVersion = null;
- for (ProtocolVersion pv : protocols) {
- if (pv.v > protocolVersion.v) {
- break; // Safe to break here as this.protocols is sorted
- }
- selectedVersion = pv;
- }
-
- return selectedVersion;
- }
-
- /**
- * Return an array with the names of the ProtocolVersions in this list.
- */
- synchronized String[] toStringArray() {
- if (protocolNames == null) {
- protocolNames = new String[protocols.size()];
- int i = 0;
- for (ProtocolVersion version : protocols) {
- protocolNames[i++] = version.name;
- }
- }
- return protocolNames.clone();
- }
-
- public String toString() {
- return protocols.toString();
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/ProtocolVersion.java b/ojluni/src/main/java/sun/security/ssl/ProtocolVersion.java
deleted file mode 100755
index 77c102a..0000000
--- a/ojluni/src/main/java/sun/security/ssl/ProtocolVersion.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-/**
- * Type safe enum for an SSL/TLS protocol version. Instances are obtained
- * using the static factory methods or by referencing the static members
- * in this class. Member variables are final and can be accessed without
- * accessor methods.
- *
- * There is only ever one instance per supported protocol version, this
- * means == can be used for comparision instead of equals() if desired.
- *
- * Checks for a particular version number should generally take this form:
- *
- * if (protocolVersion.v >= ProtocolVersion.TLS10) {
- * // TLS 1.0 code goes here
- * } else {
- * // SSL 3.0 code here
- * }
- *
- * @author Andreas Sterbenz
- * @since 1.4.1
- */
-public final class ProtocolVersion implements Comparable<ProtocolVersion> {
-
- // The limit of maximum protocol version
- final static int LIMIT_MAX_VALUE = 0xFFFF;
-
- // The limit of minimum protocol version
- final static int LIMIT_MIN_VALUE = 0x0000;
-
- // Dummy protocol version value for invalid SSLSession
- final static ProtocolVersion NONE = new ProtocolVersion(-1, "NONE");
-
- // If enabled, send/ accept SSLv2 hello messages
- final static ProtocolVersion SSL20Hello = new ProtocolVersion(0x0002,
- "SSLv2Hello");
-
- // SSL 3.0
- final static ProtocolVersion SSL30 = new ProtocolVersion(0x0300, "SSLv3");
-
- // TLS 1.0
- final static ProtocolVersion TLS10 = new ProtocolVersion(0x0301, "TLSv1");
-
- // TLS 1.1
- final static ProtocolVersion TLS11 = new ProtocolVersion(0x0302, "TLSv1.1");
-
- // TLS 1.2
- final static ProtocolVersion TLS12 = new ProtocolVersion(0x0303, "TLSv1.2");
-
- private static final boolean FIPS = SunJSSE.isFIPS();
-
- // minimum version we implement (SSL 3.0)
- final static ProtocolVersion MIN = FIPS ? TLS10 : SSL30;
-
- // maximum version we implement (TLS 1.2)
- final static ProtocolVersion MAX = TLS12;
-
- // ProtocolVersion to use by default (TLS 1.0)
- final static ProtocolVersion DEFAULT = TLS10;
-
- // Default version for hello messages (SSLv2Hello)
- final static ProtocolVersion DEFAULT_HELLO = FIPS ? TLS10 : SSL30;
-
- // version in 16 bit MSB format as it appears in records and
- // messages, i.e. 0x0301 for TLS 1.0
- public final int v;
-
- // major and minor version
- public final byte major, minor;
-
- // name used in JSSE (e.g. TLSv1 for TLS 1.0)
- final String name;
-
- // private
- private ProtocolVersion(int v, String name) {
- this.v = v;
- this.name = name;
- major = (byte)(v >>> 8);
- minor = (byte)(v & 0xff);
- }
-
- // private
- private static ProtocolVersion valueOf(int v) {
- if (v == SSL30.v) {
- return SSL30;
- } else if (v == TLS10.v) {
- return TLS10;
- } else if (v == TLS11.v) {
- return TLS11;
- } else if (v == TLS12.v) {
- return TLS12;
- } else if (v == SSL20Hello.v) {
- return SSL20Hello;
- } else {
- int major = (v >>> 8) & 0xff;
- int minor = v & 0xff;
- return new ProtocolVersion(v, "Unknown-" + major + "." + minor);
- }
- }
-
- /**
- * Return a ProtocolVersion with the specified major and minor version
- * numbers. Never throws exceptions.
- */
- public static ProtocolVersion valueOf(int major, int minor) {
- major &= 0xff;
- minor &= 0xff;
- int v = (major << 8) | minor;
- return valueOf(v);
- }
-
- /**
- * Return a ProtocolVersion for the given name.
- *
- * @exception IllegalArgumentException if name is null or does not
- * identify a supported protocol
- */
- static ProtocolVersion valueOf(String name) {
- if (name == null) {
- throw new IllegalArgumentException("Protocol cannot be null");
- }
-
- if (FIPS && (name.equals(SSL30.name) || name.equals(SSL20Hello.name))) {
- throw new IllegalArgumentException
- ("Only TLS 1.0 or later allowed in FIPS mode");
- }
-
- if (name.equals(SSL30.name)) {
- return SSL30;
- } else if (name.equals(TLS10.name)) {
- return TLS10;
- } else if (name.equals(TLS11.name)) {
- return TLS11;
- } else if (name.equals(TLS12.name)) {
- return TLS12;
- } else if (name.equals(SSL20Hello.name)) {
- return SSL20Hello;
- } else {
- throw new IllegalArgumentException(name);
- }
- }
-
- public String toString() {
- return name;
- }
-
- /**
- * Compares this object with the specified object for order.
- */
- public int compareTo(ProtocolVersion protocolVersion) {
- return this.v - protocolVersion.v;
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/RSAClientKeyExchange.java b/ojluni/src/main/java/sun/security/ssl/RSAClientKeyExchange.java
deleted file mode 100755
index f8e501e..0000000
--- a/ojluni/src/main/java/sun/security/ssl/RSAClientKeyExchange.java
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.security.*;
-import java.security.interfaces.*;
-
-import javax.crypto.*;
-import javax.crypto.spec.*;
-
-import javax.net.ssl.*;
-
-import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
-import sun.security.util.KeyUtil;
-
-/**
- * This is the client key exchange message (CLIENT --> SERVER) used with
- * all RSA key exchanges; it holds the RSA-encrypted pre-master secret.
- *
- * The message is encrypted using PKCS #1 block type 02 encryption with the
- * server's public key. The padding and resulting message size is a function
- * of this server's public key modulus size, but the pre-master secret is
- * always exactly 48 bytes.
- *
- */
-final class RSAClientKeyExchange extends HandshakeMessage {
-
- /**
- * The TLS spec says that the version in the RSA premaster secret must
- * be the maximum version supported by the client (i.e. the version it
- * requested in its client hello version). However, we (and other
- * implementations) used to send the active negotiated version. The
- * system property below allows to toggle the behavior.
- */
- private final static String PROP_NAME =
- "com.sun.net.ssl.rsaPreMasterSecretFix";
-
- /*
- * Default is "false" (old behavior) for compatibility reasons in
- * SSLv3/TLSv1. Later protocols (TLSv1.1+) do not use this property.
- */
- private final static boolean rsaPreMasterSecretFix =
- Debug.getBooleanProperty(PROP_NAME, false);
-
- /*
- * The following field values were encrypted with the server's public
- * key (or temp key from server key exchange msg) and are presented
- * here in DECRYPTED form.
- */
- private ProtocolVersion protocolVersion; // preMaster [0,1]
- SecretKey preMaster;
- private byte[] encrypted; // same size as public modulus
-
- /*
- * Client randomly creates a pre-master secret and encrypts it
- * using the server's RSA public key; only the server can decrypt
- * it, using its RSA private key. Result is the same size as the
- * server's public key, and uses PKCS #1 block format 02.
- */
- RSAClientKeyExchange(ProtocolVersion protocolVersion,
- ProtocolVersion maxVersion,
- SecureRandom generator, PublicKey publicKey) throws IOException {
- if (publicKey.getAlgorithm().equals("RSA") == false) {
- throw new SSLKeyException("Public key not of type RSA");
- }
- this.protocolVersion = protocolVersion;
-
- int major, minor;
-
- if (rsaPreMasterSecretFix || maxVersion.v >= ProtocolVersion.TLS11.v) {
- major = maxVersion.major;
- minor = maxVersion.minor;
- } else {
- major = protocolVersion.major;
- minor = protocolVersion.minor;
- }
-
- try {
- String s = ((protocolVersion.v >= ProtocolVersion.TLS12.v) ?
- "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
- KeyGenerator kg = JsseJce.getKeyGenerator(s);
- kg.init(new TlsRsaPremasterSecretParameterSpec(major, minor),
- generator);
- preMaster = kg.generateKey();
-
- Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
- cipher.init(Cipher.WRAP_MODE, publicKey, generator);
- encrypted = cipher.wrap(preMaster);
- } catch (GeneralSecurityException e) {
- throw (SSLKeyException)new SSLKeyException
- ("RSA premaster secret error").initCause(e);
- }
- }
-
- /*
- * Server gets the PKCS #1 (block format 02) data, decrypts
- * it with its private key.
- */
- RSAClientKeyExchange(ProtocolVersion currentVersion,
- ProtocolVersion maxVersion,
- SecureRandom generator, HandshakeInStream input,
- int messageSize, PrivateKey privateKey) throws IOException {
-
- if (privateKey.getAlgorithm().equals("RSA") == false) {
- throw new SSLKeyException("Private key not of type RSA");
- }
-
- if (currentVersion.v >= ProtocolVersion.TLS10.v) {
- encrypted = input.getBytes16();
- } else {
- encrypted = new byte [messageSize];
- if (input.read(encrypted) != messageSize) {
- throw new SSLProtocolException
- ("SSL: read PreMasterSecret: short read");
- }
- }
-
- try {
- Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
- cipher.init(Cipher.UNWRAP_MODE, privateKey);
- preMaster = (SecretKey)cipher.unwrap(encrypted,
- "TlsRsaPremasterSecret", Cipher.SECRET_KEY);
-
- // polish the premaster secret
- preMaster = polishPreMasterSecretKey(currentVersion, maxVersion,
- generator, preMaster, null);
- } catch (Exception e) {
- // polish the premaster secret
- preMaster =
- polishPreMasterSecretKey(currentVersion, maxVersion,
- generator, null, e);
- }
- }
-
- /**
- * To avoid vulnerabilities described by section 7.4.7.1, RFC 5246,
- * treating incorrectly formatted message blocks and/or mismatched
- * version numbers in a manner indistinguishable from correctly
- * formatted RSA blocks.
- *
- * RFC 5246 describes the approach as :
- *
- * 1. Generate a string R of 46 random bytes
- *
- * 2. Decrypt the message to recover the plaintext M
- *
- * 3. If the PKCS#1 padding is not correct, or the length of message
- * M is not exactly 48 bytes:
- * pre_master_secret = ClientHello.client_version || R
- * else If ClientHello.client_version <= TLS 1.0, and version
- * number check is explicitly disabled:
- * pre_master_secret = M
- * else:
- * pre_master_secret = ClientHello.client_version || M[2..47]
- */
- private SecretKey polishPreMasterSecretKey(ProtocolVersion currentVersion,
- ProtocolVersion clientHelloVersion, SecureRandom generator,
- SecretKey secretKey, Exception failoverException) {
-
- this.protocolVersion = clientHelloVersion;
-
- if (failoverException == null && secretKey != null) {
- // check the length
- byte[] encoded = secretKey.getEncoded();
- if (encoded == null) { // unable to get the encoded key
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println(
- "unable to get the plaintext of the premaster secret");
- }
-
- int keySize = KeyUtil.getKeySize(secretKey);
- if (keySize > 0 && keySize != 384) { // 384 = 48 * 8
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println(
- "incorrect length of premaster secret: " +
- (keySize/8));
- }
-
- return generateDummySecret(clientHelloVersion);
- }
-
- // The key size is exactly 48 bytes or not accessible.
- //
- // Conservatively, pass the checking to master secret
- // calculation.
- return secretKey;
- } else if (encoded.length == 48) {
- // check the version
- if (clientHelloVersion.major == encoded[0] &&
- clientHelloVersion.minor == encoded[1]) {
-
- return secretKey;
- } else if (clientHelloVersion.v <= ProtocolVersion.TLS10.v &&
- currentVersion.major == encoded[0] &&
- currentVersion.minor == encoded[1]) {
- /*
- * For compatibility, we maintain the behavior that the
- * version in pre_master_secret can be the negotiated
- * version for TLS v1.0 and SSL v3.0.
- */
- this.protocolVersion = currentVersion;
- return secretKey;
- }
-
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println("Mismatching Protocol Versions, " +
- "ClientHello.client_version is " + clientHelloVersion +
- ", while PreMasterSecret.client_version is " +
- ProtocolVersion.valueOf(encoded[0], encoded[1]));
- }
-
- return generateDummySecret(clientHelloVersion);
- } else {
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println(
- "incorrect length of premaster secret: " +
- encoded.length);
- }
-
- return generateDummySecret(clientHelloVersion);
- }
- }
-
- if (debug != null && Debug.isOn("handshake") &&
- failoverException != null) {
- System.out.println("Error decrypting premaster secret:");
- failoverException.printStackTrace(System.out);
- }
-
- return generateDummySecret(clientHelloVersion);
- }
-
- // generate a premaster secret with the specified version number
- static SecretKey generateDummySecret(ProtocolVersion version) {
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println("Generating a random fake premaster secret");
- }
-
- try {
- String s = ((version.v >= ProtocolVersion.TLS12.v) ?
- "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
- KeyGenerator kg = JsseJce.getKeyGenerator(s);
- kg.init(new TlsRsaPremasterSecretParameterSpec
- (version.major, version.minor));
- return kg.generateKey();
- } catch (GeneralSecurityException e) {
- throw new RuntimeException("Could not generate dummy secret", e);
- }
- }
-
- @Override
- int messageType() {
- return ht_client_key_exchange;
- }
-
- @Override
- int messageLength() {
- if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
- return encrypted.length + 2;
- } else {
- return encrypted.length;
- }
- }
-
- @Override
- void send(HandshakeOutStream s) throws IOException {
- if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
- s.putBytes16(encrypted);
- } else {
- s.write(encrypted);
- }
- }
-
- @Override
- void print(PrintStream s) throws IOException {
- s.println("*** ClientKeyExchange, RSA PreMasterSecret, " +
- protocolVersion);
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/RSASignature.java b/ojluni/src/main/java/sun/security/ssl/RSASignature.java
deleted file mode 100755
index 5b97bed..0000000
--- a/ojluni/src/main/java/sun/security/ssl/RSASignature.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.util.Arrays;
-
-import java.security.*;
-
-/**
- * Signature implementation for the SSL/TLS RSA Signature variant with both
- * MD5 and SHA-1 MessageDigests. Used for explicit RSA server authentication
- * (RSA signed server key exchange for RSA_EXPORT and DHE_RSA) and RSA client
- * authentication (RSA signed certificate verify message).
- *
- * It conforms to the standard JCA Signature API. It is registered in the
- * SunJSSE provider to avoid more complicated getInstance() code and
- * negative interaction with the JCA mechanisms for hardware providers.
- *
- * The class should be instantiated via the getInstance() method in this class,
- * which returns the implementation from the prefered provider. The internal
- * implementation allows the hashes to be explicitly set, which is required
- * for RSA client authentication. It can be obtained via the
- * getInternalInstance() method.
- *
- * This class is not thread safe.
- *
- */
-public final class RSASignature extends SignatureSpi {
-
- private final Signature rawRsa;
- private MessageDigest md5, sha;
-
- // flag indicating if the MessageDigests are in reset state
- private boolean isReset;
-
- public RSASignature() throws NoSuchAlgorithmException {
- super();
- rawRsa = JsseJce.getSignature(JsseJce.SIGNATURE_RAWRSA);
- isReset = true;
- }
-
- /**
- * Get an implementation for the RSA signature. Follows the standard
- * JCA getInstance() model, so it return the implementation from the
- * provider with the highest precedence, which may be this class.
- */
- static Signature getInstance() throws NoSuchAlgorithmException {
- return JsseJce.getSignature(JsseJce.SIGNATURE_SSLRSA);
- }
-
- /**
- * Get an internal implementation for the RSA signature. Used for RSA
- * client authentication, which needs the ability to set the digests
- * to externally provided values via the setHashes() method.
- */
- static Signature getInternalInstance()
- throws NoSuchAlgorithmException, NoSuchProviderException {
- return Signature.getInstance(JsseJce.SIGNATURE_SSLRSA, "SunJSSE");
- }
-
- /**
- * Set the MD5 and SHA hashes to the provided objects.
- */
- static void setHashes(Signature sig, MessageDigest md5, MessageDigest sha) {
- sig.setParameter("hashes", new MessageDigest[] {md5, sha});
- }
-
- /**
- * Reset the MessageDigests unless they are already reset.
- */
- private void reset() {
- if (isReset == false) {
- md5.reset();
- sha.reset();
- isReset = true;
- }
- }
-
- private static void checkNull(Key key) throws InvalidKeyException {
- if (key == null) {
- throw new InvalidKeyException("Key must not be null");
- }
- }
-
- protected void engineInitVerify(PublicKey publicKey)
- throws InvalidKeyException {
- checkNull(publicKey);
- reset();
- rawRsa.initVerify(publicKey);
- }
-
- protected void engineInitSign(PrivateKey privateKey)
- throws InvalidKeyException {
- engineInitSign(privateKey, null);
- }
-
- protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
- throws InvalidKeyException {
- checkNull(privateKey);
- reset();
- rawRsa.initSign(privateKey, random);
- }
-
- // lazily initialize the MessageDigests
- private void initDigests() {
- if (md5 == null) {
- md5 = JsseJce.getMD5();
- sha = JsseJce.getSHA();
- }
- }
-
- protected void engineUpdate(byte b) {
- initDigests();
- isReset = false;
- md5.update(b);
- sha.update(b);
- }
-
- protected void engineUpdate(byte[] b, int off, int len) {
- initDigests();
- isReset = false;
- md5.update(b, off, len);
- sha.update(b, off, len);
- }
-
- private byte[] getDigest() throws SignatureException {
- try {
- initDigests();
- byte[] data = new byte[36];
- md5.digest(data, 0, 16);
- sha.digest(data, 16, 20);
- isReset = true;
- return data;
- } catch (DigestException e) {
- // should never occur
- throw new SignatureException(e);
- }
- }
-
- protected byte[] engineSign() throws SignatureException {
- rawRsa.update(getDigest());
- return rawRsa.sign();
- }
-
- protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
- return engineVerify(sigBytes, 0, sigBytes.length);
- }
-
- protected boolean engineVerify(byte[] sigBytes, int offset, int length)
- throws SignatureException {
- rawRsa.update(getDigest());
- return rawRsa.verify(sigBytes, offset, length);
- }
-
- protected void engineSetParameter(String param, Object value)
- throws InvalidParameterException {
- if (param.equals("hashes") == false) {
- throw new InvalidParameterException
- ("Parameter not supported: " + param);
- }
- if (value instanceof MessageDigest[] == false) {
- throw new InvalidParameterException
- ("value must be MessageDigest[]");
- }
- MessageDigest[] digests = (MessageDigest[])value;
- md5 = digests[0];
- sha = digests[1];
- }
-
- protected Object engineGetParameter(String param)
- throws InvalidParameterException {
- throw new InvalidParameterException("Parameters not supported");
- }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/RandomCookie.java b/ojluni/src/main/java/sun/security/ssl/RandomCookie.java
deleted file mode 100755
index 5f414c4..0000000
--- a/ojluni/src/main/java/sun/security/ssl/RandomCookie.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.security.SecureRandom;
-
-/*
- * RandomCookie ... SSL hands standard format random cookies (nonces)
- * around. These know how to encode/decode themselves on SSL streams,
- * and can be created and printed.
- *
- * @author David Brownell
- */
-final class RandomCookie {
-
- byte random_bytes[]; // exactly 32 bytes
-
- RandomCookie(SecureRandom generator) {
- long temp = System.currentTimeMillis() / 1000;
- int gmt_unix_time;
- if (temp < Integer.MAX_VALUE) {
- gmt_unix_time = (int) temp;
- } else {
- gmt_unix_time = Integer.MAX_VALUE; // Whoops!
- }
-
- random_bytes = new byte[32];
- generator.nextBytes(random_bytes);
-
- random_bytes[0] = (byte)(gmt_unix_time >> 24);
- random_bytes[1] = (byte)(gmt_unix_time >> 16);
- random_bytes[2] = (byte)(gmt_unix_time >> 8);
- random_bytes[3] = (byte)gmt_unix_time;
- }
-
- RandomCookie(HandshakeInStream m) throws IOException {
- random_bytes = new byte[32];
- m.read(random_bytes, 0, 32);
- }
-
- void send(HandshakeOutStream out) throws IOException {
- out.write(random_bytes, 0, 32);
- }
-
- void print(PrintStream s) {
- int i, gmt_unix_time;
-
- gmt_unix_time = random_bytes[0] << 24;
- gmt_unix_time += random_bytes[1] << 16;
- gmt_unix_time += random_bytes[2] << 8;
- gmt_unix_time += random_bytes[3];
-
- s.print("GMT: " + gmt_unix_time + " ");
- s.print("bytes = { ");
-
- for (i = 4; i < 32; i++) {
- if (i != 4) {
- s.print(", ");
- }
- s.print(random_bytes[i] & 0x0ff);
- }
- s.println(" }");
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/Record.java b/ojluni/src/main/java/sun/security/ssl/Record.java
deleted file mode 100755
index 0494d9a..0000000
--- a/ojluni/src/main/java/sun/security/ssl/Record.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-
-/**
- * SSL/TLS records, as pulled off (and put onto) a TCP stream. This is
- * the base interface, which defines common information and interfaces
- * used by both Input and Output records.
- *
- * @author David Brownell
- */
-interface Record {
- /*
- * There are four SSL record types, which are part of the interface
- * to this level (along with the maximum record size)
- *
- * enum { change_cipher_spec(20), alert(21), handshake(22),
- * application_data(23), (255) } ContentType;
- */
- static final byte ct_change_cipher_spec = 20;
- static final byte ct_alert = 21;
- static final byte ct_handshake = 22;
- static final byte ct_application_data = 23;
-
- static final int headerSize = 5; // SSLv3 record header
- static final int maxExpansion = 1024; // for bad compression
- static final int trailerSize = 20; // SHA1 hash size
- static final int maxDataSize = 16384; // 2^14 bytes of data
- static final int maxPadding = 256; // block cipher padding
- static final int maxIVLength = 256; // block length
-
- /*
- * SSL has a maximum record size. It's header, (compressed) data,
- * padding, and a trailer for the MAC.
- * Some compression algorithms have rare cases where they expand the data.
- * As we don't support compression at this time, leave that out.
- */
- static final int maxRecordSize =
- headerSize // header
- + maxIVLength // iv
- + maxDataSize // data
- + maxPadding // padding
- + trailerSize; // MAC
-
- static final boolean enableCBCProtection =
- Debug.getBooleanProperty("jsse.enableCBCProtection", true);
-
- /*
- * For CBC protection in SSL3/TLS1, we break some plaintext into two
- * packets. Max application data size for the second packet.
- */
- static final int maxDataSizeMinusOneByteRecord =
- maxDataSize // max data size
- - ( // max one byte record size
- headerSize // header
- + maxIVLength // iv
- + 1 // one byte data
- + maxPadding // padding
- + trailerSize // MAC
- );
-
- /*
- * The maximum large record size.
- *
- * Some SSL/TLS implementations support large fragment upto 2^15 bytes,
- * such as Microsoft. We support large incoming fragments.
- *
- * The maximum large record size is defined as maxRecordSize plus 2^14,
- * this is the amount OpenSSL is using.
- */
- static final int maxLargeRecordSize =
- maxRecordSize // Max size with a conforming implemenation
- + maxDataSize; // extra 2^14 bytes for large data packets.
-
-
- /*
- * Maximum record size for alert and change cipher spec records.
- * They only contain 2 and 1 bytes of data, respectively.
- * Allocate a smaller array.
- */
- static final int maxAlertRecordSize =
- headerSize // header
- + maxIVLength // iv
- + 2 // alert
- + maxPadding // padding
- + trailerSize; // MAC
-
- /*
- * The overflow values of integers of 8, 16 and 24 bits.
- */
- static final int OVERFLOW_OF_INT08 = (1 << 8);
- static final int OVERFLOW_OF_INT16 = (1 << 16);
- static final int OVERFLOW_OF_INT24 = (1 << 24);
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLAlgorithmConstraints.java b/ojluni/src/main/java/sun/security/ssl/SSLAlgorithmConstraints.java
deleted file mode 100755
index 3980705..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLAlgorithmConstraints.java
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.security.AlgorithmConstraints;
-import java.security.CryptoPrimitive;
-import java.security.AlgorithmParameters;
-
-import javax.net.ssl.*;
-
-import java.security.Key;
-
-import java.util.Set;
-import java.util.HashSet;
-
-import sun.security.util.DisabledAlgorithmConstraints;
-import sun.security.ssl.CipherSuite.*;
-
-/**
- * Algorithm constraints for disabled algorithms property
- *
- * See the "jdk.certpath.disabledAlgorithms" specification in java.security
- * for the syntax of the disabled algorithm string.
- */
-final class SSLAlgorithmConstraints implements AlgorithmConstraints {
- private final static AlgorithmConstraints tlsDisabledAlgConstraints =
- new TLSDisabledAlgConstraints();
- private final static AlgorithmConstraints x509DisabledAlgConstraints =
- new X509DisabledAlgConstraints();
- private AlgorithmConstraints userAlgConstraints = null;
- private AlgorithmConstraints peerAlgConstraints = null;
-
- private boolean enabledX509DisabledAlgConstraints = true;
-
- SSLAlgorithmConstraints(AlgorithmConstraints algorithmConstraints) {
- userAlgConstraints = algorithmConstraints;
- }
-
- SSLAlgorithmConstraints(SSLSocket socket,
- boolean withDefaultCertPathConstraints) {
- if (socket != null) {
- userAlgConstraints =
- socket.getSSLParameters().getAlgorithmConstraints();
- }
-
- if (!withDefaultCertPathConstraints) {
- enabledX509DisabledAlgConstraints = false;
- }
- }
-
- SSLAlgorithmConstraints(SSLEngine engine,
- boolean withDefaultCertPathConstraints) {
- if (engine != null) {
- userAlgConstraints =
- engine.getSSLParameters().getAlgorithmConstraints();
- }
-
- if (!withDefaultCertPathConstraints) {
- enabledX509DisabledAlgConstraints = false;
- }
- }
-
- SSLAlgorithmConstraints(SSLSocket socket, String[] supportedAlgorithms,
- boolean withDefaultCertPathConstraints) {
- if (socket != null) {
- userAlgConstraints =
- socket.getSSLParameters().getAlgorithmConstraints();
- peerAlgConstraints =
- new SupportedSignatureAlgorithmConstraints(supportedAlgorithms);
- }
-
- if (!withDefaultCertPathConstraints) {
- enabledX509DisabledAlgConstraints = false;
- }
- }
-
- SSLAlgorithmConstraints(SSLEngine engine, String[] supportedAlgorithms,
- boolean withDefaultCertPathConstraints) {
- if (engine != null) {
- userAlgConstraints =
- engine.getSSLParameters().getAlgorithmConstraints();
- peerAlgConstraints =
- new SupportedSignatureAlgorithmConstraints(supportedAlgorithms);
- }
-
- if (!withDefaultCertPathConstraints) {
- enabledX509DisabledAlgConstraints = false;
- }
- }
-
- public boolean permits(Set<CryptoPrimitive> primitives,
- String algorithm, AlgorithmParameters parameters) {
-
- boolean permitted = true;
-
- if (peerAlgConstraints != null) {
- permitted = peerAlgConstraints.permits(
- primitives, algorithm, parameters);
- }
-
- if (permitted && userAlgConstraints != null) {
- permitted = userAlgConstraints.permits(
- primitives, algorithm, parameters);
- }
-
- if (permitted) {
- permitted = tlsDisabledAlgConstraints.permits(
- primitives, algorithm, parameters);
- }
-
- if (permitted && enabledX509DisabledAlgConstraints) {
- permitted = x509DisabledAlgConstraints.permits(
- primitives, algorithm, parameters);
- }
-
- return permitted;
- }
-
- public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
-
- boolean permitted = true;
-
- if (peerAlgConstraints != null) {
- permitted = peerAlgConstraints.permits(primitives, key);
- }
-
- if (permitted && userAlgConstraints != null) {
- permitted = userAlgConstraints.permits(primitives, key);
- }
-
- if (permitted) {
- permitted = tlsDisabledAlgConstraints.permits(primitives, key);
- }
-
- if (permitted && enabledX509DisabledAlgConstraints) {
- permitted = x509DisabledAlgConstraints.permits(primitives, key);
- }
-
- return permitted;
- }
-
- public boolean permits(Set<CryptoPrimitive> primitives,
- String algorithm, Key key, AlgorithmParameters parameters) {
-
- boolean permitted = true;
-
- if (peerAlgConstraints != null) {
- permitted = peerAlgConstraints.permits(
- primitives, algorithm, key, parameters);
- }
-
- if (permitted && userAlgConstraints != null) {
- permitted = userAlgConstraints.permits(
- primitives, algorithm, key, parameters);
- }
-
- if (permitted) {
- permitted = tlsDisabledAlgConstraints.permits(
- primitives, algorithm, key, parameters);
- }
-
- if (permitted && enabledX509DisabledAlgConstraints) {
- permitted = x509DisabledAlgConstraints.permits(
- primitives, algorithm, key, parameters);
- }
-
- return permitted;
- }
-
-
- static private class SupportedSignatureAlgorithmConstraints
- implements AlgorithmConstraints {
- // supported signature algorithms
- private String[] supportedAlgorithms;
-
- SupportedSignatureAlgorithmConstraints(String[] supportedAlgorithms) {
- if (supportedAlgorithms != null) {
- this.supportedAlgorithms = supportedAlgorithms.clone();
- } else {
- this.supportedAlgorithms = null;
- }
- }
-
- public boolean permits(Set<CryptoPrimitive> primitives,
- String algorithm, AlgorithmParameters parameters) {
-
- if (algorithm == null || algorithm.length() == 0) {
- throw new IllegalArgumentException(
- "No algorithm name specified");
- }
-
- if (primitives == null || primitives.isEmpty()) {
- throw new IllegalArgumentException(
- "No cryptographic primitive specified");
- }
-
- if (supportedAlgorithms == null ||
- supportedAlgorithms.length == 0) {
- return false;
- }
-
- // trim the MGF part: <digest>with<encryption>and<mgf>
- int position = algorithm.indexOf("and");
- if (position > 0) {
- algorithm = algorithm.substring(0, position);
- }
-
- for (String supportedAlgorithm : supportedAlgorithms) {
- if (algorithm.equalsIgnoreCase(supportedAlgorithm)) {
- return true;
- }
- }
-
- return false;
- }
-
- final public boolean permits(Set<CryptoPrimitive> primitives, Key key) {
- return true;
- }
-
- final public boolean permits(Set<CryptoPrimitive> primitives,
- String algorithm, Key key, AlgorithmParameters parameters) {
-
- if (algorithm == null || algorithm.length() == 0) {
- throw new IllegalArgumentException(
- "No algorithm name specified");
- }
-
- return permits(primitives, algorithm, parameters);
- }
- }
-
- static private class BasicDisabledAlgConstraints
- extends DisabledAlgorithmConstraints {
- BasicDisabledAlgConstraints(String propertyName) {
- super(propertyName);
- }
-
- protected Set<String> decomposes(KeyExchange keyExchange,
- boolean forCertPathOnly) {
- Set<String> components = new HashSet<>();
- switch (keyExchange) {
- case K_NULL:
- if (!forCertPathOnly) {
- components.add("NULL");
- }
- break;
- case K_RSA:
- components.add("RSA");
- break;
- case K_RSA_EXPORT:
- components.add("RSA");
- components.add("RSA_EXPORT");
- break;
- case K_DH_RSA:
- components.add("RSA");
- components.add("DH");
- components.add("DiffieHellman");
- components.add("DH_RSA");
- break;
- case K_DH_DSS:
- components.add("DSA");
- components.add("DSS");
- components.add("DH");
- components.add("DiffieHellman");
- components.add("DH_DSS");
- break;
- case K_DHE_DSS:
- components.add("DSA");
- components.add("DSS");
- components.add("DH");
- components.add("DHE");
- components.add("DiffieHellman");
- components.add("DHE_DSS");
- break;
- case K_DHE_RSA:
- components.add("RSA");
- components.add("DH");
- components.add("DHE");
- components.add("DiffieHellman");
- components.add("DHE_RSA");
- break;
- case K_DH_ANON:
- if (!forCertPathOnly) {
- components.add("ANON");
- components.add("DH");
- components.add("DiffieHellman");
- components.add("DH_ANON");
- }
- break;
- case K_ECDH_ECDSA:
- components.add("ECDH");
- components.add("ECDSA");
- components.add("ECDH_ECDSA");
- break;
- case K_ECDH_RSA:
- components.add("ECDH");
- components.add("RSA");
- components.add("ECDH_RSA");
- break;
- case K_ECDHE_ECDSA:
- components.add("ECDHE");
- components.add("ECDSA");
- components.add("ECDHE_ECDSA");
- break;
- case K_ECDHE_RSA:
- components.add("ECDHE");
- components.add("RSA");
- components.add("ECDHE_RSA");
- break;
- case K_ECDH_ANON:
- if (!forCertPathOnly) {
- components.add("ECDH");
- components.add("ANON");
- components.add("ECDH_ANON");
- }
- break;
- case K_KRB5:
- if (!forCertPathOnly) {
- components.add("KRB5");
- }
- break;
- case K_KRB5_EXPORT:
- if (!forCertPathOnly) {
- components.add("KRB5_EXPORT");
- }
- break;
- default:
- // ignore
- }
-
- return components;
- }
-
- protected Set<String> decomposes(BulkCipher bulkCipher) {
- Set<String> components = new HashSet<>();
-
- if (bulkCipher.transformation != null) {
- components.addAll(super.decomposes(bulkCipher.transformation));
- }
-
- return components;
- }
-
- protected Set<String> decomposes(MacAlg macAlg) {
- Set<String> components = new HashSet<>();
-
- if (macAlg == CipherSuite.M_MD5) {
- components.add("MD5");
- components.add("HmacMD5");
- } else if (macAlg == CipherSuite.M_SHA) {
- components.add("SHA1");
- components.add("SHA-1");
- components.add("HmacSHA1");
- } else if (macAlg == CipherSuite.M_SHA256) {
- components.add("SHA256");
- components.add("SHA-256");
- components.add("HmacSHA256");
- } else if (macAlg == CipherSuite.M_SHA384) {
- components.add("SHA384");
- components.add("SHA-384");
- components.add("HmacSHA384");
- }
-
- return components;
- }
- }
-
- static private class TLSDisabledAlgConstraints
- extends BasicDisabledAlgConstraints {
-
- TLSDisabledAlgConstraints() {
- super(DisabledAlgorithmConstraints.PROPERTY_TLS_DISABLED_ALGS);
- }
-
- @Override
- protected Set<String> decomposes(String algorithm) {
- if (algorithm.startsWith("SSL_") || algorithm.startsWith("TLS_")) {
- CipherSuite cipherSuite = null;
- try {
- cipherSuite = CipherSuite.valueOf(algorithm);
- } catch (IllegalArgumentException iae) {
- // ignore: unknown or unsupported ciphersuite
- }
-
- if (cipherSuite != null) {
- Set<String> components = new HashSet<>();
-
- if(cipherSuite.keyExchange != null) {
- components.addAll(
- decomposes(cipherSuite.keyExchange, false));
- }
-
- if (cipherSuite.cipher != null) {
- components.addAll(decomposes(cipherSuite.cipher));
- }
-
- if (cipherSuite.macAlg != null) {
- components.addAll(decomposes(cipherSuite.macAlg));
- }
-
- return components;
- }
- }
-
- return super.decomposes(algorithm);
- }
- }
-
- static private class X509DisabledAlgConstraints
- extends BasicDisabledAlgConstraints {
-
- X509DisabledAlgConstraints() {
- super(DisabledAlgorithmConstraints.PROPERTY_CERTPATH_DISABLED_ALGS);
- }
-
- @Override
- protected Set<String> decomposes(String algorithm) {
- if (algorithm.startsWith("SSL_") || algorithm.startsWith("TLS_")) {
- CipherSuite cipherSuite = null;
- try {
- cipherSuite = CipherSuite.valueOf(algorithm);
- } catch (IllegalArgumentException iae) {
- // ignore: unknown or unsupported ciphersuite
- }
-
- if (cipherSuite != null) {
- Set<String> components = new HashSet<>();
-
- if(cipherSuite.keyExchange != null) {
- components.addAll(
- decomposes(cipherSuite.keyExchange, true));
- }
-
- // Certification path algorithm constraints do not apply
- // to cipherSuite.cipher and cipherSuite.macAlg.
-
- return components;
- }
- }
-
- return super.decomposes(algorithm);
- }
- }
-}
-
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLContextImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLContextImpl.java
deleted file mode 100755
index c2081b7..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLContextImpl.java
+++ /dev/null
@@ -1,1162 +0,0 @@
-/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.net.Socket;
-
-import java.io.*;
-import java.util.*;
-import java.security.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-
-import javax.net.ssl.*;
-
-import sun.security.provider.certpath.AlgorithmChecker;
-
-public abstract class SSLContextImpl extends SSLContextSpi {
-
- private static final Debug debug = Debug.getInstance("ssl");
-
- private final EphemeralKeyManager ephemeralKeyManager;
- private final SSLSessionContextImpl clientCache;
- private final SSLSessionContextImpl serverCache;
-
- private boolean isInitialized;
-
- private X509ExtendedKeyManager keyManager;
- private X509TrustManager trustManager;
- private SecureRandom secureRandom;
-
- // The default algrithm constraints
- private AlgorithmConstraints defaultAlgorithmConstraints =
- new SSLAlgorithmConstraints(null);
-
- // supported and default protocols
- private ProtocolList defaultServerProtocolList;
- private ProtocolList defaultClientProtocolList;
- private ProtocolList supportedProtocolList;
-
- // supported and default cipher suites
- private CipherSuiteList defaultServerCipherSuiteList;
- private CipherSuiteList defaultClientCipherSuiteList;
- private CipherSuiteList supportedCipherSuiteList;
-
- SSLContextImpl() {
- ephemeralKeyManager = new EphemeralKeyManager();
- clientCache = new SSLSessionContextImpl();
- serverCache = new SSLSessionContextImpl();
- }
-
- protected void engineInit(KeyManager[] km, TrustManager[] tm,
- SecureRandom sr) throws KeyManagementException {
- isInitialized = false;
- keyManager = chooseKeyManager(km);
-
- if (tm == null) {
- try {
- TrustManagerFactory tmf = TrustManagerFactory.getInstance(
- TrustManagerFactory.getDefaultAlgorithm());
- tmf.init((KeyStore)null);
- tm = tmf.getTrustManagers();
- } catch (Exception e) {
- // eat
- }
- }
- trustManager = chooseTrustManager(tm);
-
- if (sr == null) {
- secureRandom = JsseJce.getSecureRandom();
- } else {
- if (SunJSSE.isFIPS() &&
- (sr.getProvider() != SunJSSE.cryptoProvider)) {
- throw new KeyManagementException
- ("FIPS mode: SecureRandom must be from provider "
- + SunJSSE.cryptoProvider.getName());
- }
- secureRandom = sr;
- }
-
- /*
- * The initial delay of seeding the random number generator
- * could be long enough to cause the initial handshake on our
- * first connection to timeout and fail. Make sure it is
- * primed and ready by getting some initial output from it.
- */
- if (debug != null && Debug.isOn("sslctx")) {
- System.out.println("trigger seeding of SecureRandom");
- }
- secureRandom.nextInt();
- if (debug != null && Debug.isOn("sslctx")) {
- System.out.println("done seeding SecureRandom");
- }
- isInitialized = true;
- }
-
- private X509TrustManager chooseTrustManager(TrustManager[] tm)
- throws KeyManagementException {
- // We only use the first instance of X509TrustManager passed to us.
- for (int i = 0; tm != null && i < tm.length; i++) {
- if (tm[i] instanceof X509TrustManager) {
- if (SunJSSE.isFIPS() &&
- !(tm[i] instanceof X509TrustManagerImpl)) {
- throw new KeyManagementException
- ("FIPS mode: only SunJSSE TrustManagers may be used");
- }
-
- if (tm[i] instanceof X509ExtendedTrustManager) {
- return (X509TrustManager)tm[i];
- } else {
- return new AbstractTrustManagerWrapper(
- (X509TrustManager)tm[i]);
- }
- }
- }
-
- // nothing found, return a dummy X509TrustManager.
- return DummyX509TrustManager.INSTANCE;
- }
-
- private X509ExtendedKeyManager chooseKeyManager(KeyManager[] kms)
- throws KeyManagementException {
- for (int i = 0; kms != null && i < kms.length; i++) {
- KeyManager km = kms[i];
- if (!(km instanceof X509KeyManager)) {
- continue;
- }
- if (SunJSSE.isFIPS()) {
- // In FIPS mode, require that one of SunJSSE's own keymanagers
- // is used. Otherwise, we cannot be sure that only keys from
- // the FIPS token are used.
- if ((km instanceof X509KeyManagerImpl)
- || (km instanceof SunX509KeyManagerImpl)) {
- return (X509ExtendedKeyManager)km;
- } else {
- // throw exception, we don't want to silently use the
- // dummy keymanager without telling the user.
- throw new KeyManagementException
- ("FIPS mode: only SunJSSE KeyManagers may be used");
- }
- }
- if (km instanceof X509ExtendedKeyManager) {
- return (X509ExtendedKeyManager)km;
- }
- if (debug != null && Debug.isOn("sslctx")) {
- System.out.println(
- "X509KeyManager passed to " +
- "SSLContext.init(): need an " +
- "X509ExtendedKeyManager for SSLEngine use");
- }
- return new AbstractKeyManagerWrapper((X509KeyManager)km);
- }
-
- // nothing found, return a dummy X509ExtendedKeyManager
- return DummyX509KeyManager.INSTANCE;
- }
-
- protected SSLSocketFactory engineGetSocketFactory() {
- if (!isInitialized) {
- throw new IllegalStateException(
- "SSLContextImpl is not initialized");
- }
- return new SSLSocketFactoryImpl(this);
- }
-
- protected SSLServerSocketFactory engineGetServerSocketFactory() {
- if (!isInitialized) {
- throw new IllegalStateException("SSLContext is not initialized");
- }
- return new SSLServerSocketFactoryImpl(this);
- }
-
- protected SSLEngine engineCreateSSLEngine() {
- if (!isInitialized) {
- throw new IllegalStateException(
- "SSLContextImpl is not initialized");
- }
- return new SSLEngineImpl(this);
- }
-
- protected SSLEngine engineCreateSSLEngine(String host, int port) {
- if (!isInitialized) {
- throw new IllegalStateException(
- "SSLContextImpl is not initialized");
- }
- return new SSLEngineImpl(this, host, port);
- }
-
- protected SSLSessionContext engineGetClientSessionContext() {
- return clientCache;
- }
-
- protected SSLSessionContext engineGetServerSessionContext() {
- return serverCache;
- }
-
- SecureRandom getSecureRandom() {
- return secureRandom;
- }
-
- X509ExtendedKeyManager getX509KeyManager() {
- return keyManager;
- }
-
- X509TrustManager getX509TrustManager() {
- return trustManager;
- }
-
- EphemeralKeyManager getEphemeralKeyManager() {
- return ephemeralKeyManager;
- }
-
- abstract SSLParameters getDefaultServerSSLParams();
- abstract SSLParameters getDefaultClientSSLParams();
- abstract SSLParameters getSupportedSSLParams();
-
- // Get suported ProtoclList.
- ProtocolList getSuportedProtocolList() {
- if (supportedProtocolList == null) {
- supportedProtocolList =
- new ProtocolList(getSupportedSSLParams().getProtocols());
- }
-
- return supportedProtocolList;
- }
-
- // Get default ProtoclList.
- ProtocolList getDefaultProtocolList(boolean roleIsServer) {
- if (roleIsServer) {
- if (defaultServerProtocolList == null) {
- defaultServerProtocolList = new ProtocolList(
- getDefaultServerSSLParams().getProtocols());
- }
-
- return defaultServerProtocolList;
- } else {
- if (defaultClientProtocolList == null) {
- defaultClientProtocolList = new ProtocolList(
- getDefaultClientSSLParams().getProtocols());
- }
-
- return defaultClientProtocolList;
- }
- }
-
- // Get suported CipherSuiteList.
- CipherSuiteList getSupportedCipherSuiteList() {
- // The maintenance of cipher suites needs to be synchronized.
- synchronized (this) {
- // Clear cache of available ciphersuites.
- clearAvailableCache();
-
- if (supportedCipherSuiteList == null) {
- supportedCipherSuiteList = getApplicableCipherSuiteList(
- getSuportedProtocolList(), false);
- }
-
- return supportedCipherSuiteList;
- }
- }
-
- // Get default CipherSuiteList.
- CipherSuiteList getDefaultCipherSuiteList(boolean roleIsServer) {
- // The maintenance of cipher suites needs to be synchronized.
- synchronized (this) {
- // Clear cache of available ciphersuites.
- clearAvailableCache();
-
- if (roleIsServer) {
- if (defaultServerCipherSuiteList == null) {
- defaultServerCipherSuiteList = getApplicableCipherSuiteList(
- getDefaultProtocolList(true), true);
- }
-
- return defaultServerCipherSuiteList;
- } else {
- if (defaultClientCipherSuiteList == null) {
- defaultClientCipherSuiteList = getApplicableCipherSuiteList(
- getDefaultProtocolList(false), true);
- }
-
- return defaultClientCipherSuiteList;
- }
- }
- }
-
- /**
- * Return whether a protocol list is the original default enabled
- * protocols. See: SSLSocket/SSLEngine.setEnabledProtocols()
- */
- boolean isDefaultProtocolList(ProtocolList protocols) {
- return (protocols == defaultServerProtocolList) ||
- (protocols == defaultClientProtocolList);
- }
-
-
- /*
- * Return the list of all available CipherSuites with a priority of
- * minPriority or above.
- */
- private CipherSuiteList getApplicableCipherSuiteList(
- ProtocolList protocols, boolean onlyEnabled) {
-
- int minPriority = CipherSuite.SUPPORTED_SUITES_PRIORITY;
- if (onlyEnabled) {
- minPriority = CipherSuite.DEFAULT_SUITES_PRIORITY;
- }
-
- Collection<CipherSuite> allowedCipherSuites =
- CipherSuite.allowedCipherSuites();
-
- TreeSet<CipherSuite> suites = new TreeSet<>();
- if (!(protocols.collection().isEmpty()) &&
- protocols.min.v != ProtocolVersion.NONE.v) {
- for (CipherSuite suite : allowedCipherSuites) {
- if (!suite.allowed || suite.priority < minPriority) {
- continue;
- }
-
- if (suite.isAvailable() &&
- suite.obsoleted > protocols.min.v &&
- suite.supported <= protocols.max.v) {
- if (defaultAlgorithmConstraints.permits(
- EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
- suite.name, null)) {
- suites.add(suite);
- }
- } else if (debug != null &&
- Debug.isOn("sslctx") && Debug.isOn("verbose")) {
- if (suite.obsoleted <= protocols.min.v) {
- System.out.println(
- "Ignoring obsoleted cipher suite: " + suite);
- } else if (suite.supported > protocols.max.v) {
- System.out.println(
- "Ignoring unsupported cipher suite: " + suite);
- } else {
- System.out.println(
- "Ignoring unavailable cipher suite: " + suite);
- }
- }
- }
- }
-
- return new CipherSuiteList(suites);
- }
-
- /**
- * Clear cache of available ciphersuites. If we support all ciphers
- * internally, there is no need to clear the cache and calling this
- * method has no effect.
- *
- * Note that every call to clearAvailableCache() and the maintenance of
- * cipher suites need to be synchronized with this instance.
- */
- private void clearAvailableCache() {
- if (CipherSuite.DYNAMIC_AVAILABILITY) {
- supportedCipherSuiteList = null;
- defaultServerCipherSuiteList = null;
- defaultClientCipherSuiteList = null;
- CipherSuite.BulkCipher.clearAvailableCache();
- JsseJce.clearEcAvailable();
- }
- }
-
- /*
- * The SSLContext implementation for TLS/SSL algorithm
- *
- * SSL/TLS protocols specify the forward compatibility and version
- * roll-back attack protections, however, a number of SSL/TLS server
- * vendors did not implement these aspects properly, and some current
- * SSL/TLS servers may refuse to talk to a TLS 1.1 or later client.
- *
- * Considering above interoperability issues, SunJSSE will not set
- * TLS 1.1 and TLS 1.2 as the enabled protocols for client by default.
- *
- * For SSL/TLS servers, there is no such interoperability issues as
- * SSL/TLS clients. In SunJSSE, TLS 1.1 or later version will be the
- * enabled protocols for server by default.
- *
- * We may change the behavior when popular TLS/SSL vendors support TLS
- * forward compatibility properly.
- *
- * SSLv2Hello is no longer necessary. This interoperability option was
- * put in place in the late 90's when SSLv3/TLS1.0 were relatively new
- * and there were a fair number of SSLv2-only servers deployed. Because
- * of the security issues in SSLv2, it is rarely (if ever) used, as
- * deployments should now be using SSLv3 and TLSv1.
- *
- * Considering the issues of SSLv2Hello, we should not enable SSLv2Hello
- * by default. Applications still can use it by enabling SSLv2Hello with
- * the series of setEnabledProtocols APIs.
- */
-
- /*
- * The conservative SSLContext implementation for TLS, SSL, SSLv3 and
- * TLS10 algorithm.
- *
- * This is a super class of DefaultSSLContext and TLS10Context.
- *
- * @see SSLContext
- */
- private static class ConservativeSSLContext extends SSLContextImpl {
- // parameters
- private static SSLParameters defaultServerSSLParams;
- private static SSLParameters defaultClientSSLParams;
- private static SSLParameters supportedSSLParams;
-
- static {
- if (SunJSSE.isFIPS()) {
- supportedSSLParams = new SSLParameters();
- supportedSSLParams.setProtocols(new String[] {
- ProtocolVersion.TLS10.name,
- ProtocolVersion.TLS11.name,
- ProtocolVersion.TLS12.name
- });
-
- defaultServerSSLParams = supportedSSLParams;
-
- defaultClientSSLParams = new SSLParameters();
- defaultClientSSLParams.setProtocols(new String[] {
- ProtocolVersion.TLS10.name
- });
-
- } else {
- supportedSSLParams = new SSLParameters();
- supportedSSLParams.setProtocols(new String[] {
- ProtocolVersion.SSL20Hello.name,
- ProtocolVersion.SSL30.name,
- ProtocolVersion.TLS10.name,
- ProtocolVersion.TLS11.name,
- ProtocolVersion.TLS12.name
- });
-
- defaultServerSSLParams = supportedSSLParams;
-
- defaultClientSSLParams = new SSLParameters();
- defaultClientSSLParams.setProtocols(new String[] {
- ProtocolVersion.SSL30.name,
- ProtocolVersion.TLS10.name
- });
- }
- }
-
- SSLParameters getDefaultServerSSLParams() {
- return defaultServerSSLParams;
- }
-
- SSLParameters getDefaultClientSSLParams() {
- return defaultClientSSLParams;
- }
-
- SSLParameters getSupportedSSLParams() {
- return supportedSSLParams;
- }
- }
-
- /*
- * The SSLContext implementation for default algorithm
- *
- * @see SSLContext
- */
- public static final class DefaultSSLContext extends ConservativeSSLContext {
- private static final String NONE = "NONE";
- private static final String P11KEYSTORE = "PKCS11";
-
- private static volatile SSLContextImpl defaultImpl;
-
- private static TrustManager[] defaultTrustManagers;
- private static KeyManager[] defaultKeyManagers;
-
- public DefaultSSLContext() throws Exception {
- try {
- super.engineInit(getDefaultKeyManager(),
- getDefaultTrustManager(), null);
- } catch (Exception e) {
- if (debug != null && Debug.isOn("defaultctx")) {
- System.out.println("default context init failed: " + e);
- }
- throw e;
- }
-
- if (defaultImpl == null) {
- defaultImpl = this;
- }
- }
-
- protected void engineInit(KeyManager[] km, TrustManager[] tm,
- SecureRandom sr) throws KeyManagementException {
- throw new KeyManagementException
- ("Default SSLContext is initialized automatically");
- }
-
- static synchronized SSLContextImpl getDefaultImpl() throws Exception {
- if (defaultImpl == null) {
- new DefaultSSLContext();
- }
- return defaultImpl;
- }
-
- private static synchronized TrustManager[] getDefaultTrustManager()
- throws Exception {
- if (defaultTrustManagers != null) {
- return defaultTrustManagers;
- }
-
- KeyStore ks =
- TrustManagerFactoryImpl.getCacertsKeyStore("defaultctx");
-
- TrustManagerFactory tmf = TrustManagerFactory.getInstance(
- TrustManagerFactory.getDefaultAlgorithm());
- tmf.init(ks);
- defaultTrustManagers = tmf.getTrustManagers();
- return defaultTrustManagers;
- }
-
- private static synchronized KeyManager[] getDefaultKeyManager()
- throws Exception {
- if (defaultKeyManagers != null) {
- return defaultKeyManagers;
- }
-
- final Map<String,String> props = new HashMap<>();
- AccessController.doPrivileged(
- new PrivilegedExceptionAction<Object>() {
- public Object run() throws Exception {
- props.put("keyStore", System.getProperty(
- "javax.net.ssl.keyStore", ""));
- props.put("keyStoreType", System.getProperty(
- "javax.net.ssl.keyStoreType",
- KeyStore.getDefaultType()));
- props.put("keyStoreProvider", System.getProperty(
- "javax.net.ssl.keyStoreProvider", ""));
- props.put("keyStorePasswd", System.getProperty(
- "javax.net.ssl.keyStorePassword", ""));
- return null;
- }
- });
-
- final String defaultKeyStore = props.get("keyStore");
- String defaultKeyStoreType = props.get("keyStoreType");
- String defaultKeyStoreProvider = props.get("keyStoreProvider");
- if (debug != null && Debug.isOn("defaultctx")) {
- System.out.println("keyStore is : " + defaultKeyStore);
- System.out.println("keyStore type is : " +
- defaultKeyStoreType);
- System.out.println("keyStore provider is : " +
- defaultKeyStoreProvider);
- }
-
- if (P11KEYSTORE.equals(defaultKeyStoreType) &&
- !NONE.equals(defaultKeyStore)) {
- throw new IllegalArgumentException("if keyStoreType is "
- + P11KEYSTORE + ", then keyStore must be " + NONE);
- }
-
- FileInputStream fs = null;
- if (defaultKeyStore.length() != 0 && !NONE.equals(defaultKeyStore)) {
- fs = AccessController.doPrivileged(
- new PrivilegedExceptionAction<FileInputStream>() {
- public FileInputStream run() throws Exception {
- return new FileInputStream(defaultKeyStore);
- }
- });
- }
-
- String defaultKeyStorePassword = props.get("keyStorePasswd");
- char[] passwd = null;
- if (defaultKeyStorePassword.length() != 0) {
- passwd = defaultKeyStorePassword.toCharArray();
- }
-
- /**
- * Try to initialize key store.
- */
- KeyStore ks = null;
- if ((defaultKeyStoreType.length()) != 0) {
- if (debug != null && Debug.isOn("defaultctx")) {
- System.out.println("init keystore");
- }
- if (defaultKeyStoreProvider.length() == 0) {
- ks = KeyStore.getInstance(defaultKeyStoreType);
- } else {
- ks = KeyStore.getInstance(defaultKeyStoreType,
- defaultKeyStoreProvider);
- }
-
- // if defaultKeyStore is NONE, fs will be null
- ks.load(fs, passwd);
- }
- if (fs != null) {
- fs.close();
- fs = null;
- }
-
- /*
- * Try to initialize key manager.
- */
- if (debug != null && Debug.isOn("defaultctx")) {
- System.out.println("init keymanager of type " +
- KeyManagerFactory.getDefaultAlgorithm());
- }
- KeyManagerFactory kmf = KeyManagerFactory.getInstance(
- KeyManagerFactory.getDefaultAlgorithm());
-
- if (P11KEYSTORE.equals(defaultKeyStoreType)) {
- kmf.init(ks, null); // do not pass key passwd if using token
- } else {
- kmf.init(ks, passwd);
- }
-
- defaultKeyManagers = kmf.getKeyManagers();
- return defaultKeyManagers;
- }
- }
-
- /*
- * The SSLContext implementation for TLS, SSL, SSLv3 and TLS10 algorithm
- *
- * @see SSLContext
- */
- public static final class TLS10Context extends ConservativeSSLContext {
- // use the default constructor and methods
- }
-
- /*
- * The SSLContext implementation for TLS11 algorithm
- *
- * @see SSLContext
- */
- public static final class TLS11Context extends SSLContextImpl {
- // parameters
- private static SSLParameters defaultServerSSLParams;
- private static SSLParameters defaultClientSSLParams;
- private static SSLParameters supportedSSLParams;
-
- static {
- if (SunJSSE.isFIPS()) {
- supportedSSLParams = new SSLParameters();
- supportedSSLParams.setProtocols(new String[] {
- ProtocolVersion.TLS10.name,
- ProtocolVersion.TLS11.name,
- ProtocolVersion.TLS12.name
- });
-
- defaultServerSSLParams = supportedSSLParams;
-
- defaultClientSSLParams = new SSLParameters();
- defaultClientSSLParams.setProtocols(new String[] {
- ProtocolVersion.TLS10.name,
- ProtocolVersion.TLS11.name
- });
-
- } else {
- supportedSSLParams = new SSLParameters();
- supportedSSLParams.setProtocols(new String[] {
- ProtocolVersion.SSL20Hello.name,
- ProtocolVersion.SSL30.name,
- ProtocolVersion.TLS10.name,
- ProtocolVersion.TLS11.name,
- ProtocolVersion.TLS12.name
- });
-
- defaultServerSSLParams = supportedSSLParams;
-
- defaultClientSSLParams = new SSLParameters();
- defaultClientSSLParams.setProtocols(new String[] {
- ProtocolVersion.SSL30.name,
- ProtocolVersion.TLS10.name,
- ProtocolVersion.TLS11.name
- });
- }
- }
-
- SSLParameters getDefaultServerSSLParams() {
- return defaultServerSSLParams;
- }
-
- SSLParameters getDefaultClientSSLParams() {
- return defaultClientSSLParams;
- }
-
- SSLParameters getSupportedSSLParams() {
- return supportedSSLParams;
- }
- }
-
- /*
- * The SSLContext implementation for TLS12 algorithm
- *
- * @see SSLContext
- */
- public static final class TLS12Context extends SSLContextImpl {
- // parameters
- private static SSLParameters defaultServerSSLParams;
- private static SSLParameters defaultClientSSLParams;
- private static SSLParameters supportedSSLParams;
-
- static {
- if (SunJSSE.isFIPS()) {
- supportedSSLParams = new SSLParameters();
- supportedSSLParams.setProtocols(new String[] {
- ProtocolVersion.TLS10.name,
- ProtocolVersion.TLS11.name,
- ProtocolVersion.TLS12.name
- });
-
- defaultServerSSLParams = supportedSSLParams;
-
- defaultClientSSLParams = new SSLParameters();
- defaultClientSSLParams.setProtocols(new String[] {
- ProtocolVersion.TLS10.name,
- ProtocolVersion.TLS11.name,
- ProtocolVersion.TLS12.name
- });
-
- } else {
- supportedSSLParams = new SSLParameters();
- supportedSSLParams.setProtocols(new String[] {
- ProtocolVersion.SSL20Hello.name,
- ProtocolVersion.SSL30.name,
- ProtocolVersion.TLS10.name,
- ProtocolVersion.TLS11.name,
- ProtocolVersion.TLS12.name
- });
-
- defaultServerSSLParams = supportedSSLParams;
-
- defaultClientSSLParams = new SSLParameters();
- defaultClientSSLParams.setProtocols(new String[] {
- ProtocolVersion.SSL30.name,
- ProtocolVersion.TLS10.name,
- ProtocolVersion.TLS11.name,
- ProtocolVersion.TLS12.name
- });
- }
- }
-
- SSLParameters getDefaultServerSSLParams() {
- return defaultServerSSLParams;
- }
-
- SSLParameters getDefaultClientSSLParams() {
- return defaultClientSSLParams;
- }
-
- SSLParameters getSupportedSSLParams() {
- return supportedSSLParams;
- }
- }
-
-}
-
-
-final class AbstractTrustManagerWrapper extends X509ExtendedTrustManager
- implements X509TrustManager {
-
- // the delegated trust manager
- private final X509TrustManager tm;
-
- AbstractTrustManagerWrapper(X509TrustManager tm) {
- this.tm = tm;
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] chain, String authType)
- throws CertificateException {
- tm.checkClientTrusted(chain, authType);
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] chain, String authType)
- throws CertificateException {
- tm.checkServerTrusted(chain, authType);
- }
-
- @Override
- public X509Certificate[] getAcceptedIssuers() {
- return tm.getAcceptedIssuers();
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] chain, String authType,
- Socket socket) throws CertificateException {
- tm.checkClientTrusted(chain, authType);
- checkAdditionalTrust(chain, authType, socket, true);
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] chain, String authType,
- Socket socket) throws CertificateException {
- tm.checkServerTrusted(chain, authType);
- checkAdditionalTrust(chain, authType, socket, false);
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] chain, String authType,
- SSLEngine engine) throws CertificateException {
- tm.checkClientTrusted(chain, authType);
- checkAdditionalTrust(chain, authType, engine, true);
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] chain, String authType,
- SSLEngine engine) throws CertificateException {
- tm.checkServerTrusted(chain, authType);
- checkAdditionalTrust(chain, authType, engine, false);
- }
-
- private void checkAdditionalTrust(X509Certificate[] chain, String authType,
- Socket socket, boolean isClient) throws CertificateException {
- if (socket != null && socket.isConnected() &&
- socket instanceof SSLSocket) {
-
- SSLSocket sslSocket = (SSLSocket)socket;
- SSLSession session = sslSocket.getHandshakeSession();
- if (session == null) {
- throw new CertificateException("No handshake session");
- }
-
- // check endpoint identity
- String identityAlg = sslSocket.getSSLParameters().
- getEndpointIdentificationAlgorithm();
- if (identityAlg != null && identityAlg.length() != 0) {
- String hostname = session.getPeerHost();
- X509TrustManagerImpl.checkIdentity(
- hostname, chain[0], identityAlg);
- }
-
- // try the best to check the algorithm constraints
- ProtocolVersion protocolVersion =
- ProtocolVersion.valueOf(session.getProtocol());
- AlgorithmConstraints constraints = null;
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- if (session instanceof ExtendedSSLSession) {
- ExtendedSSLSession extSession =
- (ExtendedSSLSession)session;
- String[] peerSupportedSignAlgs =
- extSession.getLocalSupportedSignatureAlgorithms();
-
- constraints = new SSLAlgorithmConstraints(
- sslSocket, peerSupportedSignAlgs, true);
- } else {
- constraints =
- new SSLAlgorithmConstraints(sslSocket, true);
- }
- } else {
- constraints = new SSLAlgorithmConstraints(sslSocket, true);
- }
-
- checkAlgorithmConstraints(chain, constraints);
- }
- }
-
- private void checkAdditionalTrust(X509Certificate[] chain, String authType,
- SSLEngine engine, boolean isClient) throws CertificateException {
- if (engine != null) {
- SSLSession session = engine.getHandshakeSession();
- if (session == null) {
- throw new CertificateException("No handshake session");
- }
-
- // check endpoint identity
- String identityAlg = engine.getSSLParameters().
- getEndpointIdentificationAlgorithm();
- if (identityAlg != null && identityAlg.length() != 0) {
- String hostname = session.getPeerHost();
- X509TrustManagerImpl.checkIdentity(
- hostname, chain[0], identityAlg);
- }
-
- // try the best to check the algorithm constraints
- ProtocolVersion protocolVersion =
- ProtocolVersion.valueOf(session.getProtocol());
- AlgorithmConstraints constraints = null;
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- if (session instanceof ExtendedSSLSession) {
- ExtendedSSLSession extSession =
- (ExtendedSSLSession)session;
- String[] peerSupportedSignAlgs =
- extSession.getLocalSupportedSignatureAlgorithms();
-
- constraints = new SSLAlgorithmConstraints(
- engine, peerSupportedSignAlgs, true);
- } else {
- constraints =
- new SSLAlgorithmConstraints(engine, true);
- }
- } else {
- constraints = new SSLAlgorithmConstraints(engine, true);
- }
-
- checkAlgorithmConstraints(chain, constraints);
- }
- }
-
- private void checkAlgorithmConstraints(X509Certificate[] chain,
- AlgorithmConstraints constraints) throws CertificateException {
-
- try {
- // Does the certificate chain end with a trusted certificate?
- int checkedLength = chain.length - 1;
-
- Collection<X509Certificate> trustedCerts = new HashSet<>();
- X509Certificate[] certs = tm.getAcceptedIssuers();
- if ((certs != null) && (certs.length > 0)){
- Collections.addAll(trustedCerts, certs);
- }
-
- if (trustedCerts.contains(chain[checkedLength])) {
- checkedLength--;
- }
-
- // A forward checker, need to check from trust to target
- if (checkedLength >= 0) {
- AlgorithmChecker checker = new AlgorithmChecker(constraints);
- checker.init(false);
- for (int i = checkedLength; i >= 0; i--) {
- Certificate cert = chain[i];
- // We don't care about the unresolved critical extensions.
- checker.check(cert, Collections.<String>emptySet());
- }
- }
- } catch (CertPathValidatorException cpve) {
- throw new CertificateException(
- "Certificates does not conform to algorithm constraints");
- }
- }
-}
-
-// Dummy X509TrustManager implementation, rejects all peer certificates.
-// Used if the application did not specify a proper X509TrustManager.
-final class DummyX509TrustManager extends X509ExtendedTrustManager
- implements X509TrustManager {
-
- static final X509TrustManager INSTANCE = new DummyX509TrustManager();
-
- private DummyX509TrustManager() {
- // empty
- }
-
- /*
- * Given the partial or complete certificate chain
- * provided by the peer, build a certificate path
- * to a trusted root and return if it can be
- * validated and is trusted for client SSL authentication.
- * If not, it throws an exception.
- */
- @Override
- public void checkClientTrusted(X509Certificate[] chain, String authType)
- throws CertificateException {
- throw new CertificateException(
- "No X509TrustManager implementation avaiable");
- }
-
- /*
- * Given the partial or complete certificate chain
- * provided by the peer, build a certificate path
- * to a trusted root and return if it can be
- * validated and is trusted for server SSL authentication.
- * If not, it throws an exception.
- */
- @Override
- public void checkServerTrusted(X509Certificate[] chain, String authType)
- throws CertificateException {
- throw new CertificateException(
- "No X509TrustManager implementation available");
- }
-
- /*
- * Return an array of issuer certificates which are trusted
- * for authenticating peers.
- */
- @Override
- public X509Certificate[] getAcceptedIssuers() {
- return new X509Certificate[0];
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] chain, String authType,
- Socket socket) throws CertificateException {
- throw new CertificateException(
- "No X509TrustManager implementation available");
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] chain, String authType,
- Socket socket) throws CertificateException {
- throw new CertificateException(
- "No X509TrustManager implementation available");
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] chain, String authType,
- SSLEngine engine) throws CertificateException {
- throw new CertificateException(
- "No X509TrustManager implementation available");
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] chain, String authType,
- SSLEngine engine) throws CertificateException {
- throw new CertificateException(
- "No X509TrustManager implementation available");
- }
-}
-
-/*
- * A wrapper class to turn a X509KeyManager into an X509ExtendedKeyManager
- */
-final class AbstractKeyManagerWrapper extends X509ExtendedKeyManager {
-
- private final X509KeyManager km;
-
- AbstractKeyManagerWrapper(X509KeyManager km) {
- this.km = km;
- }
-
- public String[] getClientAliases(String keyType, Principal[] issuers) {
- return km.getClientAliases(keyType, issuers);
- }
-
- public String chooseClientAlias(String[] keyType, Principal[] issuers,
- Socket socket) {
- return km.chooseClientAlias(keyType, issuers, socket);
- }
-
- public String[] getServerAliases(String keyType, Principal[] issuers) {
- return km.getServerAliases(keyType, issuers);
- }
-
- public String chooseServerAlias(String keyType, Principal[] issuers,
- Socket socket) {
- return km.chooseServerAlias(keyType, issuers, socket);
- }
-
- public X509Certificate[] getCertificateChain(String alias) {
- return km.getCertificateChain(alias);
- }
-
- public PrivateKey getPrivateKey(String alias) {
- return km.getPrivateKey(alias);
- }
-
- // Inherit chooseEngineClientAlias() and chooseEngineServerAlias() from
- // X509ExtendedKeymanager. It defines them to return null;
-}
-
-
-// Dummy X509KeyManager implementation, never returns any certificates/keys.
-// Used if the application did not specify a proper X509TrustManager.
-final class DummyX509KeyManager extends X509ExtendedKeyManager {
-
- static final X509ExtendedKeyManager INSTANCE = new DummyX509KeyManager();
-
- private DummyX509KeyManager() {
- // empty
- }
-
- /*
- * Get the matching aliases for authenticating the client side of a secure
- * socket given the public key type and the list of
- * certificate issuer authorities recognized by the peer (if any).
- */
- public String[] getClientAliases(String keyType, Principal[] issuers) {
- return null;
- }
-
- /*
- * Choose an alias to authenticate the client side of a secure
- * socket given the public key type and the list of
- * certificate issuer authorities recognized by the peer (if any).
- */
- public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
- Socket socket) {
- return null;
- }
-
- /*
- * Choose an alias to authenticate the client side of an
- * engine given the public key type and the list of
- * certificate issuer authorities recognized by the peer (if any).
- */
- public String chooseEngineClientAlias(
- String[] keyTypes, Principal[] issuers, SSLEngine engine) {
- return null;
- }
-
- /*
- * Get the matching aliases for authenticating the server side of a secure
- * socket given the public key type and the list of
- * certificate issuer authorities recognized by the peer (if any).
- */
- public String[] getServerAliases(String keyType, Principal[] issuers) {
- return null;
- }
-
- /*
- * Choose an alias to authenticate the server side of a secure
- * socket given the public key type and the list of
- * certificate issuer authorities recognized by the peer (if any).
- */
- public String chooseServerAlias(String keyType, Principal[] issuers,
- Socket socket) {
- return null;
- }
-
- /*
- * Choose an alias to authenticate the server side of an engine
- * given the public key type and the list of
- * certificate issuer authorities recognized by the peer (if any).
- */
- public String chooseEngineServerAlias(
- String keyType, Principal[] issuers, SSLEngine engine) {
- return null;
- }
-
- /**
- * Returns the certificate chain associated with the given alias.
- *
- * @param alias the alias name
- *
- * @return the certificate chain (ordered with the user's certificate first
- * and the root certificate authority last)
- */
- public X509Certificate[] getCertificateChain(String alias) {
- return null;
- }
-
- /*
- * Returns the key associated with the given alias, using the given
- * password to recover it.
- *
- * @param alias the alias name
- *
- * @return the requested key
- */
- public PrivateKey getPrivateKey(String alias) {
- return null;
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLEngineImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLEngineImpl.java
deleted file mode 100755
index afcbd51..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLEngineImpl.java
+++ /dev/null
@@ -1,2087 +0,0 @@
-/*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.nio.*;
-import java.nio.ReadOnlyBufferException;
-import java.util.LinkedList;
-import java.security.*;
-
-import javax.crypto.BadPaddingException;
-
-import javax.net.ssl.*;
-import javax.net.ssl.SSLEngineResult.*;
-
-import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
-
-/**
- * Implementation of an non-blocking SSLEngine.
- *
- * *Currently*, the SSLEngine code exists in parallel with the current
- * SSLSocket. As such, the current implementation is using legacy code
- * with many of the same abstractions. However, it varies in many
- * areas, most dramatically in the IO handling.
- *
- * There are three main I/O threads that can be existing in parallel:
- * wrap(), unwrap(), and beginHandshake(). We are encouraging users to
- * not call multiple instances of wrap or unwrap, because the data could
- * appear to flow out of the SSLEngine in a non-sequential order. We
- * take all steps we can to at least make sure the ordering remains
- * consistent, but once the calls returns, anything can happen. For
- * example, thread1 and thread2 both call wrap, thread1 gets the first
- * packet, thread2 gets the second packet, but thread2 gets control back
- * before thread1, and sends the data. The receiving side would see an
- * out-of-order error.
- *
- * Handshaking is still done the same way as SSLSocket using the normal
- * InputStream/OutputStream abstactions. We create
- * ClientHandshakers/ServerHandshakers, which produce/consume the
- * handshaking data. The transfer of the data is largely handled by the
- * HandshakeInStream/HandshakeOutStreams. Lastly, the
- * InputRecord/OutputRecords still have the same functionality, except
- * that they are overridden with EngineInputRecord/EngineOutputRecord,
- * which provide SSLEngine-specific functionality.
- *
- * Some of the major differences are:
- *
- * EngineInputRecord/EngineOutputRecord/EngineWriter:
- *
- * In order to avoid writing whole new control flows for
- * handshaking, and to reuse most of the same code, we kept most
- * of the actual handshake code the same. As usual, reading
- * handshake data may trigger output of more handshake data, so
- * what we do is write this data to internal buffers, and wait for
- * wrap() to be called to give that data a ride.
- *
- * All data is routed through
- * EngineInputRecord/EngineOutputRecord. However, all handshake
- * data (ct_alert/ct_change_cipher_spec/ct_handshake) are passed
- * through to the the underlying InputRecord/OutputRecord, and
- * the data uses the internal buffers.
- *
- * Application data is handled slightly different, we copy the data
- * directly from the src to the dst buffers, and do all operations
- * on those buffers, saving the overhead of multiple copies.
- *
- * In the case of an inbound record, unwrap passes the inbound
- * ByteBuffer to the InputRecord. If the data is handshake data,
- * the data is read into the InputRecord's internal buffer. If
- * the data is application data, the data is decoded directly into
- * the dst buffer.
- *
- * In the case of an outbound record, when the write to the
- * "real" OutputStream's would normally take place, instead we
- * call back up to the EngineOutputRecord's version of
- * writeBuffer, at which time we capture the resulting output in a
- * ByteBuffer, and send that back to the EngineWriter for internal
- * storage.
- *
- * EngineWriter is responsible for "handling" all outbound
- * data, be it handshake or app data, and for returning the data
- * to wrap() in the proper order.
- *
- * ClientHandshaker/ServerHandshaker/Handshaker:
- * Methods which relied on SSLSocket now have work on either
- * SSLSockets or SSLEngines.
- *
- * @author Brad Wetmore
- */
-final public class SSLEngineImpl extends SSLEngine {
-
- //
- // Fields and global comments
- //
-
- /*
- * There's a state machine associated with each connection, which
- * among other roles serves to negotiate session changes.
- *
- * - START with constructor, until the TCP connection's around.
- * - HANDSHAKE picks session parameters before allowing traffic.
- * There are many substates due to sequencing requirements
- * for handshake messages.
- * - DATA may be transmitted.
- * - RENEGOTIATE state allows concurrent data and handshaking
- * traffic ("same" substates as HANDSHAKE), and terminates
- * in selection of new session (and connection) parameters
- * - ERROR state immediately precedes abortive disconnect.
- * - CLOSED when one side closes down, used to start the shutdown
- * process. SSL connection objects are not reused.
- *
- * State affects what SSL record types may legally be sent:
- *
- * - Handshake ... only in HANDSHAKE and RENEGOTIATE states
- * - App Data ... only in DATA and RENEGOTIATE states
- * - Alert ... in HANDSHAKE, DATA, RENEGOTIATE
- *
- * Re what may be received: same as what may be sent, except that
- * HandshakeRequest handshaking messages can come from servers even
- * in the application data state, to request entry to RENEGOTIATE.
- *
- * The state machine within HANDSHAKE and RENEGOTIATE states controls
- * the pending session, not the connection state, until the change
- * cipher spec and "Finished" handshake messages are processed and
- * make the "new" session become the current one.
- *
- * NOTE: details of the SMs always need to be nailed down better.
- * The text above illustrates the core ideas.
- *
- * +---->-------+------>--------->-------+
- * | | |
- * <-----< ^ ^ <-----< |
- *START>----->HANDSHAKE>----->DATA>----->RENEGOTIATE |
- * v v v |
- * | | | |
- * +------------+---------------+ |
- * | |
- * v |
- * ERROR>------>----->CLOSED<--------<----+
- *
- * ALSO, note that the the purpose of handshaking (renegotiation is
- * included) is to assign a different, and perhaps new, session to
- * the connection. The SSLv3 spec is a bit confusing on that new
- * protocol feature.
- */
- private int connectionState;
-
- private static final int cs_START = 0;
- private static final int cs_HANDSHAKE = 1;
- private static final int cs_DATA = 2;
- private static final int cs_RENEGOTIATE = 3;
- private static final int cs_ERROR = 4;
- private static final int cs_CLOSED = 6;
-
- /*
- * Once we're in state cs_CLOSED, we can continue to
- * wrap/unwrap until we finish sending/receiving the messages
- * for close_notify. EngineWriter handles outboundDone.
- */
- private boolean inboundDone = false;
-
- EngineWriter writer;
-
- /*
- * The authentication context holds all information used to establish
- * who this end of the connection is (certificate chains, private keys,
- * etc) and who is trusted (e.g. as CAs or websites).
- */
- private SSLContextImpl sslContext;
-
- /*
- * This connection is one of (potentially) many associated with
- * any given session. The output of the handshake protocol is a
- * new session ... although all the protocol description talks
- * about changing the cipher spec (and it does change), in fact
- * that's incidental since it's done by changing everything that
- * is associated with a session at the same time. (TLS/IETF may
- * change that to add client authentication w/o new key exchg.)
- */
- private Handshaker handshaker;
- private SSLSessionImpl sess;
- private volatile SSLSessionImpl handshakeSession;
-
-
- /*
- * Client authentication be off, requested, or required.
- *
- * This will be used by both this class and SSLSocket's variants.
- */
- static final byte clauth_none = 0;
- static final byte clauth_requested = 1;
- static final byte clauth_required = 2;
-
- /*
- * Flag indicating if the next record we receive MUST be a Finished
- * message. Temporarily set during the handshake to ensure that
- * a change cipher spec message is followed by a finished message.
- */
- private boolean expectingFinished;
-
-
- /*
- * If someone tries to closeInbound() (say at End-Of-Stream)
- * our engine having received a close_notify, we need to
- * notify the app that we may have a truncation attack underway.
- */
- private boolean recvCN;
-
- /*
- * For improved diagnostics, we detail connection closure
- * If the engine is closed (connectionState >= cs_ERROR),
- * closeReason != null indicates if the engine was closed
- * because of an error or because or normal shutdown.
- */
- private SSLException closeReason;
-
- /*
- * Per-connection private state that doesn't change when the
- * session is changed.
- */
- private byte doClientAuth;
- private boolean enableSessionCreation = true;
- EngineInputRecord inputRecord;
- EngineOutputRecord outputRecord;
- private AccessControlContext acc;
-
- // The cipher suites enabled for use on this connection.
- private CipherSuiteList enabledCipherSuites;
-
- // the endpoint identification protocol
- private String identificationProtocol = null;
-
- // The cryptographic algorithm constraints
- private AlgorithmConstraints algorithmConstraints = null;
-
- // Have we been told whether we're client or server?
- private boolean serverModeSet = false;
- private boolean roleIsServer;
-
- /*
- * The protocol versions enabled for use on this connection.
- *
- * Note: we support a pseudo protocol called SSLv2Hello which when
- * set will result in an SSL v2 Hello being sent with SSL (version 3.0)
- * or TLS (version 3.1, 3.2, etc.) version info.
- */
- private ProtocolList enabledProtocols;
-
- /*
- * The SSL version associated with this connection.
- */
- private ProtocolVersion protocolVersion = ProtocolVersion.DEFAULT;
-
- /*
- * Crypto state that's reinitialized when the session changes.
- */
- private MAC readMAC, writeMAC;
- private CipherBox readCipher, writeCipher;
- // NOTE: compression state would be saved here
-
- /*
- * security parameters for secure renegotiation.
- */
- private boolean secureRenegotiation;
- private byte[] clientVerifyData;
- private byte[] serverVerifyData;
-
- /*
- * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
- * IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
- * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
- *
- * There are several locks here.
- *
- * The primary lock is the per-instance lock used by
- * synchronized(this) and the synchronized methods. It controls all
- * access to things such as the connection state and variables which
- * affect handshaking. If we are inside a synchronized method, we
- * can access the state directly, otherwise, we must use the
- * synchronized equivalents.
- *
- * Note that we must never acquire the <code>this</code> lock after
- * <code>writeLock</code> or run the risk of deadlock.
- *
- * Grab some coffee, and be careful with any code changes.
- */
- private Object wrapLock;
- private Object unwrapLock;
- Object writeLock;
-
- /*
- * Is it the first application record to write?
- */
- private boolean isFirstAppOutputRecord = true;
-
- /*
- * Class and subclass dynamic debugging support
- */
- private static final Debug debug = Debug.getInstance("ssl");
-
- //
- // Initialization/Constructors
- //
-
- /**
- * Constructor for an SSLEngine from SSLContext, without
- * host/port hints. This Engine will not be able to cache
- * sessions, but must renegotiate everything by hand.
- */
- SSLEngineImpl(SSLContextImpl ctx) {
- super();
- init(ctx);
- }
-
- /**
- * Constructor for an SSLEngine from SSLContext.
- */
- SSLEngineImpl(SSLContextImpl ctx, String host, int port) {
- super(host, port);
- init(ctx);
- }
-
- /**
- * Initializes the Engine
- */
- private void init(SSLContextImpl ctx) {
- if (debug != null && Debug.isOn("ssl")) {
- System.out.println("Using SSLEngineImpl.");
- }
-
- sslContext = ctx;
- sess = SSLSessionImpl.nullSession;
- handshakeSession = null;
-
- /*
- * State is cs_START until we initialize the handshaker.
- *
- * Apps using SSLEngine are probably going to be server.
- * Somewhat arbitrary choice.
- */
- roleIsServer = true;
- connectionState = cs_START;
-
- /*
- * default read and write side cipher and MAC support
- *
- * Note: compression support would go here too
- */
- readCipher = CipherBox.NULL;
- readMAC = MAC.NULL;
- writeCipher = CipherBox.NULL;
- writeMAC = MAC.NULL;
-
- // default security parameters for secure renegotiation
- secureRenegotiation = false;
- clientVerifyData = new byte[0];
- serverVerifyData = new byte[0];
-
- enabledCipherSuites =
- sslContext.getDefaultCipherSuiteList(roleIsServer);
- enabledProtocols =
- sslContext.getDefaultProtocolList(roleIsServer);
-
- wrapLock = new Object();
- unwrapLock = new Object();
- writeLock = new Object();
-
- /*
- * Save the Access Control Context. This will be used later
- * for a couple of things, including providing a context to
- * run tasks in, and for determining which credentials
- * to use for Subject based (JAAS) decisions
- */
- acc = AccessController.getContext();
-
- /*
- * All outbound application data goes through this OutputRecord,
- * other data goes through their respective records created
- * elsewhere. All inbound data goes through this one
- * input record.
- */
- outputRecord =
- new EngineOutputRecord(Record.ct_application_data, this);
- inputRecord = new EngineInputRecord(this);
- inputRecord.enableFormatChecks();
-
- writer = new EngineWriter();
- }
-
- /**
- * Initialize the handshaker object. This means:
- *
- * . if a handshake is already in progress (state is cs_HANDSHAKE
- * or cs_RENEGOTIATE), do nothing and return
- *
- * . if the engine is already closed, throw an Exception (internal error)
- *
- * . otherwise (cs_START or cs_DATA), create the appropriate handshaker
- * object and advance the connection state (to cs_HANDSHAKE or
- * cs_RENEGOTIATE, respectively).
- *
- * This method is called right after a new engine is created, when
- * starting renegotiation, or when changing client/server mode of the
- * engine.
- */
- private void initHandshaker() {
- switch (connectionState) {
-
- //
- // Starting a new handshake.
- //
- case cs_START:
- case cs_DATA:
- break;
-
- //
- // We're already in the middle of a handshake.
- //
- case cs_HANDSHAKE:
- case cs_RENEGOTIATE:
- return;
-
- //
- // Anyone allowed to call this routine is required to
- // do so ONLY if the connection state is reasonable...
- //
- default:
- throw new IllegalStateException("Internal error");
- }
-
- // state is either cs_START or cs_DATA
- if (connectionState == cs_START) {
- connectionState = cs_HANDSHAKE;
- } else { // cs_DATA
- connectionState = cs_RENEGOTIATE;
- }
- if (roleIsServer) {
- handshaker = new ServerHandshaker(this, sslContext,
- enabledProtocols, doClientAuth,
- protocolVersion, connectionState == cs_HANDSHAKE,
- secureRenegotiation, clientVerifyData, serverVerifyData);
- } else {
- handshaker = new ClientHandshaker(this, sslContext,
- enabledProtocols,
- protocolVersion, connectionState == cs_HANDSHAKE,
- secureRenegotiation, clientVerifyData, serverVerifyData);
- }
- handshaker.setEnabledCipherSuites(enabledCipherSuites);
- handshaker.setEnableSessionCreation(enableSessionCreation);
- }
-
- /*
- * Report the current status of the Handshaker
- */
- private HandshakeStatus getHSStatus(HandshakeStatus hss) {
-
- if (hss != null) {
- return hss;
- }
-
- synchronized (this) {
- if (writer.hasOutboundData()) {
- return HandshakeStatus.NEED_WRAP;
- } else if (handshaker != null) {
- if (handshaker.taskOutstanding()) {
- return HandshakeStatus.NEED_TASK;
- } else {
- return HandshakeStatus.NEED_UNWRAP;
- }
- } else if (connectionState == cs_CLOSED) {
- /*
- * Special case where we're closing, but
- * still need the close_notify before we
- * can officially be closed.
- *
- * Note isOutboundDone is taken care of by
- * hasOutboundData() above.
- */
- if (!isInboundDone()) {
- return HandshakeStatus.NEED_UNWRAP;
- } // else not handshaking
- }
-
- return HandshakeStatus.NOT_HANDSHAKING;
- }
- }
-
- synchronized private void checkTaskThrown() throws SSLException {
- if (handshaker != null) {
- handshaker.checkThrown();
- }
- }
-
- //
- // Handshaking and connection state code
- //
-
- /*
- * Provides "this" synchronization for connection state.
- * Otherwise, you can access it directly.
- */
- synchronized private int getConnectionState() {
- return connectionState;
- }
-
- synchronized private void setConnectionState(int state) {
- connectionState = state;
- }
-
- /*
- * Get the Access Control Context.
- *
- * Used for a known context to
- * run tasks in, and for determining which credentials
- * to use for Subject-based (JAAS) decisions.
- */
- AccessControlContext getAcc() {
- return acc;
- }
-
- /*
- * Is a handshake currently underway?
- */
- public SSLEngineResult.HandshakeStatus getHandshakeStatus() {
- return getHSStatus(null);
- }
-
- /*
- * When a connection finishes handshaking by enabling use of a newly
- * negotiated session, each end learns about it in two halves (read,
- * and write). When both read and write ciphers have changed, and the
- * last handshake message has been read, the connection has joined
- * (rejoined) the new session.
- *
- * NOTE: The SSLv3 spec is rather unclear on the concepts here.
- * Sessions don't change once they're established (including cipher
- * suite and master secret) but connections can join them (and leave
- * them). They're created by handshaking, though sometime handshaking
- * causes connections to join up with pre-established sessions.
- *
- * Synchronized on "this" from readRecord.
- */
- private void changeReadCiphers() throws SSLException {
- if (connectionState != cs_HANDSHAKE
- && connectionState != cs_RENEGOTIATE) {
- throw new SSLProtocolException(
- "State error, change cipher specs");
- }
-
- // ... create decompressor
-
- CipherBox oldCipher = readCipher;
-
- try {
- readCipher = handshaker.newReadCipher();
- readMAC = handshaker.newReadMAC();
- } catch (GeneralSecurityException e) {
- // "can't happen"
- throw (SSLException)new SSLException
- ("Algorithm missing: ").initCause(e);
- }
-
- /*
- * Dispose of any intermediate state in the underlying cipher.
- * For PKCS11 ciphers, this will release any attached sessions,
- * and thus make finalization faster.
- *
- * Since MAC's doFinal() is called for every SSL/TLS packet, it's
- * not necessary to do the same with MAC's.
- */
- oldCipher.dispose();
- }
-
- /*
- * used by Handshaker to change the active write cipher, follows
- * the output of the CCS message.
- *
- * Also synchronized on "this" from readRecord/delegatedTask.
- */
- void changeWriteCiphers() throws SSLException {
- if (connectionState != cs_HANDSHAKE
- && connectionState != cs_RENEGOTIATE) {
- throw new SSLProtocolException(
- "State error, change cipher specs");
- }
-
- // ... create compressor
-
- CipherBox oldCipher = writeCipher;
-
- try {
- writeCipher = handshaker.newWriteCipher();
- writeMAC = handshaker.newWriteMAC();
- } catch (GeneralSecurityException e) {
- // "can't happen"
- throw (SSLException)new SSLException
- ("Algorithm missing: ").initCause(e);
- }
-
- // See comment above.
- oldCipher.dispose();
-
- // reset the flag of the first application record
- isFirstAppOutputRecord = true;
- }
-
- /*
- * Updates the SSL version associated with this connection.
- * Called from Handshaker once it has determined the negotiated version.
- */
- synchronized void setVersion(ProtocolVersion protocolVersion) {
- this.protocolVersion = protocolVersion;
- outputRecord.setVersion(protocolVersion);
- }
-
-
- /**
- * Kickstart the handshake if it is not already in progress.
- * This means:
- *
- * . if handshaking is already underway, do nothing and return
- *
- * . if the engine is not connected or already closed, throw an
- * Exception.
- *
- * . otherwise, call initHandshake() to initialize the handshaker
- * object and progress the state. Then, send the initial
- * handshaking message if appropriate (always on clients and
- * on servers when renegotiating).
- */
- private synchronized void kickstartHandshake() throws IOException {
- switch (connectionState) {
-
- case cs_START:
- if (!serverModeSet) {
- throw new IllegalStateException(
- "Client/Server mode not yet set.");
- }
- initHandshaker();
- break;
-
- case cs_HANDSHAKE:
- // handshaker already setup, proceed
- break;
-
- case cs_DATA:
- if (!secureRenegotiation && !Handshaker.allowUnsafeRenegotiation) {
- throw new SSLHandshakeException(
- "Insecure renegotiation is not allowed");
- }
-
- if (!secureRenegotiation) {
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println(
- "Warning: Using insecure renegotiation");
- }
- }
-
- // initialize the handshaker, move to cs_RENEGOTIATE
- initHandshaker();
- break;
-
- case cs_RENEGOTIATE:
- // handshaking already in progress, return
- return;
-
- default:
- // cs_ERROR/cs_CLOSED
- throw new SSLException("SSLEngine is closing/closed");
- }
-
- //
- // Kickstart handshake state machine if we need to ...
- //
- // Note that handshaker.kickstart() writes the message
- // to its HandshakeOutStream, which calls back into
- // SSLSocketImpl.writeRecord() to send it.
- //
- if (!handshaker.activated()) {
- // prior to handshaking, activate the handshake
- if (connectionState == cs_RENEGOTIATE) {
- // don't use SSLv2Hello when renegotiating
- handshaker.activate(protocolVersion);
- } else {
- handshaker.activate(null);
- }
-
- if (handshaker instanceof ClientHandshaker) {
- // send client hello
- handshaker.kickstart();
- } else { // instanceof ServerHandshaker
- if (connectionState == cs_HANDSHAKE) {
- // initial handshake, no kickstart message to send
- } else {
- // we want to renegotiate, send hello request
- handshaker.kickstart();
-
- // hello request is not included in the handshake
- // hashes, reset them
- handshaker.handshakeHash.reset();
- }
- }
- }
- }
-
- /*
- * Start a SSLEngine handshake
- */
- public void beginHandshake() throws SSLException {
- try {
- kickstartHandshake();
- } catch (Exception e) {
- fatal(Alerts.alert_handshake_failure,
- "Couldn't kickstart handshaking", e);
- }
- }
-
-
- //
- // Read/unwrap side
- //
-
-
- /**
- * Unwraps a buffer. Does a variety of checks before grabbing
- * the unwrapLock, which blocks multiple unwraps from occuring.
- */
- public SSLEngineResult unwrap(ByteBuffer netData, ByteBuffer [] appData,
- int offset, int length) throws SSLException {
-
- EngineArgs ea = new EngineArgs(netData, appData, offset, length);
-
- try {
- synchronized (unwrapLock) {
- return readNetRecord(ea);
- }
- } catch (Exception e) {
- /*
- * Don't reset position so it looks like we didn't
- * consume anything. We did consume something, and it
- * got us into this situation, so report that much back.
- * Our days of consuming are now over anyway.
- */
- fatal(Alerts.alert_internal_error,
- "problem unwrapping net record", e);
- return null; // make compiler happy
- } finally {
- /*
- * Just in case something failed to reset limits properly.
- */
- ea.resetLim();
- }
- }
-
- /*
- * Makes additional checks for unwrap, but this time more
- * specific to this packet and the current state of the machine.
- */
- private SSLEngineResult readNetRecord(EngineArgs ea) throws IOException {
-
- Status status = null;
- HandshakeStatus hsStatus = null;
-
- /*
- * See if the handshaker needs to report back some SSLException.
- */
- checkTaskThrown();
-
- /*
- * Check if we are closing/closed.
- */
- if (isInboundDone()) {
- return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0);
- }
-
- /*
- * If we're still in cs_HANDSHAKE, make sure it's been
- * started.
- */
- synchronized (this) {
- if ((connectionState == cs_HANDSHAKE) ||
- (connectionState == cs_START)) {
- kickstartHandshake();
-
- /*
- * If there's still outbound data to flush, we
- * can return without trying to unwrap anything.
- */
- hsStatus = getHSStatus(null);
-
- if (hsStatus == HandshakeStatus.NEED_WRAP) {
- return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
- }
- }
- }
-
- /*
- * Grab a copy of this if it doesn't already exist,
- * and we can use it several places before anything major
- * happens on this side. Races aren't critical
- * here.
- */
- if (hsStatus == null) {
- hsStatus = getHSStatus(null);
- }
-
- /*
- * If we have a task outstanding, this *MUST* be done before
- * doing any more unwrapping, because we could be in the middle
- * of receiving a handshake message, for example, a finished
- * message which would change the ciphers.
- */
- if (hsStatus == HandshakeStatus.NEED_TASK) {
- return new SSLEngineResult(
- Status.OK, hsStatus, 0, 0);
- }
-
- /*
- * Check the packet to make sure enough is here.
- * This will also indirectly check for 0 len packets.
- */
- int packetLen = inputRecord.bytesInCompletePacket(ea.netData);
-
- // Is this packet bigger than SSL/TLS normally allows?
- if (packetLen > sess.getPacketBufferSize()) {
- if (packetLen > Record.maxLargeRecordSize) {
- throw new SSLProtocolException(
- "Input SSL/TLS record too big: max = " +
- Record.maxLargeRecordSize +
- " len = " + packetLen);
- } else {
- // Expand the expected maximum packet/application buffer
- // sizes.
- sess.expandBufferSizes();
- }
- }
-
- /*
- * Check for OVERFLOW.
- *
- * To be considered: We could delay enforcing the application buffer
- * free space requirement until after the initial handshaking.
- */
- if ((packetLen - Record.headerSize) > ea.getAppRemaining()) {
- return new SSLEngineResult(Status.BUFFER_OVERFLOW, hsStatus, 0, 0);
- }
-
- // check for UNDERFLOW.
- if ((packetLen == -1) || (ea.netData.remaining() < packetLen)) {
- return new SSLEngineResult(
- Status.BUFFER_UNDERFLOW, hsStatus, 0, 0);
- }
-
- /*
- * We're now ready to actually do the read.
- * The only result code we really need to be exactly
- * right is the HS finished, for signaling to
- * HandshakeCompletedListeners.
- */
- try {
- hsStatus = readRecord(ea);
- } catch (SSLException e) {
- throw e;
- } catch (IOException e) {
- SSLException ex = new SSLException("readRecord");
- ex.initCause(e);
- throw ex;
- }
-
- /*
- * Check the various condition that we could be reporting.
- *
- * It's *possible* something might have happened between the
- * above and now, but it was better to minimally lock "this"
- * during the read process. We'll return the current
- * status, which is more representative of the current state.
- *
- * status above should cover: FINISHED, NEED_TASK
- */
- status = (isInboundDone() ? Status.CLOSED : Status.OK);
- hsStatus = getHSStatus(hsStatus);
-
- return new SSLEngineResult(status, hsStatus,
- ea.deltaNet(), ea.deltaApp());
- }
-
- /*
- * Actually do the read record processing.
- *
- * Returns a Status if it can make specific determinations
- * of the engine state. In particular, we need to signal
- * that a handshake just completed.
- *
- * It would be nice to be symmetrical with the write side and move
- * the majority of this to EngineInputRecord, but there's too much
- * SSLEngine state to do that cleanly. It must still live here.
- */
- private HandshakeStatus readRecord(EngineArgs ea) throws IOException {
-
- HandshakeStatus hsStatus = null;
-
- /*
- * The various operations will return new sliced BB's,
- * this will avoid having to worry about positions and
- * limits in the netBB.
- */
- ByteBuffer readBB = null;
- ByteBuffer decryptedBB = null;
-
- if (getConnectionState() != cs_ERROR) {
-
- /*
- * Read a record ... maybe emitting an alert if we get a
- * comprehensible but unsupported "hello" message during
- * format checking (e.g. V2).
- */
- try {
- readBB = inputRecord.read(ea.netData);
- } catch (IOException e) {
- fatal(Alerts.alert_unexpected_message, e);
- }
-
- /*
- * The basic SSLv3 record protection involves (optional)
- * encryption for privacy, and an integrity check ensuring
- * data origin authentication. We do them both here, and
- * throw a fatal alert if the integrity check fails.
- */
- try {
- decryptedBB = inputRecord.decrypt(readMAC, readCipher, readBB);
- } catch (BadPaddingException e) {
- byte alertType = (inputRecord.contentType() ==
- Record.ct_handshake) ?
- Alerts.alert_handshake_failure :
- Alerts.alert_bad_record_mac;
- fatal(alertType, e.getMessage(), e);
- }
-
-
- // if (!inputRecord.decompress(c))
- // fatal(Alerts.alert_decompression_failure,
- // "decompression failure");
-
-
- /*
- * Process the record.
- */
-
- synchronized (this) {
- switch (inputRecord.contentType()) {
- case Record.ct_handshake:
- /*
- * Handshake messages always go to a pending session
- * handshaker ... if there isn't one, create one. This
- * must work asynchronously, for renegotiation.
- *
- * NOTE that handshaking will either resume a session
- * which was in the cache (and which might have other
- * connections in it already), or else will start a new
- * session (new keys exchanged) with just this connection
- * in it.
- */
- initHandshaker();
- if (!handshaker.activated()) {
- // prior to handshaking, activate the handshake
- if (connectionState == cs_RENEGOTIATE) {
- // don't use SSLv2Hello when renegotiating
- handshaker.activate(protocolVersion);
- } else {
- handshaker.activate(null);
- }
- }
-
- /*
- * process the handshake record ... may contain just
- * a partial handshake message or multiple messages.
- *
- * The handshaker state machine will ensure that it's
- * a finished message.
- */
- handshaker.process_record(inputRecord, expectingFinished);
- expectingFinished = false;
-
- if (handshaker.invalidated) {
- handshaker = null;
- // if state is cs_RENEGOTIATE, revert it to cs_DATA
- if (connectionState == cs_RENEGOTIATE) {
- connectionState = cs_DATA;
- }
- } else if (handshaker.isDone()) {
- // reset the parameters for secure renegotiation.
- secureRenegotiation =
- handshaker.isSecureRenegotiation();
- clientVerifyData = handshaker.getClientVerifyData();
- serverVerifyData = handshaker.getServerVerifyData();
-
- sess = handshaker.getSession();
- handshakeSession = null;
- if (!writer.hasOutboundData()) {
- hsStatus = HandshakeStatus.FINISHED;
- }
- handshaker = null;
- connectionState = cs_DATA;
-
- // No handshakeListeners here. That's a
- // SSLSocket thing.
- } else if (handshaker.taskOutstanding()) {
- hsStatus = HandshakeStatus.NEED_TASK;
- }
- break;
-
- case Record.ct_application_data:
- // Pass this right back up to the application.
- if ((connectionState != cs_DATA)
- && (connectionState != cs_RENEGOTIATE)
- && (connectionState != cs_CLOSED)) {
- throw new SSLProtocolException(
- "Data received in non-data state: " +
- connectionState);
- }
-
- if (expectingFinished) {
- throw new SSLProtocolException
- ("Expecting finished message, received data");
- }
-
- /*
- * Don't return data once the inbound side is
- * closed.
- */
- if (!inboundDone) {
- ea.scatter(decryptedBB.slice());
- }
- break;
-
- case Record.ct_alert:
- recvAlert();
- break;
-
- case Record.ct_change_cipher_spec:
- if ((connectionState != cs_HANDSHAKE
- && connectionState != cs_RENEGOTIATE)
- || inputRecord.available() != 1
- || inputRecord.read() != 1) {
- fatal(Alerts.alert_unexpected_message,
- "illegal change cipher spec msg, state = "
- + connectionState);
- }
-
- //
- // The first message after a change_cipher_spec
- // record MUST be a "Finished" handshake record,
- // else it's a protocol violation. We force this
- // to be checked by a minor tweak to the state
- // machine.
- //
- changeReadCiphers();
- // next message MUST be a finished message
- expectingFinished = true;
- break;
-
- default:
- //
- // TLS requires that unrecognized records be ignored.
- //
- if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() +
- ", Received record type: "
- + inputRecord.contentType());
- }
- break;
- } // switch
-
- /*
- * We only need to check the sequence number state for
- * non-handshaking record.
- *
- * Note that in order to maintain the handshake status
- * properly, we check the sequence number after the last
- * record reading process. As we request renegotiation
- * or close the connection for wrapped sequence number
- * when there is enough sequence number space left to
- * handle a few more records, so the sequence number
- * of the last record cannot be wrapped.
- */
- if (connectionState < cs_ERROR && !isInboundDone() &&
- (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
- if (checkSequenceNumber(readMAC,
- inputRecord.contentType())) {
- hsStatus = getHSStatus(null);
- }
- }
- } // synchronized (this)
- }
-
- return hsStatus;
- }
-
-
- //
- // write/wrap side
- //
-
-
- /**
- * Wraps a buffer. Does a variety of checks before grabbing
- * the wrapLock, which blocks multiple wraps from occuring.
- */
- public SSLEngineResult wrap(ByteBuffer [] appData,
- int offset, int length, ByteBuffer netData) throws SSLException {
-
- EngineArgs ea = new EngineArgs(appData, offset, length, netData);
-
- /*
- * We can be smarter about using smaller buffer sizes later.
- * For now, force it to be large enough to handle any
- * valid SSL/TLS record.
- */
- if (netData.remaining() < outputRecord.maxRecordSize) {
- return new SSLEngineResult(
- Status.BUFFER_OVERFLOW, getHSStatus(null), 0, 0);
- }
-
- try {
- synchronized (wrapLock) {
- return writeAppRecord(ea);
- }
- } catch (Exception e) {
- ea.resetPos();
-
- fatal(Alerts.alert_internal_error,
- "problem wrapping app data", e);
- return null; // make compiler happy
- } finally {
- /*
- * Just in case something didn't reset limits properly.
- */
- ea.resetLim();
- }
- }
-
- /*
- * Makes additional checks for unwrap, but this time more
- * specific to this packet and the current state of the machine.
- */
- private SSLEngineResult writeAppRecord(EngineArgs ea) throws IOException {
-
- Status status = null;
- HandshakeStatus hsStatus = null;
-
- /*
- * See if the handshaker needs to report back some SSLException.
- */
- checkTaskThrown();
-
- /*
- * short circuit if we're closed/closing.
- */
- if (writer.isOutboundDone()) {
- return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0);
- }
-
- /*
- * If we're still in cs_HANDSHAKE, make sure it's been
- * started.
- */
- synchronized (this) {
- if ((connectionState == cs_HANDSHAKE) ||
- (connectionState == cs_START)) {
- kickstartHandshake();
-
- /*
- * If there's no HS data available to write, we can return
- * without trying to wrap anything.
- */
- hsStatus = getHSStatus(null);
-
- if (hsStatus == HandshakeStatus.NEED_UNWRAP) {
- return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
- }
- }
- }
-
- /*
- * Grab a copy of this if it doesn't already exist,
- * and we can use it several places before anything major
- * happens on this side. Races aren't critical
- * here.
- */
- if (hsStatus == null) {
- hsStatus = getHSStatus(null);
- }
-
- /*
- * If we have a task outstanding, this *MUST* be done before
- * doing any more wrapping, because we could be in the middle
- * of receiving a handshake message, for example, a finished
- * message which would change the ciphers.
- */
- if (hsStatus == HandshakeStatus.NEED_TASK) {
- return new SSLEngineResult(
- Status.OK, hsStatus, 0, 0);
- }
-
- /*
- * This will obtain any waiting outbound data, or will
- * process the outbound appData.
- */
- try {
- synchronized (writeLock) {
- hsStatus = writeRecord(outputRecord, ea);
- }
- } catch (SSLException e) {
- throw e;
- } catch (IOException e) {
- SSLException ex = new SSLException("Write problems");
- ex.initCause(e);
- throw ex;
- }
-
- /*
- * writeRecord might have reported some status.
- * Now check for the remaining cases.
- *
- * status above should cover: NEED_WRAP/FINISHED
- */
- status = (isOutboundDone() ? Status.CLOSED : Status.OK);
- hsStatus = getHSStatus(hsStatus);
-
- return new SSLEngineResult(status, hsStatus,
- ea.deltaApp(), ea.deltaNet());
- }
-
- /*
- * Central point to write/get all of the outgoing data.
- */
- private HandshakeStatus writeRecord(EngineOutputRecord eor,
- EngineArgs ea) throws IOException {
-
- // eventually compress as well.
- HandshakeStatus hsStatus =
- writer.writeRecord(eor, ea, writeMAC, writeCipher);
-
- /*
- * We only need to check the sequence number state for
- * non-handshaking record.
- *
- * Note that in order to maintain the handshake status
- * properly, we check the sequence number after the last
- * record writing process. As we request renegotiation
- * or close the connection for wrapped sequence number
- * when there is enough sequence number space left to
- * handle a few more records, so the sequence number
- * of the last record cannot be wrapped.
- */
- if (connectionState < cs_ERROR && !isOutboundDone() &&
- (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) {
- if (checkSequenceNumber(writeMAC, eor.contentType())) {
- hsStatus = getHSStatus(null);
- }
- }
-
- /*
- * turn off the flag of the first application record if we really
- * consumed at least byte.
- */
- if (isFirstAppOutputRecord && ea.deltaApp() > 0) {
- isFirstAppOutputRecord = false;
- }
-
- return hsStatus;
- }
-
- /*
- * Need to split the payload except the following cases:
- *
- * 1. protocol version is TLS 1.1 or later;
- * 2. bulk cipher does not use CBC mode, including null bulk cipher suites.
- * 3. the payload is the first application record of a freshly
- * negotiated TLS session.
- * 4. the CBC protection is disabled;
- *
- * More details, please refer to
- * EngineOutputRecord.write(EngineArgs, MAC, CipherBox).
- */
- boolean needToSplitPayload(CipherBox cipher, ProtocolVersion protocol) {
- return (protocol.v <= ProtocolVersion.TLS10.v) &&
- cipher.isCBCMode() && !isFirstAppOutputRecord &&
- Record.enableCBCProtection;
- }
-
- /*
- * Non-application OutputRecords go through here.
- */
- void writeRecord(EngineOutputRecord eor) throws IOException {
- // eventually compress as well.
- writer.writeRecord(eor, writeMAC, writeCipher);
-
- /*
- * Check the sequence number state
- *
- * Note that in order to maintain the connection I/O
- * properly, we check the sequence number after the last
- * record writing process. As we request renegotiation
- * or close the connection for wrapped sequence number
- * when there is enough sequence number space left to
- * handle a few more records, so the sequence number
- * of the last record cannot be wrapped.
- */
- if ((connectionState < cs_ERROR) && !isOutboundDone()) {
- checkSequenceNumber(writeMAC, eor.contentType());
- }
- }
-
- //
- // Close code
- //
-
- /**
- * Check the sequence number state
- *
- * RFC 4346 states that, "Sequence numbers are of type uint64 and
- * may not exceed 2^64-1. Sequence numbers do not wrap. If a TLS
- * implementation would need to wrap a sequence number, it must
- * renegotiate instead."
- *
- * Return true if the handshake status may be changed.
- */
- private boolean checkSequenceNumber(MAC mac, byte type)
- throws IOException {
-
- /*
- * Don't bother to check the sequence number for error or
- * closed connections, or NULL MAC
- */
- if (connectionState >= cs_ERROR || mac == MAC.NULL) {
- return false;
- }
-
- /*
- * Conservatively, close the connection immediately when the
- * sequence number is close to overflow
- */
- if (mac.seqNumOverflow()) {
- /*
- * TLS protocols do not define a error alert for sequence
- * number overflow. We use handshake_failure error alert
- * for handshaking and bad_record_mac for other records.
- */
- if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() +
- ", sequence number extremely close to overflow " +
- "(2^64-1 packets). Closing connection.");
- }
-
- fatal(Alerts.alert_handshake_failure, "sequence number overflow");
-
- return true; // make the compiler happy
- }
-
- /*
- * Ask for renegotiation when need to renew sequence number.
- *
- * Don't bother to kickstart the renegotiation when the local is
- * asking for it.
- */
- if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {
- if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() + ", request renegotiation " +
- "to avoid sequence number overflow");
- }
-
- beginHandshake();
- return true;
- }
-
- return false;
- }
-
- /**
- * Signals that no more outbound application data will be sent
- * on this <code>SSLEngine</code>.
- */
- private void closeOutboundInternal() {
-
- if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() + ", closeOutboundInternal()");
- }
-
- /*
- * Already closed, ignore
- */
- if (writer.isOutboundDone()) {
- return;
- }
-
- switch (connectionState) {
-
- /*
- * If we haven't even started yet, don't bother reading inbound.
- */
- case cs_START:
- writer.closeOutbound();
- inboundDone = true;
- break;
-
- case cs_ERROR:
- case cs_CLOSED:
- break;
-
- /*
- * Otherwise we indicate clean termination.
- */
- // case cs_HANDSHAKE:
- // case cs_DATA:
- // case cs_RENEGOTIATE:
- default:
- warning(Alerts.alert_close_notify);
- writer.closeOutbound();
- break;
- }
-
- // See comment in changeReadCiphers()
- writeCipher.dispose();
-
- connectionState = cs_CLOSED;
- }
-
- synchronized public void closeOutbound() {
- /*
- * Dump out a close_notify to the remote side
- */
- if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() + ", called closeOutbound()");
- }
-
- closeOutboundInternal();
- }
-
- /**
- * Returns the outbound application data closure state
- */
- public boolean isOutboundDone() {
- return writer.isOutboundDone();
- }
-
- /**
- * Signals that no more inbound network data will be sent
- * to this <code>SSLEngine</code>.
- */
- private void closeInboundInternal() {
-
- if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() + ", closeInboundInternal()");
- }
-
- /*
- * Already closed, ignore
- */
- if (inboundDone) {
- return;
- }
-
- closeOutboundInternal();
- inboundDone = true;
-
- // See comment in changeReadCiphers()
- readCipher.dispose();
-
- connectionState = cs_CLOSED;
- }
-
- /*
- * Close the inbound side of the connection. We grab the
- * lock here, and do the real work in the internal verison.
- * We do check for truncation attacks.
- */
- synchronized public void closeInbound() throws SSLException {
- /*
- * Currently closes the outbound side as well. The IETF TLS
- * working group has expressed the opinion that 1/2 open
- * connections are not allowed by the spec. May change
- * someday in the future.
- */
- if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() + ", called closeInbound()");
- }
-
- /*
- * No need to throw an Exception if we haven't even started yet.
- */
- if ((connectionState != cs_START) && !recvCN) {
- recvCN = true; // Only receive the Exception once
- fatal(Alerts.alert_internal_error,
- "Inbound closed before receiving peer's close_notify: " +
- "possible truncation attack?");
- } else {
- /*
- * Currently, this is a no-op, but in case we change
- * the close inbound code later.
- */
- closeInboundInternal();
- }
- }
-
- /**
- * Returns the network inbound data closure state
- */
- synchronized public boolean isInboundDone() {
- return inboundDone;
- }
-
-
- //
- // Misc stuff
- //
-
-
- /**
- * Returns the current <code>SSLSession</code> for this
- * <code>SSLEngine</code>
- * <P>
- * These can be long lived, and frequently correspond to an
- * entire login session for some user.
- */
- synchronized public SSLSession getSession() {
- return sess;
- }
-
- @Override
- synchronized public SSLSession getHandshakeSession() {
- return handshakeSession;
- }
-
- synchronized void setHandshakeSession(SSLSessionImpl session) {
- handshakeSession = session;
- }
-
- /**
- * Returns a delegated <code>Runnable</code> task for
- * this <code>SSLEngine</code>.
- */
- synchronized public Runnable getDelegatedTask() {
- if (handshaker != null) {
- return handshaker.getTask();
- }
- return null;
- }
-
-
- //
- // EXCEPTION AND ALERT HANDLING
- //
-
- /*
- * Send a warning alert.
- */
- void warning(byte description) {
- sendAlert(Alerts.alert_warning, description);
- }
-
- synchronized void fatal(byte description, String diagnostic)
- throws SSLException {
- fatal(description, diagnostic, null);
- }
-
- synchronized void fatal(byte description, Throwable cause)
- throws SSLException {
- fatal(description, null, cause);
- }
-
- /*
- * We've got a fatal error here, so start the shutdown process.
- *
- * Because of the way the code was written, we have some code
- * calling fatal directly when the "description" is known
- * and some throwing Exceptions which are then caught by higher
- * levels which then call here. This code needs to determine
- * if one of the lower levels has already started the process.
- *
- * We won't worry about Error's, if we have one of those,
- * we're in worse trouble. Note: the networking code doesn't
- * deal with Errors either.
- */
- synchronized void fatal(byte description, String diagnostic,
- Throwable cause) throws SSLException {
-
- /*
- * If we have no further information, make a general-purpose
- * message for folks to see. We generally have one or the other.
- */
- if (diagnostic == null) {
- diagnostic = "General SSLEngine problem";
- }
- if (cause == null) {
- cause = Alerts.getSSLException(description, cause, diagnostic);
- }
-
- /*
- * If we've already shutdown because of an error,
- * there is nothing we can do except rethrow the exception.
- *
- * Most exceptions seen here will be SSLExceptions.
- * We may find the occasional Exception which hasn't been
- * converted to a SSLException, so we'll do it here.
- */
- if (closeReason != null) {
- if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() +
- ", fatal: engine already closed. Rethrowing " +
- cause.toString());
- }
- if (cause instanceof RuntimeException) {
- throw (RuntimeException)cause;
- } else if (cause instanceof SSLException) {
- throw (SSLException)cause;
- } else if (cause instanceof Exception) {
- SSLException ssle = new SSLException(
- "fatal SSLEngine condition");
- ssle.initCause(cause);
- throw ssle;
- }
- }
-
- if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName()
- + ", fatal error: " + description +
- ": " + diagnostic + "\n" + cause.toString());
- }
-
- /*
- * Ok, this engine's going down.
- */
- int oldState = connectionState;
- connectionState = cs_ERROR;
-
- inboundDone = true;
-
- sess.invalidate();
- if (handshakeSession != null) {
- handshakeSession.invalidate();
- }
-
- /*
- * If we haven't even started handshaking yet, no need
- * to generate the fatal close alert.
- */
- if (oldState != cs_START) {
- sendAlert(Alerts.alert_fatal, description);
- }
-
- if (cause instanceof SSLException) { // only true if != null
- closeReason = (SSLException)cause;
- } else {
- /*
- * Including RuntimeExceptions, but we'll throw those
- * down below. The closeReason isn't used again,
- * except for null checks.
- */
- closeReason =
- Alerts.getSSLException(description, cause, diagnostic);
- }
-
- writer.closeOutbound();
-
- connectionState = cs_CLOSED;
-
- // See comment in changeReadCiphers()
- readCipher.dispose();
- writeCipher.dispose();
-
- if (cause instanceof RuntimeException) {
- throw (RuntimeException)cause;
- } else {
- throw closeReason;
- }
- }
-
- /*
- * Process an incoming alert ... caller must already have synchronized
- * access to "this".
- */
- private void recvAlert() throws IOException {
- byte level = (byte)inputRecord.read();
- byte description = (byte)inputRecord.read();
- if (description == -1) { // check for short message
- fatal(Alerts.alert_illegal_parameter, "Short alert message");
- }
-
- if (debug != null && (Debug.isOn("record") ||
- Debug.isOn("handshake"))) {
- synchronized (System.out) {
- System.out.print(threadName());
- System.out.print(", RECV " + protocolVersion + " ALERT: ");
- if (level == Alerts.alert_fatal) {
- System.out.print("fatal, ");
- } else if (level == Alerts.alert_warning) {
- System.out.print("warning, ");
- } else {
- System.out.print("<level " + (0x0ff & level) + ">, ");
- }
- System.out.println(Alerts.alertDescription(description));
- }
- }
-
- if (level == Alerts.alert_warning) {
- if (description == Alerts.alert_close_notify) {
- if (connectionState == cs_HANDSHAKE) {
- fatal(Alerts.alert_unexpected_message,
- "Received close_notify during handshake");
- } else {
- recvCN = true;
- closeInboundInternal(); // reply to close
- }
- } else {
-
- //
- // The other legal warnings relate to certificates,
- // e.g. no_certificate, bad_certificate, etc; these
- // are important to the handshaking code, which can
- // also handle illegal protocol alerts if needed.
- //
- if (handshaker != null) {
- handshaker.handshakeAlert(description);
- }
- }
- } else { // fatal or unknown level
- String reason = "Received fatal alert: "
- + Alerts.alertDescription(description);
- if (closeReason == null) {
- closeReason = Alerts.getSSLException(description, reason);
- }
- fatal(Alerts.alert_unexpected_message, reason);
- }
- }
-
-
- /*
- * Emit alerts. Caller must have synchronized with "this".
- */
- private void sendAlert(byte level, byte description) {
- // the connectionState cannot be cs_START
- if (connectionState >= cs_CLOSED) {
- return;
- }
-
- // For initial handshaking, don't send alert message to peer if
- // handshaker has not started.
- if (connectionState == cs_HANDSHAKE &&
- (handshaker == null || !handshaker.started())) {
- return;
- }
-
- EngineOutputRecord r = new EngineOutputRecord(Record.ct_alert, this);
- r.setVersion(protocolVersion);
-
- boolean useDebug = debug != null && Debug.isOn("ssl");
- if (useDebug) {
- synchronized (System.out) {
- System.out.print(threadName());
- System.out.print(", SEND " + protocolVersion + " ALERT: ");
- if (level == Alerts.alert_fatal) {
- System.out.print("fatal, ");
- } else if (level == Alerts.alert_warning) {
- System.out.print("warning, ");
- } else {
- System.out.print("<level = " + (0x0ff & level) + ">, ");
- }
- System.out.println("description = "
- + Alerts.alertDescription(description));
- }
- }
-
- r.write(level);
- r.write(description);
- try {
- writeRecord(r);
- } catch (IOException e) {
- if (useDebug) {
- System.out.println(threadName() +
- ", Exception sending alert: " + e);
- }
- }
- }
-
-
- //
- // VARIOUS OTHER METHODS (COMMON TO SSLSocket)
- //
-
-
- /**
- * Controls whether new connections may cause creation of new SSL
- * sessions.
- *
- * As long as handshaking has not started, we can change
- * whether we enable session creations. Otherwise,
- * we will need to wait for the next handshake.
- */
- synchronized public void setEnableSessionCreation(boolean flag) {
- enableSessionCreation = flag;
-
- if ((handshaker != null) && !handshaker.activated()) {
- handshaker.setEnableSessionCreation(enableSessionCreation);
- }
- }
-
- /**
- * Returns true if new connections may cause creation of new SSL
- * sessions.
- */
- synchronized public boolean getEnableSessionCreation() {
- return enableSessionCreation;
- }
-
-
- /**
- * Sets the flag controlling whether a server mode engine
- * *REQUIRES* SSL client authentication.
- *
- * As long as handshaking has not started, we can change
- * whether client authentication is needed. Otherwise,
- * we will need to wait for the next handshake.
- */
- synchronized public void setNeedClientAuth(boolean flag) {
- doClientAuth = (flag ?
- SSLEngineImpl.clauth_required : SSLEngineImpl.clauth_none);
-
- if ((handshaker != null) &&
- (handshaker instanceof ServerHandshaker) &&
- !handshaker.activated()) {
- ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
- }
- }
-
- synchronized public boolean getNeedClientAuth() {
- return (doClientAuth == SSLEngineImpl.clauth_required);
- }
-
- /**
- * Sets the flag controlling whether a server mode engine
- * *REQUESTS* SSL client authentication.
- *
- * As long as handshaking has not started, we can change
- * whether client authentication is requested. Otherwise,
- * we will need to wait for the next handshake.
- */
- synchronized public void setWantClientAuth(boolean flag) {
- doClientAuth = (flag ?
- SSLEngineImpl.clauth_requested : SSLEngineImpl.clauth_none);
-
- if ((handshaker != null) &&
- (handshaker instanceof ServerHandshaker) &&
- !handshaker.activated()) {
- ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
- }
- }
-
- synchronized public boolean getWantClientAuth() {
- return (doClientAuth == SSLEngineImpl.clauth_requested);
- }
-
-
- /**
- * Sets the flag controlling whether the engine is in SSL
- * client or server mode. Must be called before any SSL
- * traffic has started.
- */
- synchronized public void setUseClientMode(boolean flag) {
- switch (connectionState) {
-
- case cs_START:
- /*
- * If we need to change the engine mode and the enabled
- * protocols haven't specifically been set by the user,
- * change them to the corresponding default ones.
- */
- if (roleIsServer != (!flag) &&
- sslContext.isDefaultProtocolList(enabledProtocols)) {
- enabledProtocols = sslContext.getDefaultProtocolList(!flag);
- }
-
- roleIsServer = !flag;
- serverModeSet = true;
- break;
-
- case cs_HANDSHAKE:
- /*
- * If we have a handshaker, but haven't started
- * SSL traffic, we can throw away our current
- * handshaker, and start from scratch. Don't
- * need to call doneConnect() again, we already
- * have the streams.
- */
- assert(handshaker != null);
- if (!handshaker.activated()) {
- /*
- * If we need to change the engine mode and the enabled
- * protocols haven't specifically been set by the user,
- * change them to the corresponding default ones.
- */
- if (roleIsServer != (!flag) &&
- sslContext.isDefaultProtocolList(enabledProtocols)) {
- enabledProtocols = sslContext.getDefaultProtocolList(!flag);
- }
-
- roleIsServer = !flag;
- connectionState = cs_START;
- initHandshaker();
- break;
- }
-
- // If handshake has started, that's an error. Fall through...
-
- default:
- if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() +
- ", setUseClientMode() invoked in state = " +
- connectionState);
- }
-
- /*
- * We can let them continue if they catch this correctly,
- * we don't need to shut this down.
- */
- throw new IllegalArgumentException(
- "Cannot change mode after SSL traffic has started");
- }
- }
-
- synchronized public boolean getUseClientMode() {
- return !roleIsServer;
- }
-
-
- /**
- * Returns the names of the cipher suites which could be enabled for use
- * on an SSL connection. Normally, only a subset of these will actually
- * be enabled by default, since this list may include cipher suites which
- * do not support the mutual authentication of servers and clients, or
- * which do not protect data confidentiality. Servers may also need
- * certain kinds of certificates to use certain cipher suites.
- *
- * @return an array of cipher suite names
- */
- public String[] getSupportedCipherSuites() {
- return sslContext.getSupportedCipherSuiteList().toStringArray();
- }
-
- /**
- * Controls which particular cipher suites are enabled for use on
- * this connection. The cipher suites must have been listed by
- * getCipherSuites() as being supported. Even if a suite has been
- * enabled, it might never be used if no peer supports it or the
- * requisite certificates (and private keys) are not available.
- *
- * @param suites Names of all the cipher suites to enable.
- */
- synchronized public void setEnabledCipherSuites(String[] suites) {
- enabledCipherSuites = new CipherSuiteList(suites);
- if ((handshaker != null) && !handshaker.activated()) {
- handshaker.setEnabledCipherSuites(enabledCipherSuites);
- }
- }
-
- /**
- * Returns the names of the SSL cipher suites which are currently enabled
- * for use on this connection. When an SSL engine is first created,
- * all enabled cipher suites <em>(a)</em> protect data confidentiality,
- * by traffic encryption, and <em>(b)</em> can mutually authenticate
- * both clients and servers. Thus, in some environments, this value
- * might be empty.
- *
- * @return an array of cipher suite names
- */
- synchronized public String[] getEnabledCipherSuites() {
- return enabledCipherSuites.toStringArray();
- }
-
-
- /**
- * Returns the protocols that are supported by this implementation.
- * A subset of the supported protocols may be enabled for this connection
- * @return an array of protocol names.
- */
- public String[] getSupportedProtocols() {
- return sslContext.getSuportedProtocolList().toStringArray();
- }
-
- /**
- * Controls which protocols are enabled for use on
- * this connection. The protocols must have been listed by
- * getSupportedProtocols() as being supported.
- *
- * @param protocols protocols to enable.
- * @exception IllegalArgumentException when one of the protocols
- * named by the parameter is not supported.
- */
- synchronized public void setEnabledProtocols(String[] protocols) {
- enabledProtocols = new ProtocolList(protocols);
- if ((handshaker != null) && !handshaker.activated()) {
- handshaker.setEnabledProtocols(enabledProtocols);
- }
- }
-
- synchronized public String[] getEnabledProtocols() {
- return enabledProtocols.toStringArray();
- }
-
- /**
- * Returns the SSLParameters in effect for this SSLEngine.
- */
- synchronized public SSLParameters getSSLParameters() {
- SSLParameters params = super.getSSLParameters();
-
- // the super implementation does not handle the following parameters
- params.setEndpointIdentificationAlgorithm(identificationProtocol);
- params.setAlgorithmConstraints(algorithmConstraints);
-
- return params;
- }
-
- /**
- * Applies SSLParameters to this engine.
- */
- synchronized public void setSSLParameters(SSLParameters params) {
- super.setSSLParameters(params);
-
- // the super implementation does not handle the following parameters
- identificationProtocol = params.getEndpointIdentificationAlgorithm();
- algorithmConstraints = params.getAlgorithmConstraints();
- if ((handshaker != null) && !handshaker.started()) {
- handshaker.setIdentificationProtocol(identificationProtocol);
- handshaker.setAlgorithmConstraints(algorithmConstraints);
- }
- }
-
- /**
- * Return the name of the current thread. Utility method.
- */
- private static String threadName() {
- return Thread.currentThread().getName();
- }
-
- /**
- * Returns a printable representation of this end of the connection.
- */
- public String toString() {
- StringBuilder retval = new StringBuilder(80);
-
- retval.append(Integer.toHexString(hashCode()));
- retval.append("[");
- retval.append("SSLEngine[hostname=");
- String host = getPeerHost();
- retval.append((host == null) ? "null" : host);
- retval.append(" port=");
- retval.append(Integer.toString(getPeerPort()));
- retval.append("] ");
- retval.append(getSession().getCipherSuite());
- retval.append("]");
-
- return retval.toString();
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLServerSocketFactoryImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLServerSocketFactoryImpl.java
deleted file mode 100755
index 2b99129..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLServerSocketFactoryImpl.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-
-import javax.net.ssl.SSLServerSocketFactory;
-
-/**
- * This class creates SSL server sockets.
- *
- * @author David Brownell
- */
-final
-public class SSLServerSocketFactoryImpl extends SSLServerSocketFactory
-{
- private static final int DEFAULT_BACKLOG = 50;
- private SSLContextImpl context;
-
-
- /**
- * Constructor used to instantiate the default factory. This method is
- * only called if the old "ssl.ServerSocketFactory.provider" property in the
- * java.security file is set.
- */
- public SSLServerSocketFactoryImpl() throws Exception {
- this.context = SSLContextImpl.DefaultSSLContext.getDefaultImpl();
- }
-
- /**
- * Called from SSLContextImpl's getSSLServerSocketFactory().
- */
- SSLServerSocketFactoryImpl (SSLContextImpl context)
- {
- this.context = context;
- }
-
- /**
- * Returns an unbound server socket.
- *
- * @return the unbound socket
- * @throws IOException if the socket cannot be created
- * @see java.net.Socket#bind(java.net.SocketAddress)
- */
- public ServerSocket createServerSocket() throws IOException {
- return new SSLServerSocketImpl(context);
- }
-
- public ServerSocket createServerSocket (int port)
- throws IOException
- {
- return new SSLServerSocketImpl (port, DEFAULT_BACKLOG, context);
- }
-
-
- public ServerSocket createServerSocket (int port, int backlog)
- throws IOException
- {
- return new SSLServerSocketImpl (port, backlog, context);
- }
-
- public ServerSocket
- createServerSocket (int port, int backlog, InetAddress ifAddress)
- throws IOException
- {
- return new SSLServerSocketImpl (port, backlog, ifAddress, context);
- }
-
- /**
- * Returns the subset of the supported cipher suites which are
- * enabled by default. These cipher suites all provide a minimum
- * quality of service whereby the server authenticates itself
- * (preventing person-in-the-middle attacks) and where traffic
- * is encrypted to provide confidentiality.
- */
- public String[] getDefaultCipherSuites() {
- return context.getDefaultCipherSuiteList(true).toStringArray();
- }
-
- /**
- * Returns the names of the cipher suites which could be enabled for use
- * on an SSL connection. Normally, only a subset of these will actually
- * be enabled by default, since this list may include cipher suites which
- * do not support the mutual authentication of servers and clients, or
- * which do not protect data confidentiality. Servers may also need
- * certain kinds of certificates to use certain cipher suites.
- *
- * @return an array of cipher suite names
- */
- public String[] getSupportedCipherSuites() {
- return context.getSupportedCipherSuiteList().toStringArray();
- }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLServerSocketImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLServerSocketImpl.java
deleted file mode 100755
index c2098c1..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLServerSocketImpl.java
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.net.ServerSocket;
-
-import java.security.AlgorithmConstraints;
-
-import java.util.*;
-
-import javax.net.ServerSocketFactory;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLServerSocket;
-import javax.net.ssl.SSLParameters;
-
-
-/**
- * This class provides a simple way for servers to support conventional
- * use of the Secure Sockets Layer (SSL). Application code uses an
- * SSLServerSocketImpl exactly like it uses a regular TCP ServerSocket; the
- * difference is that the connections established are secured using SSL.
- *
- * <P> Also, the constructors take an explicit authentication context
- * parameter, giving flexibility with respect to how the server socket
- * authenticates itself. That policy flexibility is not exposed through
- * the standard SSLServerSocketFactory API.
- *
- * <P> System security defaults prevent server sockets from accepting
- * connections if they the authentication context has not been given
- * a certificate chain and its matching private key. If the clients
- * of your application support "anonymous" cipher suites, you may be
- * able to configure a server socket to accept those suites.
- *
- * @see SSLSocketImpl
- * @see SSLServerSocketFactoryImpl
- *
- * @author David Brownell
- */
-final
-class SSLServerSocketImpl extends SSLServerSocket
-{
- private SSLContextImpl sslContext;
-
- /* Do newly accepted connections require clients to authenticate? */
- private byte doClientAuth = SSLEngineImpl.clauth_none;
-
- /* Do new connections created here use the "server" mode of SSL? */
- private boolean useServerMode = true;
-
- /* Can new connections created establish new sessions? */
- private boolean enableSessionCreation = true;
-
- /* what cipher suites to use by default */
- private CipherSuiteList enabledCipherSuites = null;
-
- /* which protocol to use by default */
- private ProtocolList enabledProtocols = null;
-
- /* could enabledCipherSuites ever complete handshaking? */
- private boolean checkedEnabled = false;
-
- // the endpoint identification protocol to use by default
- private String identificationProtocol = null;
-
- // The cryptographic algorithm constraints
- private AlgorithmConstraints algorithmConstraints = null;
-
- /**
- * Create an SSL server socket on a port, using a non-default
- * authentication context and a specified connection backlog.
- *
- * @param port the port on which to listen
- * @param backlog how many connections may be pending before
- * the system should start rejecting new requests
- * @param context authentication context for this server
- */
- SSLServerSocketImpl(int port, int backlog, SSLContextImpl context)
- throws IOException, SSLException
- {
- super(port, backlog);
- initServer(context);
- }
-
-
- /**
- * Create an SSL server socket on a port, using a specified
- * authentication context and a specified backlog of connections
- * as well as a particular specified network interface. This
- * constructor is used on multihomed hosts, such as those used
- * for firewalls or as routers, to control through which interface
- * a network service is provided.
- *
- * @param port the port on which to listen
- * @param backlog how many connections may be pending before
- * the system should start rejecting new requests
- * @param address the address of the network interface through
- * which connections will be accepted
- * @param context authentication context for this server
- */
- SSLServerSocketImpl(
- int port,
- int backlog,
- InetAddress address,
- SSLContextImpl context)
- throws IOException
- {
- super(port, backlog, address);
- initServer(context);
- }
-
-
- /**
- * Creates an unbound server socket.
- */
- SSLServerSocketImpl(SSLContextImpl context) throws IOException {
- super();
- initServer(context);
- }
-
-
- /**
- * Initializes the server socket.
- */
- private void initServer(SSLContextImpl context) throws SSLException {
- if (context == null) {
- throw new SSLException("No Authentication context given");
- }
- sslContext = context;
- enabledCipherSuites = sslContext.getDefaultCipherSuiteList(true);
- enabledProtocols = sslContext.getDefaultProtocolList(true);
- }
-
- /**
- * Returns the names of the cipher suites which could be enabled for use
- * on an SSL connection. Normally, only a subset of these will actually
- * be enabled by default, since this list may include cipher suites which
- * do not support the mutual authentication of servers and clients, or
- * which do not protect data confidentiality. Servers may also need
- * certain kinds of certificates to use certain cipher suites.
- *
- * @return an array of cipher suite names
- */
- public String[] getSupportedCipherSuites() {
- return sslContext.getSupportedCipherSuiteList().toStringArray();
- }
-
- /**
- * Returns the list of cipher suites which are currently enabled
- * for use by newly accepted connections. A null return indicates
- * that the system defaults are in effect.
- */
- synchronized public String[] getEnabledCipherSuites() {
- return enabledCipherSuites.toStringArray();
- }
-
- /**
- * Controls which particular SSL cipher suites are enabled for use
- * by accepted connections.
- *
- * @param suites Names of all the cipher suites to enable; null
- * means to accept system defaults.
- */
- synchronized public void setEnabledCipherSuites(String[] suites) {
- enabledCipherSuites = new CipherSuiteList(suites);
- checkedEnabled = false;
- }
-
- public String[] getSupportedProtocols() {
- return sslContext.getSuportedProtocolList().toStringArray();
- }
-
- /**
- * Controls which protocols are enabled for use.
- * The protocols must have been listed by
- * getSupportedProtocols() as being supported.
- *
- * @param protocols protocols to enable.
- * @exception IllegalArgumentException when one of the protocols
- * named by the parameter is not supported.
- */
- synchronized public void setEnabledProtocols(String[] protocols) {
- enabledProtocols = new ProtocolList(protocols);
- }
-
- synchronized public String[] getEnabledProtocols() {
- return enabledProtocols.toStringArray();
- }
-
- /**
- * Controls whether the connections which are accepted must include
- * client authentication.
- */
- public void setNeedClientAuth(boolean flag) {
- doClientAuth = (flag ?
- SSLEngineImpl.clauth_required : SSLEngineImpl.clauth_none);
- }
-
- public boolean getNeedClientAuth() {
- return (doClientAuth == SSLEngineImpl.clauth_required);
- }
-
- /**
- * Controls whether the connections which are accepted should request
- * client authentication.
- */
- public void setWantClientAuth(boolean flag) {
- doClientAuth = (flag ?
- SSLEngineImpl.clauth_requested : SSLEngineImpl.clauth_none);
- }
-
- public boolean getWantClientAuth() {
- return (doClientAuth == SSLEngineImpl.clauth_requested);
- }
-
- /**
- * Makes the returned sockets act in SSL "client" mode, not the usual
- * server mode. The canonical example of why this is needed is for
- * FTP clients, which accept connections from servers and should be
- * rejoining the already-negotiated SSL connection.
- */
- public void setUseClientMode(boolean flag) {
- /*
- * If we need to change the socket mode and the enabled
- * protocols haven't specifically been set by the user,
- * change them to the corresponding default ones.
- */
- if (useServerMode != (!flag) &&
- sslContext.isDefaultProtocolList(enabledProtocols)) {
- enabledProtocols = sslContext.getDefaultProtocolList(!flag);
- }
-
- useServerMode = !flag;
- }
-
- public boolean getUseClientMode() {
- return !useServerMode;
- }
-
-
- /**
- * Controls whether new connections may cause creation of new SSL
- * sessions.
- */
- public void setEnableSessionCreation(boolean flag) {
- enableSessionCreation = flag;
- }
-
- /**
- * Returns true if new connections may cause creation of new SSL
- * sessions.
- */
- public boolean getEnableSessionCreation() {
- return enableSessionCreation;
- }
-
- /**
- * Returns the SSLParameters in effect for newly accepted connections.
- */
- synchronized public SSLParameters getSSLParameters() {
- SSLParameters params = super.getSSLParameters();
-
- // the super implementation does not handle the following parameters
- params.setEndpointIdentificationAlgorithm(identificationProtocol);
- params.setAlgorithmConstraints(algorithmConstraints);
-
- return params;
- }
-
- /**
- * Applies SSLParameters to newly accepted connections.
- */
- synchronized public void setSSLParameters(SSLParameters params) {
- super.setSSLParameters(params);
-
- // the super implementation does not handle the following parameters
- identificationProtocol = params.getEndpointIdentificationAlgorithm();
- algorithmConstraints = params.getAlgorithmConstraints();
- }
-
- /**
- * Accept a new SSL connection. This server identifies itself with
- * information provided in the authentication context which was
- * presented during construction.
- */
- public Socket accept() throws IOException {
- SSLSocketImpl s = new SSLSocketImpl(sslContext, useServerMode,
- enabledCipherSuites, doClientAuth, enableSessionCreation,
- enabledProtocols, identificationProtocol, algorithmConstraints);
-
- implAccept(s);
- s.doneConnect();
- return s;
- }
-
- /**
- * Provides a brief description of this SSL socket.
- */
- public String toString() {
- return "[SSL: "+ super.toString() + "]";
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLSessionContextImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLSessionContextImpl.java
deleted file mode 100755
index 756a48e..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLSessionContextImpl.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.util.Enumeration;
-import java.util.Vector;
-import java.util.Locale;
-
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSessionContext;
-
-import sun.security.util.Cache;
-
-
-final class SSLSessionContextImpl implements SSLSessionContext {
- private Cache<SessionId, SSLSessionImpl> sessionCache;
- // session cache, session id as key
- private Cache<String, SSLSessionImpl> sessionHostPortCache;
- // session cache, "host:port" as key
- private int cacheLimit; // the max cache size
- private int timeout; // timeout in seconds
-
- // package private
- SSLSessionContextImpl() {
- cacheLimit = getDefaultCacheLimit(); // default cache size
- timeout = 86400; // default, 24 hours
-
- // use soft reference
- sessionCache = Cache.newSoftMemoryCache(cacheLimit, timeout);
- sessionHostPortCache = Cache.newSoftMemoryCache(cacheLimit, timeout);
- }
-
- /**
- * Returns the <code>SSLSession</code> bound to the specified session id.
- */
- @Override
- public SSLSession getSession(byte[] sessionId) {
- if (sessionId == null) {
- throw new NullPointerException("session id cannot be null");
- }
-
- SSLSessionImpl sess = sessionCache.get(new SessionId(sessionId));
- if (!isTimedout(sess)) {
- return sess;
- }
-
- return null;
- }
-
- /**
- * Returns an enumeration of the active SSL sessions.
- */
- @Override
- public Enumeration<byte[]> getIds() {
- SessionCacheVisitor scVisitor = new SessionCacheVisitor();
- sessionCache.accept(scVisitor);
-
- return scVisitor.getSessionIds();
- }
-
- /**
- * Sets the timeout limit for cached <code>SSLSession</code> objects
- *
- * Note that after reset the timeout, the cached session before
- * should be timed within the shorter one of the old timeout and the
- * new timeout.
- */
- @Override
- public void setSessionTimeout(int seconds)
- throws IllegalArgumentException {
- if (seconds < 0) {
- throw new IllegalArgumentException();
- }
-
- if (timeout != seconds) {
- sessionCache.setTimeout(seconds);
- sessionHostPortCache.setTimeout(seconds);
- timeout = seconds;
- }
- }
-
- /**
- * Gets the timeout limit for cached <code>SSLSession</code> objects
- */
- @Override
- public int getSessionTimeout() {
- return timeout;
- }
-
- /**
- * Sets the size of the cache used for storing
- * <code>SSLSession</code> objects.
- */
- @Override
- public void setSessionCacheSize(int size)
- throws IllegalArgumentException {
- if (size < 0)
- throw new IllegalArgumentException();
-
- if (cacheLimit != size) {
- sessionCache.setCapacity(size);
- sessionHostPortCache.setCapacity(size);
- cacheLimit = size;
- }
- }
-
- /**
- * Gets the size of the cache used for storing
- * <code>SSLSession</code> objects.
- */
- @Override
- public int getSessionCacheSize() {
- return cacheLimit;
- }
-
-
- // package-private method, used ONLY by ServerHandshaker
- SSLSessionImpl get(byte[] id) {
- return (SSLSessionImpl)getSession(id);
- }
-
- // package-private method, used ONLY by ClientHandshaker
- SSLSessionImpl get(String hostname, int port) {
- /*
- * If no session caching info is available, we won't
- * get one, so exit before doing a lookup.
- */
- if (hostname == null && port == -1) {
- return null;
- }
-
- SSLSessionImpl sess = sessionHostPortCache.get(getKey(hostname, port));
- if (!isTimedout(sess)) {
- return sess;
- }
-
- return null;
- }
-
- private String getKey(String hostname, int port) {
- return (hostname + ":" +
- String.valueOf(port)).toLowerCase(Locale.ENGLISH);
- }
-
- // cache a SSLSession
- //
- // In SunJSSE implementation, a session is created while getting a
- // client hello or a server hello message, and cached while the
- // handshaking finished.
- // Here we time the session from the time it cached instead of the
- // time it created, which is a little longer than the expected. So
- // please do check isTimedout() while getting entry from the cache.
- void put(SSLSessionImpl s) {
- sessionCache.put(s.getSessionId(), s);
-
- // If no hostname/port info is available, don't add this one.
- if ((s.getPeerHost() != null) && (s.getPeerPort() != -1)) {
- sessionHostPortCache.put(
- getKey(s.getPeerHost(), s.getPeerPort()), s);
- }
-
- s.setContext(this);
- }
-
- // package-private method, remove a cached SSLSession
- void remove(SessionId key) {
- SSLSessionImpl s = sessionCache.get(key);
- if (s != null) {
- sessionCache.remove(key);
- sessionHostPortCache.remove(
- getKey(s.getPeerHost(), s.getPeerPort()));
- }
- }
-
- private int getDefaultCacheLimit() {
- int cacheLimit = 0;
- try {
- String s = java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction<String>() {
- @Override
- public String run() {
- return System.getProperty(
- "javax.net.ssl.sessionCacheSize");
- }
- });
- cacheLimit = (s != null) ? Integer.parseInt(s) : 0;
- } catch (Exception e) {
- }
-
- return (cacheLimit > 0) ? cacheLimit : 0;
- }
-
- boolean isTimedout(SSLSession sess) {
- if (timeout == 0) {
- return false;
- }
-
- if ((sess != null) && ((sess.getCreationTime() + timeout * 1000L)
- <= (System.currentTimeMillis()))) {
- sess.invalidate();
- return true;
- }
-
- return false;
- }
-
- final class SessionCacheVisitor
- implements Cache.CacheVisitor<SessionId, SSLSessionImpl> {
- Vector<byte[]> ids = null;
-
- // public void visit(java.util.Map<K,V> map) {}
- @Override
- public void visit(java.util.Map<SessionId, SSLSessionImpl> map) {
- ids = new Vector<>(map.size());
-
- for (SessionId key : map.keySet()) {
- SSLSessionImpl value = map.get(key);
- if (!isTimedout(value)) {
- ids.addElement(key.getId());
- }
- }
- }
-
- public Enumeration<byte[]> getSessionIds() {
- return ids != null ? ids.elements() :
- new Vector<byte[]>().elements();
- }
- }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLSessionImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLSessionImpl.java
deleted file mode 100755
index 110fc9c..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLSessionImpl.java
+++ /dev/null
@@ -1,832 +0,0 @@
-/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.net.*;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-import java.util.Arrays;
-import java.util.Collection;
-
-import java.security.Principal;
-import java.security.PrivateKey;
-import java.security.SecureRandom;
-import java.security.cert.X509Certificate;
-import java.security.cert.CertificateEncodingException;
-
-import javax.crypto.SecretKey;
-
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLSessionContext;
-import javax.net.ssl.SSLSessionBindingListener;
-import javax.net.ssl.SSLSessionBindingEvent;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLSession;
-import javax.net.ssl.SSLPermission;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.ExtendedSSLSession;
-
-import javax.security.auth.x500.X500Principal;
-
-import static sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.KeyExchange.*;
-
-/**
- * Implements the SSL session interface, and exposes the session context
- * which is maintained by SSL servers.
- *
- * <P> Servers have the ability to manage the sessions associated with
- * their authentication context(s). They can do this by enumerating the
- * IDs of the sessions which are cached, examining those sessions, and then
- * perhaps invalidating a given session so that it can't be used again.
- * If servers do not explicitly manage the cache, sessions will linger
- * until memory is low enough that the runtime environment purges cache
- * entries automatically to reclaim space.
- *
- * <P><em> The only reason this class is not package-private is that
- * there's no other public way to get at the server session context which
- * is associated with any given authentication context. </em>
- *
- * @author David Brownell
- */
-final class SSLSessionImpl extends ExtendedSSLSession {
-
- /*
- * we only really need a single null session
- */
- static final SSLSessionImpl nullSession = new SSLSessionImpl();
-
- // compression methods
- private static final byte compression_null = 0;
-
- /*
- * The state of a single session, as described in section 7.1
- * of the SSLv3 spec.
- */
- private final ProtocolVersion protocolVersion;
- private final SessionId sessionId;
- private X509Certificate[] peerCerts;
- private byte compressionMethod;
- private CipherSuite cipherSuite;
- private SecretKey masterSecret;
-
- /*
- * Information not part of the SSLv3 protocol spec, but used
- * to support session management policies.
- */
- private final long creationTime = System.currentTimeMillis();
- private long lastUsedTime = 0;
- private final String host;
- private final int port;
- private SSLSessionContextImpl context;
- private int sessionCount;
- private boolean invalidated;
- private X509Certificate[] localCerts;
- private PrivateKey localPrivateKey;
- private String[] localSupportedSignAlgs;
- private String[] peerSupportedSignAlgs;
-
- // Principals for non-certificate based cipher suites
- private Principal peerPrincipal;
- private Principal localPrincipal;
-
- /*
- * We count session creations, eventually for statistical data but
- * also since counters make shorter debugging IDs than the big ones
- * we use in the protocol for uniqueness-over-time.
- */
- private static volatile int counter = 0;
-
- /*
- * Use of session caches is globally enabled/disabled.
- */
- private static boolean defaultRejoinable = true;
-
- /* Class and subclass dynamic debugging support */
- private static final Debug debug = Debug.getInstance("ssl");
-
- /*
- * Create a new non-rejoinable session, using the default (null)
- * cipher spec. This constructor returns a session which could
- * be used either by a client or by a server, as a connection is
- * first opened and before handshaking begins.
- */
- private SSLSessionImpl() {
- this(ProtocolVersion.NONE, CipherSuite.C_NULL, null,
- new SessionId(false, null), null, -1);
- }
-
- /*
- * Create a new session, using a given cipher spec. This will
- * be rejoinable if session caching is enabled; the constructor
- * is intended mostly for use by serves.
- */
- SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
- Collection<SignatureAndHashAlgorithm> algorithms,
- SecureRandom generator, String host, int port) {
- this(protocolVersion, cipherSuite, algorithms,
- new SessionId(defaultRejoinable, generator), host, port);
- }
-
- /*
- * Record a new session, using a given cipher spec and session ID.
- */
- SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
- Collection<SignatureAndHashAlgorithm> algorithms,
- SessionId id, String host, int port) {
- this.protocolVersion = protocolVersion;
- sessionId = id;
- peerCerts = null;
- compressionMethod = compression_null;
- this.cipherSuite = cipherSuite;
- masterSecret = null;
- this.host = host;
- this.port = port;
- sessionCount = ++counter;
- localSupportedSignAlgs =
- SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
-
- if (debug != null && Debug.isOn("session")) {
- System.out.println("%% Initialized: " + this);
- }
- }
-
- void setMasterSecret(SecretKey secret) {
- if (masterSecret == null) {
- masterSecret = secret;
- } else {
- throw new RuntimeException("setMasterSecret() error");
- }
- }
-
- /**
- * Returns the master secret ... treat with extreme caution!
- */
- SecretKey getMasterSecret() {
- return masterSecret;
- }
-
- void setPeerCertificates(X509Certificate[] peer) {
- if (peerCerts == null) {
- peerCerts = peer;
- }
- }
-
- void setLocalCertificates(X509Certificate[] local) {
- localCerts = local;
- }
-
- void setLocalPrivateKey(PrivateKey privateKey) {
- localPrivateKey = privateKey;
- }
-
- void setPeerSupportedSignatureAlgorithms(
- Collection<SignatureAndHashAlgorithm> algorithms) {
- peerSupportedSignAlgs =
- SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
- }
-
- /**
- * Set the peer principal.
- */
- void setPeerPrincipal(Principal principal) {
- if (peerPrincipal == null) {
- peerPrincipal = principal;
- }
- }
-
- /**
- * Set the local principal.
- */
- void setLocalPrincipal(Principal principal) {
- localPrincipal = principal;
- }
-
- /**
- * Returns true iff this session may be resumed ... sessions are
- * usually resumable. Security policies may suggest otherwise,
- * for example sessions that haven't been used for a while (say,
- * a working day) won't be resumable, and sessions might have a
- * maximum lifetime in any case.
- */
- boolean isRejoinable() {
- return sessionId != null && sessionId.length() != 0 &&
- !invalidated && isLocalAuthenticationValid();
- }
-
- public synchronized boolean isValid() {
- return isRejoinable();
- }
-
- /**
- * Check if the authentication used when establishing this session
- * is still valid. Returns true if no authentication was used
- */
- boolean isLocalAuthenticationValid() {
- if (localPrivateKey != null) {
- try {
- // if the private key is no longer valid, getAlgorithm()
- // should throw an exception
- // (e.g. Smartcard has been removed from the reader)
- localPrivateKey.getAlgorithm();
- } catch (Exception e) {
- invalidate();
- return false;
- }
- }
- return true;
- }
-
- /**
- * Returns the ID for this session. The ID is fixed for the
- * duration of the session; neither it, nor its value, changes.
- */
- public byte[] getId() {
- return sessionId.getId();
- }
-
- /**
- * For server sessions, this returns the set of sessions which
- * are currently valid in this process. For client sessions,
- * this returns null.
- */
- public SSLSessionContext getSessionContext() {
- /*
- * An interim security policy until we can do something
- * more specific in 1.2. Only allow trusted code (code which
- * can set system properties) to get an
- * SSLSessionContext. This is to limit the ability of code to
- * look up specific sessions or enumerate over them. Otherwise,
- * code can only get session objects from successful SSL
- * connections which implies that they must have had permission
- * to make the network connection in the first place.
- */
- SecurityManager sm;
- if ((sm = System.getSecurityManager()) != null) {
- sm.checkPermission(new SSLPermission("getSSLSessionContext"));
- }
-
- return context;
- }
-
-
- SessionId getSessionId() {
- return sessionId;
- }
-
-
- /**
- * Returns the cipher spec in use on this session
- */
- CipherSuite getSuite() {
- return cipherSuite;
- }
-
- /**
- * Resets the cipher spec in use on this session
- */
- void setSuite(CipherSuite suite) {
- cipherSuite = suite;
-
- if (debug != null && Debug.isOn("session")) {
- System.out.println("%% Negotiating: " + this);
- }
- }
-
- /**
- * Returns the name of the cipher suite in use on this session
- */
- public String getCipherSuite() {
- return getSuite().name;
- }
-
- ProtocolVersion getProtocolVersion() {
- return protocolVersion;
- }
-
- /**
- * Returns the standard name of the protocol in use on this session
- */
- public String getProtocol() {
- return getProtocolVersion().name;
- }
-
- /**
- * Returns the compression technique used in this session
- */
- byte getCompression() {
- return compressionMethod;
- }
-
- /**
- * Returns the hashcode for this session
- */
- public int hashCode() {
- return sessionId.hashCode();
- }
-
-
- /**
- * Returns true if sessions have same ids, false otherwise.
- */
- public boolean equals(Object obj) {
-
- if (obj == this) {
- return true;
- }
-
- if (obj instanceof SSLSessionImpl) {
- SSLSessionImpl sess = (SSLSessionImpl) obj;
- return (sessionId != null) && (sessionId.equals(
- sess.getSessionId()));
- }
-
- return false;
- }
-
-
- /**
- * Return the cert chain presented by the peer in the
- * java.security.cert format.
- * Note: This method can be used only when using certificate-based
- * cipher suites; using it with non-certificate-based cipher suites,
- * such as Kerberos, will throw an SSLPeerUnverifiedException.
- *
- * @return array of peer X.509 certs, with the peer's own cert
- * first in the chain, and with the "root" CA last.
- */
- public java.security.cert.Certificate[] getPeerCertificates()
- throws SSLPeerUnverifiedException {
- //
- // clone to preserve integrity of session ... caller can't
- // change record of peer identity even by accident, much
- // less do it intentionally.
- //
- if ((cipherSuite.keyExchange == K_KRB5) ||
- (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
- throw new SSLPeerUnverifiedException("no certificates expected"
- + " for Kerberos cipher suites");
- }
- if (peerCerts == null) {
- throw new SSLPeerUnverifiedException("peer not authenticated");
- }
- // Certs are immutable objects, therefore we don't clone them.
- // But do need to clone the array, so that nothing is inserted
- // into peerCerts.
- return (java.security.cert.Certificate[])peerCerts.clone();
- }
-
- /**
- * Return the cert chain presented to the peer in the
- * java.security.cert format.
- * Note: This method is useful only when using certificate-based
- * cipher suites.
- *
- * @return array of peer X.509 certs, with the peer's own cert
- * first in the chain, and with the "root" CA last.
- */
- public java.security.cert.Certificate[] getLocalCertificates() {
- //
- // clone to preserve integrity of session ... caller can't
- // change record of peer identity even by accident, much
- // less do it intentionally.
- return (localCerts == null ? null :
- (java.security.cert.Certificate[])localCerts.clone());
- }
-
- /**
- * Return the cert chain presented by the peer in the
- * javax.security.cert format.
- * Note: This method can be used only when using certificate-based
- * cipher suites; using it with non-certificate-based cipher suites,
- * such as Kerberos, will throw an SSLPeerUnverifiedException.
- *
- * @return array of peer X.509 certs, with the peer's own cert
- * first in the chain, and with the "root" CA last.
- */
- public javax.security.cert.X509Certificate[] getPeerCertificateChain()
- throws SSLPeerUnverifiedException {
- //
- // clone to preserve integrity of session ... caller can't
- // change record of peer identity even by accident, much
- // less do it intentionally.
- //
- if ((cipherSuite.keyExchange == K_KRB5) ||
- (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
- throw new SSLPeerUnverifiedException("no certificates expected"
- + " for Kerberos cipher suites");
- }
- if (peerCerts == null) {
- throw new SSLPeerUnverifiedException("peer not authenticated");
- }
- javax.security.cert.X509Certificate[] certs;
- certs = new javax.security.cert.X509Certificate[peerCerts.length];
- for (int i = 0; i < peerCerts.length; i++) {
- byte[] der = null;
- try {
- der = peerCerts[i].getEncoded();
- certs[i] = javax.security.cert.X509Certificate.getInstance(der);
- } catch (CertificateEncodingException e) {
- throw new SSLPeerUnverifiedException(e.getMessage());
- } catch (javax.security.cert.CertificateException e) {
- throw new SSLPeerUnverifiedException(e.getMessage());
- }
- }
-
- return certs;
- }
-
- /**
- * Return the cert chain presented by the peer.
- * Note: This method can be used only when using certificate-based
- * cipher suites; using it with non-certificate-based cipher suites,
- * such as Kerberos, will throw an SSLPeerUnverifiedException.
- *
- * @return array of peer X.509 certs, with the peer's own cert
- * first in the chain, and with the "root" CA last.
- */
- public X509Certificate[] getCertificateChain()
- throws SSLPeerUnverifiedException {
- /*
- * clone to preserve integrity of session ... caller can't
- * change record of peer identity even by accident, much
- * less do it intentionally.
- */
- if ((cipherSuite.keyExchange == K_KRB5) ||
- (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
- throw new SSLPeerUnverifiedException("no certificates expected"
- + " for Kerberos cipher suites");
- }
- if (peerCerts != null) {
- return peerCerts.clone();
- } else {
- throw new SSLPeerUnverifiedException("peer not authenticated");
- }
- }
-
- /**
- * Returns the identity of the peer which was established as part of
- * defining the session.
- *
- * @return the peer's principal. Returns an X500Principal of the
- * end-entity certificate for X509-based cipher suites, and
- * Principal for Kerberos cipher suites.
- *
- * @throws SSLPeerUnverifiedException if the peer's identity has not
- * been verified
- */
- public Principal getPeerPrincipal()
- throws SSLPeerUnverifiedException
- {
- if ((cipherSuite.keyExchange == K_KRB5) ||
- (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
- if (peerPrincipal == null) {
- throw new SSLPeerUnverifiedException("peer not authenticated");
- } else {
- // Eliminate dependency on KerberosPrincipal
- return peerPrincipal;
- }
- }
- if (peerCerts == null) {
- throw new SSLPeerUnverifiedException("peer not authenticated");
- }
- return peerCerts[0].getSubjectX500Principal();
- }
-
- /**
- * Returns the principal that was sent to the peer during handshaking.
- *
- * @return the principal sent to the peer. Returns an X500Principal
- * of the end-entity certificate for X509-based cipher suites, and
- * Principal for Kerberos cipher suites. If no principal was
- * sent, then null is returned.
- */
- public Principal getLocalPrincipal() {
-
- if ((cipherSuite.keyExchange == K_KRB5) ||
- (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
- // Eliminate dependency on KerberosPrincipal
- return (localPrincipal == null ? null : localPrincipal);
- }
- return (localCerts == null ? null :
- localCerts[0].getSubjectX500Principal());
- }
-
- /**
- * Returns the time this session was created.
- */
- public long getCreationTime() {
- return creationTime;
- }
-
- /**
- * Returns the last time this session was used to initialize
- * a connection.
- */
- public long getLastAccessedTime() {
- return (lastUsedTime != 0) ? lastUsedTime : creationTime;
- }
-
- void setLastAccessedTime(long time) {
- lastUsedTime = time;
- }
-
-
- /**
- * Returns the network address of the session's peer. This
- * implementation does not insist that connections between
- * different ports on the same host must necessarily belong
- * to different sessions, though that is of course allowed.
- */
- public InetAddress getPeerAddress() {
- try {
- return InetAddress.getByName(host);
- } catch (java.net.UnknownHostException e) {
- return null;
- }
- }
-
- public String getPeerHost() {
- return host;
- }
-
- /**
- * Need to provide the port info for caching sessions based on
- * host and port. Accessed by SSLSessionContextImpl
- */
- public int getPeerPort() {
- return port;
- }
-
- void setContext(SSLSessionContextImpl ctx) {
- if (context == null) {
- context = ctx;
- }
- }
-
- /**
- * Invalidate a session. Active connections may still exist, but
- * no connections will be able to rejoin this session.
- */
- synchronized public void invalidate() {
- //
- // Can't invalidate the NULL session -- this would be
- // attempted when we get a handshaking error on a brand
- // new connection, with no "real" session yet.
- //
- if (this == nullSession) {
- return;
- }
- invalidated = true;
- if (debug != null && Debug.isOn("session")) {
- System.out.println("%% Invalidated: " + this);
- }
- if (context != null) {
- context.remove(sessionId);
- context = null;
- }
- }
-
- /*
- * Table of application-specific session data indexed by an application
- * key and the calling security context. This is important since
- * sessions can be shared across different protection domains.
- */
- private Hashtable<SecureKey, Object> table = new Hashtable<>();
-
- /**
- * Assigns a session value. Session change events are given if
- * appropriate, to any original value as well as the new value.
- */
- public void putValue(String key, Object value) {
- if ((key == null) || (value == null)) {
- throw new IllegalArgumentException("arguments can not be null");
- }
-
- SecureKey secureKey = new SecureKey(key);
- Object oldValue = table.put(secureKey, value);
-
- if (oldValue instanceof SSLSessionBindingListener) {
- SSLSessionBindingEvent e;
-
- e = new SSLSessionBindingEvent(this, key);
- ((SSLSessionBindingListener)oldValue).valueUnbound(e);
- }
- if (value instanceof SSLSessionBindingListener) {
- SSLSessionBindingEvent e;
-
- e = new SSLSessionBindingEvent(this, key);
- ((SSLSessionBindingListener)value).valueBound(e);
- }
- }
-
-
- /**
- * Returns the specified session value.
- */
- public Object getValue(String key) {
- if (key == null) {
- throw new IllegalArgumentException("argument can not be null");
- }
-
- SecureKey secureKey = new SecureKey(key);
- return table.get(secureKey);
- }
-
-
- /**
- * Removes the specified session value, delivering a session changed
- * event as appropriate.
- */
- public void removeValue(String key) {
- if (key == null) {
- throw new IllegalArgumentException("argument can not be null");
- }
-
- SecureKey secureKey = new SecureKey(key);
- Object value = table.remove(secureKey);
-
- if (value instanceof SSLSessionBindingListener) {
- SSLSessionBindingEvent e;
-
- e = new SSLSessionBindingEvent(this, key);
- ((SSLSessionBindingListener)value).valueUnbound(e);
- }
- }
-
-
- /**
- * Lists the names of the session values.
- */
- public String[] getValueNames() {
- Enumeration<SecureKey> e;
- Vector<Object> v = new Vector<>();
- SecureKey key;
- Object securityCtx = SecureKey.getCurrentSecurityContext();
-
- for (e = table.keys(); e.hasMoreElements(); ) {
- key = e.nextElement();
-
- if (securityCtx.equals(key.getSecurityContext())) {
- v.addElement(key.getAppKey());
- }
- }
- String[] names = new String[v.size()];
- v.copyInto(names);
-
- return names;
- }
-
- /**
- * Use large packet sizes now or follow RFC 2246 packet sizes (2^14)
- * until changed.
- *
- * In the TLS specification (section 6.2.1, RFC2246), it is not
- * recommended that the plaintext has more than 2^14 bytes.
- * However, some TLS implementations violate the specification.
- * This is a workaround for interoperability with these stacks.
- *
- * Application could accept large fragments up to 2^15 bytes by
- * setting the system property jsse.SSLEngine.acceptLargeFragments
- * to "true".
- */
- private boolean acceptLargeFragments =
- Debug.getBooleanProperty("jsse.SSLEngine.acceptLargeFragments", false);
-
- /**
- * Expand the buffer size of both SSL/TLS network packet and
- * application data.
- */
- protected synchronized void expandBufferSizes() {
- acceptLargeFragments = true;
- }
-
- /**
- * Gets the current size of the largest SSL/TLS packet that is expected
- * when using this session.
- */
- public synchronized int getPacketBufferSize() {
- return acceptLargeFragments ?
- Record.maxLargeRecordSize : Record.maxRecordSize;
- }
-
- /**
- * Gets the current size of the largest application data that is
- * expected when using this session.
- */
- public synchronized int getApplicationBufferSize() {
- return getPacketBufferSize() - Record.headerSize;
- }
-
- /**
- * Gets an array of supported signature algorithms that the local side is
- * willing to verify.
- */
- public String[] getLocalSupportedSignatureAlgorithms() {
- if (localSupportedSignAlgs != null) {
- return localSupportedSignAlgs.clone();
- }
-
- return new String[0];
- }
-
- /**
- * Gets an array of supported signature algorithms that the peer is
- * able to verify.
- */
- public String[] getPeerSupportedSignatureAlgorithms() {
- if (peerSupportedSignAlgs != null) {
- return peerSupportedSignAlgs.clone();
- }
-
- return new String[0];
- }
-
- /** Returns a string representation of this SSL session */
- public String toString() {
- return "[Session-" + sessionCount
- + ", " + getCipherSuite()
- + "]";
- }
-
- /**
- * When SSL sessions are finalized, all values bound to
- * them are removed.
- */
- public void finalize() {
- String[] names = getValueNames();
- for (int i = 0; i < names.length; i++) {
- removeValue(names[i]);
- }
- }
-}
-
-
-/**
- * This "struct" class serves as a Hash Key that combines an
- * application-specific key and a security context.
- */
-class SecureKey {
- private static Object nullObject = new Object();
- private Object appKey;
- private Object securityCtx;
-
- static Object getCurrentSecurityContext() {
- SecurityManager sm = System.getSecurityManager();
- Object context = null;
-
- if (sm != null)
- context = sm.getSecurityContext();
- if (context == null)
- context = nullObject;
- return context;
- }
-
- SecureKey(Object key) {
- this.appKey = key;
- this.securityCtx = getCurrentSecurityContext();
- }
-
- Object getAppKey() {
- return appKey;
- }
-
- Object getSecurityContext() {
- return securityCtx;
- }
-
- public int hashCode() {
- return appKey.hashCode() ^ securityCtx.hashCode();
- }
-
- public boolean equals(Object o) {
- return o instanceof SecureKey && ((SecureKey)o).appKey.equals(appKey)
- && ((SecureKey)o).securityCtx.equals(securityCtx);
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLSocketFactoryImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLSocketFactoryImpl.java
deleted file mode 100755
index 135b462..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLSocketFactoryImpl.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.net.*;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.SSLSocket;
-
-
-/**
- * Implementation of an SSL socket factory. This provides the public
- * hooks to create SSL sockets, using a "high level" programming
- * interface which encapsulates system security policy defaults rather than
- * offering application flexibility. In particular, it uses a configurable
- * authentication context (and the keys held there) rather than offering
- * any flexibility about which keys to use; that context defaults to the
- * process-default context, but may be explicitly specified.
- *
- * @author David Brownell
- */
-final public class SSLSocketFactoryImpl extends SSLSocketFactory {
-
- private static SSLContextImpl defaultContext;
- private SSLContextImpl context;
-
- /**
- * Constructor used to instantiate the default factory. This method is
- * only called if the old "ssl.SocketFactory.provider" property in the
- * java.security file is set.
- */
- public SSLSocketFactoryImpl() throws Exception {
- this.context = SSLContextImpl.DefaultSSLContext.getDefaultImpl();
- }
-
- /**
- * Constructs an SSL socket factory.
- */
- SSLSocketFactoryImpl(SSLContextImpl context) {
- this.context = context;
- }
-
- /**
- * Creates an unconnected socket.
- *
- * @return the unconnected socket
- * @see java.net.Socket#connect(java.net.SocketAddress, int)
- */
- public Socket createSocket() {
- return new SSLSocketImpl(context);
- }
-
- /**
- * Constructs an SSL connection to a named host at a specified port.
- * This acts as the SSL client, and may authenticate itself or rejoin
- * existing SSL sessions allowed by the authentication context which
- * has been configured.
- *
- * @param host name of the host with which to connect
- * @param port number of the server's port
- */
- public Socket createSocket(String host, int port)
- throws IOException, UnknownHostException
- {
- return new SSLSocketImpl(context, host, port);
- }
-
- /**
- * Returns a socket layered over an existing socket to a
- * ServerSocket on the named host, at the given port. This
- * constructor can be used when tunneling SSL through a proxy. The
- * host and port refer to the logical destination server. This
- * socket is configured using the socket options established for
- * this factory.
- *
- * @param s the existing socket
- * @param host the server host
- * @param port the server port
- * @param autoClose close the underlying socket when this socket is closed
- *
- * @exception IOException if the connection can't be established
- * @exception UnknownHostException if the host is not known
- */
- public Socket createSocket(Socket s, String host, int port,
- boolean autoClose) throws IOException {
- return new SSLSocketImpl(context, s, host, port, autoClose);
- }
-
-
- /**
- * Constructs an SSL connection to a server at a specified address
- * and TCP port. This acts as the SSL client, and may authenticate
- * itself or rejoin existing SSL sessions allowed by the authentication
- * context which has been configured.
- *
- * @param address the server's host
- * @param port its port
- */
- public Socket createSocket(InetAddress address, int port)
- throws IOException
- {
- return new SSLSocketImpl(context, address, port);
- }
-
-
- /**
- * Constructs an SSL connection to a named host at a specified port.
- * This acts as the SSL client, and may authenticate itself or rejoin
- * existing SSL sessions allowed by the authentication context which
- * has been configured. The socket will also bind() to the local
- * address and port supplied.
- */
- public Socket createSocket(String host, int port,
- InetAddress clientAddress, int clientPort)
- throws IOException
- {
- return new SSLSocketImpl(context, host, port,
- clientAddress, clientPort);
- }
-
- /**
- * Constructs an SSL connection to a server at a specified address
- * and TCP port. This acts as the SSL client, and may authenticate
- * itself or rejoin existing SSL sessions allowed by the authentication
- * context which has been configured. The socket will also bind() to
- * the local address and port supplied.
- */
- public Socket createSocket(InetAddress address, int port,
- InetAddress clientAddress, int clientPort)
- throws IOException
- {
- return new SSLSocketImpl(context, address, port,
- clientAddress, clientPort);
- }
-
-
- /**
- * Returns the subset of the supported cipher suites which are
- * enabled by default. These cipher suites all provide a minimum
- * quality of service whereby the server authenticates itself
- * (preventing person-in-the-middle attacks) and where traffic
- * is encrypted to provide confidentiality.
- */
- public String[] getDefaultCipherSuites() {
- return context.getDefaultCipherSuiteList(false).toStringArray();
- }
-
- /**
- * Returns the names of the cipher suites which could be enabled for use
- * on an SSL connection. Normally, only a subset of these will actually
- * be enabled by default, since this list may include cipher suites which
- * do not support the mutual authentication of servers and clients, or
- * which do not protect data confidentiality. Servers may also need
- * certain kinds of certificates to use certain cipher suites.
- */
- public String[] getSupportedCipherSuites() {
- return context.getSupportedCipherSuiteList().toStringArray();
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SSLSocketImpl.java b/ojluni/src/main/java/sun/security/ssl/SSLSocketImpl.java
deleted file mode 100755
index 37158fb..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SSLSocketImpl.java
+++ /dev/null
@@ -1,2545 +0,0 @@
-/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.net.*;
-import java.security.GeneralSecurityException;
-import java.security.AccessController;
-import java.security.AccessControlContext;
-import java.security.PrivilegedAction;
-import java.security.AlgorithmConstraints;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.ReentrantLock;
-
-import javax.crypto.BadPaddingException;
-
-import javax.net.ssl.*;
-
-import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
-
-/**
- * Implementation of an SSL socket. This is a normal connection type
- * socket, implementing SSL over some lower level socket, such as TCP.
- * Because it is layered over some lower level socket, it MUST override
- * all default socket methods.
- *
- * <P> This API offers a non-traditional option for establishing SSL
- * connections. You may first establish the connection directly, then pass
- * that connection to the SSL socket constructor with a flag saying which
- * role should be taken in the handshake protocol. (The two ends of the
- * connection must not choose the same role!) This allows setup of SSL
- * proxying or tunneling, and also allows the kind of "role reversal"
- * that is required for most FTP data transfers.
- *
- * @see javax.net.ssl.SSLSocket
- * @see SSLServerSocket
- *
- * @author David Brownell
- */
-final public class SSLSocketImpl extends BaseSSLSocketImpl {
-
- /*
- * ERROR HANDLING GUIDELINES
- * (which exceptions to throw and catch and which not to throw and catch)
- *
- * . if there is an IOException (SocketException) when accessing the
- * underlying Socket, pass it through
- *
- * . do not throw IOExceptions, throw SSLExceptions (or a subclass)
- *
- * . for internal errors (things that indicate a bug in JSSE or a
- * grossly misconfigured J2RE), throw either an SSLException or
- * a RuntimeException at your convenience.
- *
- * . handshaking code (Handshaker or HandshakeMessage) should generally
- * pass through exceptions, but can handle them if they know what to
- * do.
- *
- * . exception chaining should be used for all new code. If you happen
- * to touch old code that does not use chaining, you should change it.
- *
- * . there is a top level exception handler that sits at all entry
- * points from application code to SSLSocket read/write code. It
- * makes sure that all errors are handled (see handleException()).
- *
- * . JSSE internal code should generally not call close(), call
- * closeInternal().
- */
-
- /*
- * There's a state machine associated with each connection, which
- * among other roles serves to negotiate session changes.
- *
- * - START with constructor, until the TCP connection's around.
- * - HANDSHAKE picks session parameters before allowing traffic.
- * There are many substates due to sequencing requirements
- * for handshake messages.
- * - DATA may be transmitted.
- * - RENEGOTIATE state allows concurrent data and handshaking
- * traffic ("same" substates as HANDSHAKE), and terminates
- * in selection of new session (and connection) parameters
- * - ERROR state immediately precedes abortive disconnect.
- * - SENT_CLOSE sent a close_notify to the peer. For layered,
- * non-autoclose socket, must now read close_notify
- * from peer before closing the connection. For nonlayered or
- * non-autoclose socket, close connection and go onto
- * cs_CLOSED state.
- * - CLOSED after sending close_notify alert, & socket is closed.
- * SSL connection objects are not reused.
- * - APP_CLOSED once the application calls close(). Then it behaves like
- * a closed socket, e.g.. getInputStream() throws an Exception.
- *
- * State affects what SSL record types may legally be sent:
- *
- * - Handshake ... only in HANDSHAKE and RENEGOTIATE states
- * - App Data ... only in DATA and RENEGOTIATE states
- * - Alert ... in HANDSHAKE, DATA, RENEGOTIATE
- *
- * Re what may be received: same as what may be sent, except that
- * HandshakeRequest handshaking messages can come from servers even
- * in the application data state, to request entry to RENEGOTIATE.
- *
- * The state machine within HANDSHAKE and RENEGOTIATE states controls
- * the pending session, not the connection state, until the change
- * cipher spec and "Finished" handshake messages are processed and
- * make the "new" session become the current one.
- *
- * NOTE: details of the SMs always need to be nailed down better.
- * The text above illustrates the core ideas.
- *
- * +---->-------+------>--------->-------+
- * | | |
- * <-----< ^ ^ <-----< v
- *START>----->HANDSHAKE>----->DATA>----->RENEGOTIATE SENT_CLOSE
- * v v v | |
- * | | | | v
- * +------------+---------------+ v ERROR
- * | | |
- * v | |
- * ERROR>------>----->CLOSED<--------<----+-- +
- * |
- * v
- * APP_CLOSED
- *
- * ALSO, note that the the purpose of handshaking (renegotiation is
- * included) is to assign a different, and perhaps new, session to
- * the connection. The SSLv3 spec is a bit confusing on that new
- * protocol feature.
- */
- private static final int cs_START = 0;
- private static final int cs_HANDSHAKE = 1;
- private static final int cs_DATA = 2;
- private static final int cs_RENEGOTIATE = 3;
- private static final int cs_ERROR = 4;
- private static final int cs_SENT_CLOSE = 5;
- private static final int cs_CLOSED = 6;
- private static final int cs_APP_CLOSED = 7;
-
-
- /*
- * Client authentication be off, requested, or required.
- *
- * Migrated to SSLEngineImpl:
- * clauth_none/cl_auth_requested/clauth_required
- */
-
- /*
- * Drives the protocol state machine.
- */
- private int connectionState;
-
- /*
- * Flag indicating if the next record we receive MUST be a Finished
- * message. Temporarily set during the handshake to ensure that
- * a change cipher spec message is followed by a finished message.
- */
- private boolean expectingFinished;
-
- /*
- * For improved diagnostics, we detail connection closure
- * If the socket is closed (connectionState >= cs_ERROR),
- * closeReason != null indicates if the socket was closed
- * because of an error or because or normal shutdown.
- */
- private SSLException closeReason;
-
- /*
- * Per-connection private state that doesn't change when the
- * session is changed.
- */
- private byte doClientAuth;
- private boolean roleIsServer;
- private boolean enableSessionCreation = true;
- private String host;
- private boolean autoClose = true;
- private AccessControlContext acc;
-
- /*
- * We cannot use the hostname resolved from name services. For
- * virtual hosting, multiple hostnames may be bound to the same IP
- * address, so the hostname resolved from name services is not
- * reliable.
- */
- private String rawHostname;
-
- // The cipher suites enabled for use on this connection.
- private CipherSuiteList enabledCipherSuites;
-
- // The endpoint identification protocol
- private String identificationProtocol = null;
-
- // The cryptographic algorithm constraints
- private AlgorithmConstraints algorithmConstraints = null;
-
- /*
- * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
- * IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
- * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
- *
- * There are several locks here.
- *
- * The primary lock is the per-instance lock used by
- * synchronized(this) and the synchronized methods. It controls all
- * access to things such as the connection state and variables which
- * affect handshaking. If we are inside a synchronized method, we
- * can access the state directly, otherwise, we must use the
- * synchronized equivalents.
- *
- * The handshakeLock is used to ensure that only one thread performs
- * the *complete initial* handshake. If someone is handshaking, any
- * stray application or startHandshake() requests who find the
- * connection state is cs_HANDSHAKE will stall on handshakeLock
- * until handshaking is done. Once the handshake is done, we either
- * succeeded or failed, but we can never go back to the cs_HANDSHAKE
- * or cs_START state again.
- *
- * Note that the read/write() calls here in SSLSocketImpl are not
- * obviously synchronized. In fact, it's very nonintuitive, and
- * requires careful examination of code paths. Grab some coffee,
- * and be careful with any code changes.
- *
- * There can be only three threads active at a time in the I/O
- * subsection of this class.
- * 1. startHandshake
- * 2. AppInputStream
- * 3. AppOutputStream
- * One thread could call startHandshake().
- * AppInputStream/AppOutputStream read() and write() calls are each
- * synchronized on 'this' in their respective classes, so only one
- * app. thread will be doing a SSLSocketImpl.read() or .write()'s at
- * a time.
- *
- * If handshaking is required (state cs_HANDSHAKE), and
- * getConnectionState() for some/all threads returns cs_HANDSHAKE,
- * only one can grab the handshakeLock, and the rest will stall
- * either on getConnectionState(), or on the handshakeLock if they
- * happen to successfully race through the getConnectionState().
- *
- * If a writer is doing the initial handshaking, it must create a
- * temporary reader to read the responses from the other side. As a
- * side-effect, the writer's reader will have priority over any
- * other reader. However, the writer's reader is not allowed to
- * consume any application data. When handshakeLock is finally
- * released, we either have a cs_DATA connection, or a
- * cs_CLOSED/cs_ERROR socket.
- *
- * The writeLock is held while writing on a socket connection and
- * also to protect the MAC and cipher for their direction. The
- * writeLock is package private for Handshaker which holds it while
- * writing the ChangeCipherSpec message.
- *
- * To avoid the problem of a thread trying to change operational
- * modes on a socket while handshaking is going on, we synchronize
- * on 'this'. If handshaking has not started yet, we tell the
- * handshaker to change its mode. If handshaking has started,
- * we simply store that request until the next pending session
- * is created, at which time the new handshaker's state is set.
- *
- * The readLock is held during readRecord(), which is responsible
- * for reading an InputRecord, decrypting it, and processing it.
- * The readLock ensures that these three steps are done atomically
- * and that once started, no other thread can block on InputRecord.read.
- * This is necessary so that processing of close_notify alerts
- * from the peer are handled properly.
- */
- final private Object handshakeLock = new Object();
- final ReentrantLock writeLock = new ReentrantLock();
- final private Object readLock = new Object();
-
- private InputRecord inrec;
-
- /*
- * Crypto state that's reinitialized when the session changes.
- */
- private MAC readMAC, writeMAC;
- private CipherBox readCipher, writeCipher;
- // NOTE: compression state would be saved here
-
- /*
- * security parameters for secure renegotiation.
- */
- private boolean secureRenegotiation;
- private byte[] clientVerifyData;
- private byte[] serverVerifyData;
-
- /*
- * The authentication context holds all information used to establish
- * who this end of the connection is (certificate chains, private keys,
- * etc) and who is trusted (e.g. as CAs or websites).
- */
- private SSLContextImpl sslContext;
-
-
- /*
- * This connection is one of (potentially) many associated with
- * any given session. The output of the handshake protocol is a
- * new session ... although all the protocol description talks
- * about changing the cipher spec (and it does change), in fact
- * that's incidental since it's done by changing everything that
- * is associated with a session at the same time. (TLS/IETF may
- * change that to add client authentication w/o new key exchg.)
- */
- private Handshaker handshaker;
- private SSLSessionImpl sess;
- private volatile SSLSessionImpl handshakeSession;
-
-
- /*
- * If anyone wants to get notified about handshake completions,
- * they'll show up on this list.
- */
- private HashMap<HandshakeCompletedListener, AccessControlContext>
- handshakeListeners;
-
- /*
- * Reuse the same internal input/output streams.
- */
- private InputStream sockInput;
- private OutputStream sockOutput;
-
-
- /*
- * These input and output streams block their data in SSL records,
- * and usually arrange integrity and privacy protection for those
- * records. The guts of the SSL protocol are wrapped up in these
- * streams, and in the handshaking that establishes the details of
- * that integrity and privacy protection.
- */
- private AppInputStream input;
- private AppOutputStream output;
-
- /*
- * The protocol versions enabled for use on this connection.
- *
- * Note: we support a pseudo protocol called SSLv2Hello which when
- * set will result in an SSL v2 Hello being sent with SSL (version 3.0)
- * or TLS (version 3.1, 3.2, etc.) version info.
- */
- private ProtocolList enabledProtocols;
-
- /*
- * The SSL version associated with this connection.
- */
- private ProtocolVersion protocolVersion = ProtocolVersion.DEFAULT;
-
- /* Class and subclass dynamic debugging support */
- private static final Debug debug = Debug.getInstance("ssl");
-
- /*
- * Is it the first application record to write?
- */
- private boolean isFirstAppOutputRecord = true;
-
- /*
- * If AppOutputStream needs to delay writes of small packets, we
- * will use this to store the data until we actually do the write.
- */
- private ByteArrayOutputStream heldRecordBuffer = null;
-
- //
- // CONSTRUCTORS AND INITIALIZATION CODE
- //
-
- /**
- * Constructs an SSL connection to a named host at a specified port,
- * using the authentication context provided. This endpoint acts as
- * the client, and may rejoin an existing SSL session if appropriate.
- *
- * @param context authentication context to use
- * @param host name of the host with which to connect
- * @param port number of the server's port
- */
- SSLSocketImpl(SSLContextImpl context, String host, int port)
- throws IOException, UnknownHostException {
- super();
- this.host = host;
- this.rawHostname = host;
- init(context, false);
- SocketAddress socketAddress =
- host != null ? new InetSocketAddress(host, port) :
- new InetSocketAddress(InetAddress.getByName(null), port);
- connect(socketAddress, 0);
- }
-
-
- /**
- * Constructs an SSL connection to a server at a specified address.
- * and TCP port, using the authentication context provided. This
- * endpoint acts as the client, and may rejoin an existing SSL session
- * if appropriate.
- *
- * @param context authentication context to use
- * @param address the server's host
- * @param port its port
- */
- SSLSocketImpl(SSLContextImpl context, InetAddress host, int port)
- throws IOException {
- super();
- init(context, false);
- SocketAddress socketAddress = new InetSocketAddress(host, port);
- connect(socketAddress, 0);
- }
-
- /**
- * Constructs an SSL connection to a named host at a specified port,
- * using the authentication context provided. This endpoint acts as
- * the client, and may rejoin an existing SSL session if appropriate.
- *
- * @param context authentication context to use
- * @param host name of the host with which to connect
- * @param port number of the server's port
- * @param localAddr the local address the socket is bound to
- * @param localPort the local port the socket is bound to
- */
- SSLSocketImpl(SSLContextImpl context, String host, int port,
- InetAddress localAddr, int localPort)
- throws IOException, UnknownHostException {
- super();
- this.host = host;
- this.rawHostname = host;
- init(context, false);
- bind(new InetSocketAddress(localAddr, localPort));
- SocketAddress socketAddress =
- host != null ? new InetSocketAddress(host, port) :
- new InetSocketAddress(InetAddress.getByName(null), port);
- connect(socketAddress, 0);
- }
-
-
- /**
- * Constructs an SSL connection to a server at a specified address.
- * and TCP port, using the authentication context provided. This
- * endpoint acts as the client, and may rejoin an existing SSL session
- * if appropriate.
- *
- * @param context authentication context to use
- * @param address the server's host
- * @param port its port
- * @param localAddr the local address the socket is bound to
- * @param localPort the local port the socket is bound to
- */
- SSLSocketImpl(SSLContextImpl context, InetAddress host, int port,
- InetAddress localAddr, int localPort)
- throws IOException {
- super();
- init(context, false);
- bind(new InetSocketAddress(localAddr, localPort));
- SocketAddress socketAddress = new InetSocketAddress(host, port);
- connect(socketAddress, 0);
- }
-
- /*
- * Package-private constructor used ONLY by SSLServerSocket. The
- * java.net package accepts the TCP connection after this call is
- * made. This just initializes handshake state to use "server mode",
- * giving control over the use of SSL client authentication.
- */
- SSLSocketImpl(SSLContextImpl context, boolean serverMode,
- CipherSuiteList suites, byte clientAuth,
- boolean sessionCreation, ProtocolList protocols,
- String identificationProtocol,
- AlgorithmConstraints algorithmConstraints) throws IOException {
-
- super();
- doClientAuth = clientAuth;
- enableSessionCreation = sessionCreation;
- this.identificationProtocol = identificationProtocol;
- this.algorithmConstraints = algorithmConstraints;
- init(context, serverMode);
-
- /*
- * Override what was picked out for us.
- */
- enabledCipherSuites = suites;
- enabledProtocols = protocols;
- }
-
-
- /**
- * Package-private constructor used to instantiate an unconnected
- * socket. The java.net package will connect it, either when the
- * connect() call is made by the application. This instance is
- * meant to set handshake state to use "client mode".
- */
- SSLSocketImpl(SSLContextImpl context) {
- super();
- init(context, false);
- }
-
-
- /**
- * Layer SSL traffic over an existing connection, rather than creating
- * a new connection. The existing connection may be used only for SSL
- * traffic (using this SSLSocket) until the SSLSocket.close() call
- * returns. However, if a protocol error is detected, that existing
- * connection is automatically closed.
- *
- * <P> This particular constructor always uses the socket in the
- * role of an SSL client. It may be useful in cases which start
- * using SSL after some initial data transfers, for example in some
- * SSL tunneling applications or as part of some kinds of application
- * protocols which negotiate use of a SSL based security.
- *
- * @param sock the existing connection
- * @param context the authentication context to use
- */
- SSLSocketImpl(SSLContextImpl context, Socket sock, String host,
- int port, boolean autoClose) throws IOException {
- super(sock);
- // We always layer over a connected socket
- if (!sock.isConnected()) {
- throw new SocketException("Underlying socket is not connected");
- }
- this.host = host;
- this.rawHostname = host;
- init(context, false);
- this.autoClose = autoClose;
- doneConnect();
- }
-
- /**
- * Initializes the client socket.
- */
- private void init(SSLContextImpl context, boolean isServer) {
- sslContext = context;
- sess = SSLSessionImpl.nullSession;
- handshakeSession = null;
-
- /*
- * role is as specified, state is START until after
- * the low level connection's established.
- */
- roleIsServer = isServer;
- connectionState = cs_START;
-
- /*
- * default read and write side cipher and MAC support
- *
- * Note: compression support would go here too
- */
- readCipher = CipherBox.NULL;
- readMAC = MAC.NULL;
- writeCipher = CipherBox.NULL;
- writeMAC = MAC.NULL;
-
- // initial security parameters for secure renegotiation
- secureRenegotiation = false;
- clientVerifyData = new byte[0];
- serverVerifyData = new byte[0];
-
- enabledCipherSuites =
- sslContext.getDefaultCipherSuiteList(roleIsServer);
- enabledProtocols =
- sslContext.getDefaultProtocolList(roleIsServer);
-
- inrec = null;
-
- // save the acc
- acc = AccessController.getContext();
-
- input = new AppInputStream(this);
- output = new AppOutputStream(this);
- }
-
- /**
- * Connects this socket to the server with a specified timeout
- * value.
- *
- * This method is either called on an unconnected SSLSocketImpl by the
- * application, or it is called in the constructor of a regular
- * SSLSocketImpl. If we are layering on top on another socket, then
- * this method should not be called, because we assume that the
- * underlying socket is already connected by the time it is passed to
- * us.
- *
- * @param endpoint the <code>SocketAddress</code>
- * @param timeout the timeout value to be used, 0 is no timeout
- * @throws IOException if an error occurs during the connection
- * @throws SocketTimeoutException if timeout expires before connecting
- */
- public void connect(SocketAddress endpoint, int timeout)
- throws IOException {
-
- if (self != this) {
- throw new SocketException("Already connected");
- }
-
- if (!(endpoint instanceof InetSocketAddress)) {
- throw new SocketException(
- "Cannot handle non-Inet socket addresses.");
- }
-
- super.connect(endpoint, timeout);
- doneConnect();
- }
-
- /**
- * Initialize the handshaker and socket streams.
- *
- * Called by connect, the layered constructor, and SSLServerSocket.
- */
- void doneConnect() throws IOException {
- /*
- * Save the input and output streams. May be done only after
- * java.net actually connects using the socket "self", else
- * we get some pretty bizarre failure modes.
- */
- if (self == this) {
- sockInput = super.getInputStream();
- sockOutput = super.getOutputStream();
- } else {
- sockInput = self.getInputStream();
- sockOutput = self.getOutputStream();
- }
-
- /*
- * Move to handshaking state, with pending session initialized
- * to defaults and the appropriate kind of handshaker set up.
- */
- initHandshaker();
- }
-
- synchronized private int getConnectionState() {
- return connectionState;
- }
-
- synchronized private void setConnectionState(int state) {
- connectionState = state;
- }
-
- AccessControlContext getAcc() {
- return acc;
- }
-
- //
- // READING AND WRITING RECORDS
- //
-
- /*
- * AppOutputStream calls may need to buffer multiple outbound
- * application packets.
- *
- * All other writeRecord() calls will not buffer, so do not hold
- * these records.
- */
- void writeRecord(OutputRecord r) throws IOException {
- writeRecord(r, false);
- }
-
- /*
- * Record Output. Application data can't be sent until the first
- * handshake establishes a session.
- *
- * NOTE: we let empty records be written as a hook to force some
- * TCP-level activity, notably handshaking, to occur.
- */
- void writeRecord(OutputRecord r, boolean holdRecord) throws IOException {
- /*
- * The loop is in case of HANDSHAKE --> ERROR transitions, etc
- */
- loop:
- while (r.contentType() == Record.ct_application_data) {
- /*
- * Not all states support passing application data. We
- * synchronize access to the connection state, so that
- * synchronous handshakes can complete cleanly.
- */
- switch (getConnectionState()) {
-
- /*
- * We've deferred the initial handshaking till just now,
- * when presumably a thread's decided it's OK to block for
- * longish periods of time for I/O purposes (as well as
- * configured the cipher suites it wants to use).
- */
- case cs_HANDSHAKE:
- performInitialHandshake();
- break;
-
- case cs_DATA:
- case cs_RENEGOTIATE:
- break loop;
-
- case cs_ERROR:
- fatal(Alerts.alert_close_notify,
- "error while writing to socket");
- break; // dummy
-
- case cs_SENT_CLOSE:
- case cs_CLOSED:
- case cs_APP_CLOSED:
- // we should never get here (check in AppOutputStream)
- // this is just a fallback
- if (closeReason != null) {
- throw closeReason;
- } else {
- throw new SocketException("Socket closed");
- }
-
- /*
- * Else something's goofy in this state machine's use.
- */
- default:
- throw new SSLProtocolException("State error, send app data");
- }
- }
-
- //
- // Don't bother to really write empty records. We went this
- // far to drive the handshake machinery, for correctness; not
- // writing empty records improves performance by cutting CPU
- // time and network resource usage. However, some protocol
- // implementations are fragile and don't like to see empty
- // records, so this also increases robustness.
- //
- if (!r.isEmpty()) {
-
- // If the record is a close notify alert, we need to honor
- // socket option SO_LINGER. Note that we will try to send
- // the close notify even if the SO_LINGER set to zero.
- if (r.isAlert(Alerts.alert_close_notify) && getSoLinger() >= 0) {
-
- // keep and clear the current thread interruption status.
- boolean interrupted = Thread.interrupted();
- try {
- if (writeLock.tryLock(getSoLinger(), TimeUnit.SECONDS)) {
- try {
- writeRecordInternal(r, holdRecord);
- } finally {
- writeLock.unlock();
- }
- } else {
- SSLException ssle = new SSLException(
- "SO_LINGER timeout," +
- " close_notify message cannot be sent.");
-
-
- // For layered, non-autoclose sockets, we are not
- // able to bring them into a usable state, so we
- // treat it as fatal error.
- if (self != this && !autoClose) {
- // Note that the alert description is
- // specified as -1, so no message will be send
- // to peer anymore.
- fatal((byte)(-1), ssle);
- } else if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() +
- ", received Exception: " + ssle);
- }
-
- // RFC2246 requires that the session becomes
- // unresumable if any connection is terminated
- // without proper close_notify messages with
- // level equal to warning.
- //
- // RFC4346 no longer requires that a session not be
- // resumed if failure to properly close a connection.
- //
- // We choose to make the session unresumable if
- // failed to send the close_notify message.
- //
- sess.invalidate();
- }
- } catch (InterruptedException ie) {
- // keep interrupted status
- interrupted = true;
- }
-
- // restore the interrupted status
- if (interrupted) {
- Thread.currentThread().interrupt();
- }
- } else {
- writeLock.lock();
- try {
- writeRecordInternal(r, holdRecord);
- } finally {
- writeLock.unlock();
- }
- }
- }
- }
-
- private void writeRecordInternal(OutputRecord r,
- boolean holdRecord) throws IOException {
- // r.compress(c);
- r.addMAC(writeMAC);
- r.encrypt(writeCipher);
-
- if (holdRecord) {
- // If we were requested to delay the record due to possibility
- // of Nagle's being active when finally got to writing, and
- // it's actually not, we don't really need to delay it.
- if (getTcpNoDelay()) {
- holdRecord = false;
- } else {
- // We need to hold the record, so let's provide
- // a per-socket place to do it.
- if (heldRecordBuffer == null) {
- // Likely only need 37 bytes.
- heldRecordBuffer = new ByteArrayOutputStream(40);
- }
- }
- }
- r.write(sockOutput, holdRecord, heldRecordBuffer);
-
- /*
- * Check the sequence number state
- *
- * Note that in order to maintain the connection I/O
- * properly, we check the sequence number after the last
- * record writing process. As we request renegotiation
- * or close the connection for wrapped sequence number
- * when there is enough sequence number space left to
- * handle a few more records, so the sequence number
- * of the last record cannot be wrapped.
- */
- if (connectionState < cs_ERROR) {
- checkSequenceNumber(writeMAC, r.contentType());
- }
-
- // turn off the flag of the first application record
- if (isFirstAppOutputRecord &&
- r.contentType() == Record.ct_application_data) {
- isFirstAppOutputRecord = false;
- }
- }
-
- /*
- * Need to split the payload except the following cases:
- *
- * 1. protocol version is TLS 1.1 or later;
- * 2. bulk cipher does not use CBC mode, including null bulk cipher suites.
- * 3. the payload is the first application record of a freshly
- * negotiated TLS session.
- * 4. the CBC protection is disabled;
- *
- * More details, please refer to AppOutputStream.write(byte[], int, int).
- */
- boolean needToSplitPayload() {
- writeLock.lock();
- try {
- return (protocolVersion.v <= ProtocolVersion.TLS10.v) &&
- writeCipher.isCBCMode() && !isFirstAppOutputRecord &&
- Record.enableCBCProtection;
- } finally {
- writeLock.unlock();
- }
- }
-
- /*
- * Read an application data record. Alerts and handshake
- * messages are handled directly.
- */
- void readDataRecord(InputRecord r) throws IOException {
- if (getConnectionState() == cs_HANDSHAKE) {
- performInitialHandshake();
- }
- readRecord(r, true);
- }
-
-
- /*
- * Clear the pipeline of records from the peer, optionally returning
- * application data. Caller is responsible for knowing that it's
- * possible to do this kind of clearing, if they don't want app
- * data -- e.g. since it's the initial SSL handshake.
- *
- * Don't synchronize (this) during a blocking read() since it
- * protects data which is accessed on the write side as well.
- */
- private void readRecord(InputRecord r, boolean needAppData)
- throws IOException {
- int state;
-
- // readLock protects reading and processing of an InputRecord.
- // It keeps the reading from sockInput and processing of the record
- // atomic so that no two threads can be blocked on the
- // read from the same input stream at the same time.
- // This is required for example when a reader thread is
- // blocked on the read and another thread is trying to
- // close the socket. For a non-autoclose, layered socket,
- // the thread performing the close needs to read the close_notify.
- //
- // Use readLock instead of 'this' for locking because
- // 'this' also protects data accessed during writing.
- synchronized (readLock) {
- /*
- * Read and handle records ... return application data
- * ONLY if it's needed.
- */
-
- while (((state = getConnectionState()) != cs_CLOSED) &&
- (state != cs_ERROR) && (state != cs_APP_CLOSED)) {
- /*
- * Read a record ... maybe emitting an alert if we get a
- * comprehensible but unsupported "hello" message during
- * format checking (e.g. V2).
- */
- try {
- r.setAppDataValid(false);
- r.read(sockInput, sockOutput);
- } catch (SSLProtocolException e) {
- try {
- fatal(Alerts.alert_unexpected_message, e);
- } catch (IOException x) {
- // discard this exception
- }
- throw e;
- } catch (EOFException eof) {
- boolean handshaking = (getConnectionState() <= cs_HANDSHAKE);
- boolean rethrow = requireCloseNotify || handshaking;
- if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() +
- ", received EOFException: "
- + (rethrow ? "error" : "ignored"));
- }
- if (rethrow) {
- SSLException e;
- if (handshaking) {
- e = new SSLHandshakeException
- ("Remote host closed connection during handshake");
- } else {
- e = new SSLProtocolException
- ("Remote host closed connection incorrectly");
- }
- e.initCause(eof);
- throw e;
- } else {
- // treat as if we had received a close_notify
- closeInternal(false);
- continue;
- }
- }
-
-
- /*
- * The basic SSLv3 record protection involves (optional)
- * encryption for privacy, and an integrity check ensuring
- * data origin authentication. We do them both here, and
- * throw a fatal alert if the integrity check fails.
- */
- try {
- r.decrypt(readMAC, readCipher);
- } catch (BadPaddingException e) {
- byte alertType = (r.contentType() == Record.ct_handshake)
- ? Alerts.alert_handshake_failure
- : Alerts.alert_bad_record_mac;
- fatal(alertType, e.getMessage(), e);
- }
-
- // if (!r.decompress(c))
- // fatal(Alerts.alert_decompression_failure,
- // "decompression failure");
-
- /*
- * Process the record.
- */
- synchronized (this) {
- switch (r.contentType()) {
- case Record.ct_handshake:
- /*
- * Handshake messages always go to a pending session
- * handshaker ... if there isn't one, create one. This
- * must work asynchronously, for renegotiation.
- *
- * NOTE that handshaking will either resume a session
- * which was in the cache (and which might have other
- * connections in it already), or else will start a new
- * session (new keys exchanged) with just this connection
- * in it.
- */
- initHandshaker();
- if (!handshaker.activated()) {
- // prior to handshaking, activate the handshake
- if (connectionState == cs_RENEGOTIATE) {
- // don't use SSLv2Hello when renegotiating
- handshaker.activate(protocolVersion);
- } else {
- handshaker.activate(null);
- }
- }
-
- /*
- * process the handshake record ... may contain just
- * a partial handshake message or multiple messages.
- *
- * The handshaker state machine will ensure that it's
- * a finished message.
- */
- handshaker.process_record(r, expectingFinished);
- expectingFinished = false;
-
- if (handshaker.invalidated) {
- handshaker = null;
- // if state is cs_RENEGOTIATE, revert it to cs_DATA
- if (connectionState == cs_RENEGOTIATE) {
- connectionState = cs_DATA;
- }
- } else if (handshaker.isDone()) {
- // reset the parameters for secure renegotiation.
- secureRenegotiation =
- handshaker.isSecureRenegotiation();
- clientVerifyData = handshaker.getClientVerifyData();
- serverVerifyData = handshaker.getServerVerifyData();
-
- sess = handshaker.getSession();
- handshakeSession = null;
- handshaker = null;
- connectionState = cs_DATA;
-
- //
- // Tell folk about handshake completion, but do
- // it in a separate thread.
- //
- if (handshakeListeners != null) {
- HandshakeCompletedEvent event =
- new HandshakeCompletedEvent(this, sess);
-
- Thread t = new NotifyHandshakeThread(
- handshakeListeners.entrySet(), event);
- t.start();
- }
- }
-
- if (needAppData || connectionState != cs_DATA) {
- continue;
- }
- break;
-
- case Record.ct_application_data:
- // Pass this right back up to the application.
- if (connectionState != cs_DATA
- && connectionState != cs_RENEGOTIATE
- && connectionState != cs_SENT_CLOSE) {
- throw new SSLProtocolException(
- "Data received in non-data state: " +
- connectionState);
- }
- if (expectingFinished) {
- throw new SSLProtocolException
- ("Expecting finished message, received data");
- }
- if (!needAppData) {
- throw new SSLException("Discarding app data");
- }
-
- r.setAppDataValid(true);
- break;
-
- case Record.ct_alert:
- recvAlert(r);
- continue;
-
- case Record.ct_change_cipher_spec:
- if ((connectionState != cs_HANDSHAKE
- && connectionState != cs_RENEGOTIATE)
- || r.available() != 1
- || r.read() != 1) {
- fatal(Alerts.alert_unexpected_message,
- "illegal change cipher spec msg, state = "
- + connectionState);
- }
-
- //
- // The first message after a change_cipher_spec
- // record MUST be a "Finished" handshake record,
- // else it's a protocol violation. We force this
- // to be checked by a minor tweak to the state
- // machine.
- //
- changeReadCiphers();
- // next message MUST be a finished message
- expectingFinished = true;
- continue;
-
- default:
- //
- // TLS requires that unrecognized records be ignored.
- //
- if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() +
- ", Received record type: "
- + r.contentType());
- }
- continue;
- } // switch
-
- /*
- * Check the sequence number state
- *
- * Note that in order to maintain the connection I/O
- * properly, we check the sequence number after the last
- * record reading process. As we request renegotiation
- * or close the connection for wrapped sequence number
- * when there is enough sequence number space left to
- * handle a few more records, so the sequence number
- * of the last record cannot be wrapped.
- */
- if (connectionState < cs_ERROR) {
- checkSequenceNumber(readMAC, r.contentType());
- }
-
- return;
- } // synchronized (this)
- }
-
- //
- // couldn't read, due to some kind of error
- //
- r.close();
- return;
- } // synchronized (readLock)
- }
-
- /**
- * Check the sequence number state
- *
- * RFC 4346 states that, "Sequence numbers are of type uint64 and
- * may not exceed 2^64-1. Sequence numbers do not wrap. If a TLS
- * implementation would need to wrap a sequence number, it must
- * renegotiate instead."
- */
- private void checkSequenceNumber(MAC mac, byte type)
- throws IOException {
-
- /*
- * Don't bother to check the sequence number for error or
- * closed connections, or NULL MAC.
- */
- if (connectionState >= cs_ERROR || mac == MAC.NULL) {
- return;
- }
-
- /*
- * Conservatively, close the connection immediately when the
- * sequence number is close to overflow
- */
- if (mac.seqNumOverflow()) {
- /*
- * TLS protocols do not define a error alert for sequence
- * number overflow. We use handshake_failure error alert
- * for handshaking and bad_record_mac for other records.
- */
- if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() +
- ", sequence number extremely close to overflow " +
- "(2^64-1 packets). Closing connection.");
-
- }
-
- fatal(Alerts.alert_handshake_failure, "sequence number overflow");
- }
-
- /*
- * Ask for renegotiation when need to renew sequence number.
- *
- * Don't bother to kickstart the renegotiation when the local is
- * asking for it.
- */
- if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {
- if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() + ", request renegotiation " +
- "to avoid sequence number overflow");
- }
-
- startHandshake();
- }
- }
-
- //
- // HANDSHAKE RELATED CODE
- //
-
- /**
- * Return the AppInputStream. For use by Handshaker only.
- */
- AppInputStream getAppInputStream() {
- return input;
- }
-
- /**
- * Return the AppOutputStream. For use by Handshaker only.
- */
- AppOutputStream getAppOutputStream() {
- return output;
- }
-
- /**
- * Initialize the handshaker object. This means:
- *
- * . if a handshake is already in progress (state is cs_HANDSHAKE
- * or cs_RENEGOTIATE), do nothing and return
- *
- * . if the socket is already closed, throw an Exception (internal error)
- *
- * . otherwise (cs_START or cs_DATA), create the appropriate handshaker
- * object, and advance the connection state (to cs_HANDSHAKE or
- * cs_RENEGOTIATE, respectively).
- *
- * This method is called right after a new socket is created, when
- * starting renegotiation, or when changing client/ server mode of the
- * socket.
- */
- private void initHandshaker() {
- switch (connectionState) {
-
- //
- // Starting a new handshake.
- //
- case cs_START:
- case cs_DATA:
- break;
-
- //
- // We're already in the middle of a handshake.
- //
- case cs_HANDSHAKE:
- case cs_RENEGOTIATE:
- return;
-
- //
- // Anyone allowed to call this routine is required to
- // do so ONLY if the connection state is reasonable...
- //
- default:
- throw new IllegalStateException("Internal error");
- }
-
- // state is either cs_START or cs_DATA
- if (connectionState == cs_START) {
- connectionState = cs_HANDSHAKE;
- } else { // cs_DATA
- connectionState = cs_RENEGOTIATE;
- }
- if (roleIsServer) {
- handshaker = new ServerHandshaker(this, sslContext,
- enabledProtocols, doClientAuth,
- protocolVersion, connectionState == cs_HANDSHAKE,
- secureRenegotiation, clientVerifyData, serverVerifyData);
- } else {
- handshaker = new ClientHandshaker(this, sslContext,
- enabledProtocols,
- protocolVersion, connectionState == cs_HANDSHAKE,
- secureRenegotiation, clientVerifyData, serverVerifyData);
- }
- handshaker.setEnabledCipherSuites(enabledCipherSuites);
- handshaker.setEnableSessionCreation(enableSessionCreation);
- }
-
- /**
- * Synchronously perform the initial handshake.
- *
- * If the handshake is already in progress, this method blocks until it
- * is completed. If the initial handshake has already been completed,
- * it returns immediately.
- */
- private void performInitialHandshake() throws IOException {
- // use handshakeLock and the state check to make sure only
- // one thread performs the handshake
- synchronized (handshakeLock) {
- if (getConnectionState() == cs_HANDSHAKE) {
- kickstartHandshake();
-
- /*
- * All initial handshaking goes through this
- * InputRecord until we have a valid SSL connection.
- * Once initial handshaking is finished, AppInputStream's
- * InputRecord can handle any future renegotiation.
- *
- * Keep this local so that it goes out of scope and is
- * eventually GC'd.
- */
- if (inrec == null) {
- inrec = new InputRecord();
-
- /*
- * Grab the characteristics already assigned to
- * AppInputStream's InputRecord. Enable checking for
- * SSLv2 hellos on this first handshake.
- */
- inrec.setHandshakeHash(input.r.getHandshakeHash());
- inrec.setHelloVersion(input.r.getHelloVersion());
- inrec.enableFormatChecks();
- }
-
- readRecord(inrec, false);
- inrec = null;
- }
- }
- }
-
- /**
- * Starts an SSL handshake on this connection.
- */
- public void startHandshake() throws IOException {
- // start an ssl handshake that could be resumed from timeout exception
- startHandshake(true);
- }
-
- /**
- * Starts an ssl handshake on this connection.
- *
- * @param resumable indicates the handshake process is resumable from a
- * certain exception. If <code>resumable</code>, the socket will
- * be reserved for exceptions like timeout; otherwise, the socket
- * will be closed, no further communications could be done.
- */
- private void startHandshake(boolean resumable) throws IOException {
- checkWrite();
- try {
- if (getConnectionState() == cs_HANDSHAKE) {
- // do initial handshake
- performInitialHandshake();
- } else {
- // start renegotiation
- kickstartHandshake();
- }
- } catch (Exception e) {
- // shutdown and rethrow (wrapped) exception as appropriate
- handleException(e, resumable);
- }
- }
-
- /**
- * Kickstart the handshake if it is not already in progress.
- * This means:
- *
- * . if handshaking is already underway, do nothing and return
- *
- * . if the socket is not connected or already closed, throw an
- * Exception.
- *
- * . otherwise, call initHandshake() to initialize the handshaker
- * object and progress the state. Then, send the initial
- * handshaking message if appropriate (always on clients and
- * on servers when renegotiating).
- */
- private synchronized void kickstartHandshake() throws IOException {
-
- switch (connectionState) {
-
- case cs_HANDSHAKE:
- // handshaker already setup, proceed
- break;
-
- case cs_DATA:
- if (!secureRenegotiation && !Handshaker.allowUnsafeRenegotiation) {
- throw new SSLHandshakeException(
- "Insecure renegotiation is not allowed");
- }
-
- if (!secureRenegotiation) {
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println(
- "Warning: Using insecure renegotiation");
- }
- }
-
- // initialize the handshaker, move to cs_RENEGOTIATE
- initHandshaker();
- break;
-
- case cs_RENEGOTIATE:
- // handshaking already in progress, return
- return;
-
- /*
- * The only way to get a socket in the state is when
- * you have an unconnected socket.
- */
- case cs_START:
- throw new SocketException(
- "handshaking attempted on unconnected socket");
-
- default:
- throw new SocketException("connection is closed");
- }
-
- //
- // Kickstart handshake state machine if we need to ...
- //
- // Note that handshaker.kickstart() writes the message
- // to its HandshakeOutStream, which calls back into
- // SSLSocketImpl.writeRecord() to send it.
- //
- if (!handshaker.activated()) {
- // prior to handshaking, activate the handshake
- if (connectionState == cs_RENEGOTIATE) {
- // don't use SSLv2Hello when renegotiating
- handshaker.activate(protocolVersion);
- } else {
- handshaker.activate(null);
- }
-
- if (handshaker instanceof ClientHandshaker) {
- // send client hello
- handshaker.kickstart();
- } else {
- if (connectionState == cs_HANDSHAKE) {
- // initial handshake, no kickstart message to send
- } else {
- // we want to renegotiate, send hello request
- handshaker.kickstart();
- // hello request is not included in the handshake
- // hashes, reset them
- handshaker.handshakeHash.reset();
- }
- }
- }
- }
-
- //
- // CLOSURE RELATED CALLS
- //
-
- /**
- * Return whether the socket has been explicitly closed by the application.
- */
- public boolean isClosed() {
- return getConnectionState() == cs_APP_CLOSED;
- }
-
- /**
- * Return whether we have reached end-of-file.
- *
- * If the socket is not connected, has been shutdown because of an error
- * or has been closed, throw an Exception.
- */
- boolean checkEOF() throws IOException {
- switch (getConnectionState()) {
- case cs_START:
- throw new SocketException("Socket is not connected");
-
- case cs_HANDSHAKE:
- case cs_DATA:
- case cs_RENEGOTIATE:
- case cs_SENT_CLOSE:
- return false;
-
- case cs_APP_CLOSED:
- throw new SocketException("Socket is closed");
-
- case cs_ERROR:
- case cs_CLOSED:
- default:
- // either closed because of error, or normal EOF
- if (closeReason == null) {
- return true;
- }
- IOException e = new SSLException
- ("Connection has been shutdown: " + closeReason);
- e.initCause(closeReason);
- throw e;
-
- }
- }
-
- /**
- * Check if we can write data to this socket. If not, throw an IOException.
- */
- void checkWrite() throws IOException {
- if (checkEOF() || (getConnectionState() == cs_SENT_CLOSE)) {
- // we are at EOF, write must throw Exception
- throw new SocketException("Connection closed by remote host");
- }
- }
-
- protected void closeSocket() throws IOException {
-
- if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() + ", called closeSocket()");
- }
- if (self == this) {
- super.close();
- } else {
- self.close();
- }
- }
-
- private void closeSocket(boolean selfInitiated) throws IOException {
- if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() + ", called closeSocket(selfInitiated)");
- }
- if (self == this) {
- super.close();
- } else if (autoClose) {
- self.close();
- } else if (selfInitiated) {
- // layered && non-autoclose
- // read close_notify alert to clear input stream
- waitForClose(false);
- }
- }
-
- /*
- * Closing the connection is tricky ... we can't officially close the
- * connection until we know the other end is ready to go away too,
- * and if ever the connection gets aborted we must forget session
- * state (it becomes invalid).
- */
-
- /**
- * Closes the SSL connection. SSL includes an application level
- * shutdown handshake; you should close SSL sockets explicitly
- * rather than leaving it for finalization, so that your remote
- * peer does not experience a protocol error.
- */
- public void close() throws IOException {
- if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() + ", called close()");
- }
- closeInternal(true); // caller is initiating close
- setConnectionState(cs_APP_CLOSED);
- }
-
- /**
- * Don't synchronize the whole method because waitForClose()
- * (which calls readRecord()) might be called.
- *
- * @param selfInitiated Indicates which party initiated the close.
- * If selfInitiated, this side is initiating a close; for layered and
- * non-autoclose socket, wait for close_notify response.
- * If !selfInitiated, peer sent close_notify; we reciprocate but
- * no need to wait for response.
- */
- private void closeInternal(boolean selfInitiated) throws IOException {
- if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() + ", called closeInternal("
- + selfInitiated + ")");
- }
-
- int state = getConnectionState();
- boolean closeSocketCalled = false;
- Throwable cachedThrowable = null;
- try {
- switch (state) {
- case cs_START:
- // unconnected socket or handshaking has not been initialized
- closeSocket(selfInitiated);
- break;
-
- /*
- * If we're closing down due to error, we already sent (or else
- * received) the fatal alert ... no niceties, blow the connection
- * away as quickly as possible (even if we didn't allocate the
- * socket ourselves; it's unusable, regardless).
- */
- case cs_ERROR:
- closeSocket();
- break;
-
- /*
- * Sometimes close() gets called more than once.
- */
- case cs_CLOSED:
- case cs_APP_CLOSED:
- break;
-
- /*
- * Otherwise we indicate clean termination.
- */
- // case cs_HANDSHAKE:
- // case cs_DATA:
- // case cs_RENEGOTIATE:
- // case cs_SENT_CLOSE:
- default:
- synchronized (this) {
- if (((state = getConnectionState()) == cs_CLOSED) ||
- (state == cs_ERROR) || (state == cs_APP_CLOSED)) {
- return; // connection was closed while we waited
- }
- if (state != cs_SENT_CLOSE) {
- try {
- warning(Alerts.alert_close_notify);
- connectionState = cs_SENT_CLOSE;
- } catch (Throwable th) {
- // we need to ensure socket is closed out
- // if we encounter any errors.
- connectionState = cs_ERROR;
- // cache this for later use
- cachedThrowable = th;
- closeSocketCalled = true;
- closeSocket(selfInitiated);
- }
- }
- }
- // If state was cs_SENT_CLOSE before, we don't do the actual
- // closing since it is already in progress.
- if (state == cs_SENT_CLOSE) {
- if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() +
- ", close invoked again; state = " +
- getConnectionState());
- }
- if (selfInitiated == false) {
- // We were called because a close_notify message was
- // received. This may be due to another thread calling
- // read() or due to our call to waitForClose() below.
- // In either case, just return.
- return;
- }
- // Another thread explicitly called close(). We need to
- // wait for the closing to complete before returning.
- synchronized (this) {
- while (connectionState < cs_CLOSED) {
- try {
- this.wait();
- } catch (InterruptedException e) {
- // ignore
- }
- }
- }
- if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() +
- ", after primary close; state = " +
- getConnectionState());
- }
- return;
- }
-
- if (!closeSocketCalled) {
- closeSocketCalled = true;
- closeSocket(selfInitiated);
- }
-
- break;
- }
- } finally {
- synchronized (this) {
- // Upon exit from this method, the state is always >= cs_CLOSED
- connectionState = (connectionState == cs_APP_CLOSED)
- ? cs_APP_CLOSED : cs_CLOSED;
- // notify any threads waiting for the closing to finish
- this.notifyAll();
- }
- if (closeSocketCalled) {
- // Dispose of ciphers since we've closed socket
- disposeCiphers();
- }
- if (cachedThrowable != null) {
- /*
- * Rethrow the error to the calling method
- * The Throwable caught can only be an Error or RuntimeException
- */
- if (cachedThrowable instanceof Error)
- throw (Error) cachedThrowable;
- if (cachedThrowable instanceof RuntimeException)
- throw (RuntimeException) cachedThrowable;
- }
- }
- }
-
- /**
- * Reads a close_notify or a fatal alert from the input stream.
- * Keep reading records until we get a close_notify or until
- * the connection is otherwise closed. The close_notify or alert
- * might be read by another reader,
- * which will then process the close and set the connection state.
- */
- void waitForClose(boolean rethrow) throws IOException {
- if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() +
- ", waiting for close_notify or alert: state "
- + getConnectionState());
- }
-
- try {
- int state;
-
- while (((state = getConnectionState()) != cs_CLOSED) &&
- (state != cs_ERROR) && (state != cs_APP_CLOSED)) {
- // create the InputRecord if it isn't intialized.
- if (inrec == null) {
- inrec = new InputRecord();
- }
-
- // Ask for app data and then throw it away
- try {
- readRecord(inrec, true);
- } catch (SocketTimeoutException e) {
- // if time out, ignore the exception and continue
- }
- }
- inrec = null;
- } catch (IOException e) {
- if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() +
- ", Exception while waiting for close " +e);
- }
- if (rethrow) {
- throw e; // pass exception up
- }
- }
- }
-
- /**
- * Called by closeInternal() only. Be sure to consider the
- * synchronization locks carefully before calling it elsewhere.
- */
- private void disposeCiphers() {
- // See comment in changeReadCiphers()
- synchronized (readLock) {
- readCipher.dispose();
- }
- // See comment in changeReadCiphers()
- writeLock.lock();
- try {
- writeCipher.dispose();
- } finally {
- writeLock.unlock();
- }
- }
-
- //
- // EXCEPTION AND ALERT HANDLING
- //
-
- /**
- * Handle an exception. This method is called by top level exception
- * handlers (in read(), write()) to make sure we always shutdown the
- * connection correctly and do not pass runtime exception to the
- * application.
- */
- void handleException(Exception e) throws IOException {
- handleException(e, true);
- }
-
- /**
- * Handle an exception. This method is called by top level exception
- * handlers (in read(), write(), startHandshake()) to make sure we
- * always shutdown the connection correctly and do not pass runtime
- * exception to the application.
- *
- * This method never returns normally, it always throws an IOException.
- *
- * We first check if the socket has already been shutdown because of an
- * error. If so, we just rethrow the exception. If the socket has not
- * been shutdown, we sent a fatal alert and remember the exception.
- *
- * @param e the Exception
- * @param resumable indicates the caller process is resumable from the
- * exception. If <code>resumable</code>, the socket will be
- * reserved for exceptions like timeout; otherwise, the socket
- * will be closed, no further communications could be done.
- */
- synchronized private void handleException(Exception e, boolean resumable)
- throws IOException {
- if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName()
- + ", handling exception: " + e.toString());
- }
-
- // don't close the Socket in case of timeouts or interrupts if
- // the process is resumable.
- if (e instanceof InterruptedIOException && resumable) {
- throw (IOException)e;
- }
-
- // if we've already shutdown because of an error,
- // there is nothing to do except rethrow the exception
- if (closeReason != null) {
- if (e instanceof IOException) { // includes SSLException
- throw (IOException)e;
- } else {
- // this is odd, not an IOException.
- // normally, this should not happen
- // if closeReason has been already been set
- throw Alerts.getSSLException(Alerts.alert_internal_error, e,
- "Unexpected exception");
- }
- }
-
- // need to perform error shutdown
- boolean isSSLException = (e instanceof SSLException);
- if ((isSSLException == false) && (e instanceof IOException)) {
- // IOException from the socket
- // this means the TCP connection is already dead
- // we call fatal just to set the error status
- try {
- fatal(Alerts.alert_unexpected_message, e);
- } catch (IOException ee) {
- // ignore (IOException wrapped in SSLException)
- }
- // rethrow original IOException
- throw (IOException)e;
- }
-
- // must be SSLException or RuntimeException
- byte alertType;
- if (isSSLException) {
- if (e instanceof SSLHandshakeException) {
- alertType = Alerts.alert_handshake_failure;
- } else {
- alertType = Alerts.alert_unexpected_message;
- }
- } else {
- alertType = Alerts.alert_internal_error;
- }
- fatal(alertType, e);
- }
-
- /*
- * Send a warning alert.
- */
- void warning(byte description) {
- sendAlert(Alerts.alert_warning, description);
- }
-
- synchronized void fatal(byte description, String diagnostic)
- throws IOException {
- fatal(description, diagnostic, null);
- }
-
- synchronized void fatal(byte description, Throwable cause)
- throws IOException {
- fatal(description, null, cause);
- }
-
- /*
- * Send a fatal alert, and throw an exception so that callers will
- * need to stand on their heads to accidentally continue processing.
- */
- synchronized void fatal(byte description, String diagnostic,
- Throwable cause) throws IOException {
- if ((input != null) && (input.r != null)) {
- input.r.close();
- }
- sess.invalidate();
- if (handshakeSession != null) {
- handshakeSession.invalidate();
- }
-
- int oldState = connectionState;
- if (connectionState < cs_ERROR) {
- connectionState = cs_ERROR;
- }
-
- /*
- * Has there been an error received yet? If not, remember it.
- * By RFC 2246, we don't bother waiting for a response.
- * Fatal errors require immediate shutdown.
- */
- if (closeReason == null) {
- /*
- * Try to clear the kernel buffer to avoid TCP connection resets.
- */
- if (oldState == cs_HANDSHAKE) {
- sockInput.skip(sockInput.available());
- }
-
- // If the description equals -1, the alert won't be sent to peer.
- if (description != -1) {
- sendAlert(Alerts.alert_fatal, description);
- }
- if (cause instanceof SSLException) { // only true if != null
- closeReason = (SSLException)cause;
- } else {
- closeReason =
- Alerts.getSSLException(description, cause, diagnostic);
- }
- }
-
- /*
- * Clean up our side.
- */
- closeSocket();
- // Another thread may have disposed the ciphers during closing
- if (connectionState < cs_CLOSED) {
- connectionState = (oldState == cs_APP_CLOSED) ? cs_APP_CLOSED
- : cs_CLOSED;
-
- // We should lock readLock and writeLock if no deadlock risks.
- // See comment in changeReadCiphers()
- readCipher.dispose();
- writeCipher.dispose();
- }
-
- throw closeReason;
- }
-
-
- /*
- * Process an incoming alert ... caller must already have synchronized
- * access to "this".
- */
- private void recvAlert(InputRecord r) throws IOException {
- byte level = (byte)r.read();
- byte description = (byte)r.read();
- if (description == -1) { // check for short message
- fatal(Alerts.alert_illegal_parameter, "Short alert message");
- }
-
- if (debug != null && (Debug.isOn("record") ||
- Debug.isOn("handshake"))) {
- synchronized (System.out) {
- System.out.print(threadName());
- System.out.print(", RECV " + protocolVersion + " ALERT: ");
- if (level == Alerts.alert_fatal) {
- System.out.print("fatal, ");
- } else if (level == Alerts.alert_warning) {
- System.out.print("warning, ");
- } else {
- System.out.print("<level " + (0x0ff & level) + ">, ");
- }
- System.out.println(Alerts.alertDescription(description));
- }
- }
-
- if (level == Alerts.alert_warning) {
- if (description == Alerts.alert_close_notify) {
- if (connectionState == cs_HANDSHAKE) {
- fatal(Alerts.alert_unexpected_message,
- "Received close_notify during handshake");
- } else {
- closeInternal(false); // reply to close
- }
- } else {
-
- //
- // The other legal warnings relate to certificates,
- // e.g. no_certificate, bad_certificate, etc; these
- // are important to the handshaking code, which can
- // also handle illegal protocol alerts if needed.
- //
- if (handshaker != null) {
- handshaker.handshakeAlert(description);
- }
- }
- } else { // fatal or unknown level
- String reason = "Received fatal alert: "
- + Alerts.alertDescription(description);
- if (closeReason == null) {
- closeReason = Alerts.getSSLException(description, reason);
- }
- fatal(Alerts.alert_unexpected_message, reason);
- }
- }
-
-
- /*
- * Emit alerts. Caller must have synchronized with "this".
- */
- private void sendAlert(byte level, byte description) {
- // the connectionState cannot be cs_START
- if (connectionState >= cs_SENT_CLOSE) {
- return;
- }
-
- // For initial handshaking, don't send alert message to peer if
- // handshaker has not started.
- if (connectionState == cs_HANDSHAKE &&
- (handshaker == null || !handshaker.started())) {
- return;
- }
-
- OutputRecord r = new OutputRecord(Record.ct_alert);
- r.setVersion(protocolVersion);
-
- boolean useDebug = debug != null && Debug.isOn("ssl");
- if (useDebug) {
- synchronized (System.out) {
- System.out.print(threadName());
- System.out.print(", SEND " + protocolVersion + " ALERT: ");
- if (level == Alerts.alert_fatal) {
- System.out.print("fatal, ");
- } else if (level == Alerts.alert_warning) {
- System.out.print("warning, ");
- } else {
- System.out.print("<level = " + (0x0ff & level) + ">, ");
- }
- System.out.println("description = "
- + Alerts.alertDescription(description));
- }
- }
-
- r.write(level);
- r.write(description);
- try {
- writeRecord(r);
- } catch (IOException e) {
- if (useDebug) {
- System.out.println(threadName() +
- ", Exception sending alert: " + e);
- }
- }
- }
-
- //
- // VARIOUS OTHER METHODS
- //
-
- /*
- * When a connection finishes handshaking by enabling use of a newly
- * negotiated session, each end learns about it in two halves (read,
- * and write). When both read and write ciphers have changed, and the
- * last handshake message has been read, the connection has joined
- * (rejoined) the new session.
- *
- * NOTE: The SSLv3 spec is rather unclear on the concepts here.
- * Sessions don't change once they're established (including cipher
- * suite and master secret) but connections can join them (and leave
- * them). They're created by handshaking, though sometime handshaking
- * causes connections to join up with pre-established sessions.
- */
- private void changeReadCiphers() throws SSLException {
- if (connectionState != cs_HANDSHAKE
- && connectionState != cs_RENEGOTIATE) {
- throw new SSLProtocolException(
- "State error, change cipher specs");
- }
-
- // ... create decompressor
-
- CipherBox oldCipher = readCipher;
-
- try {
- readCipher = handshaker.newReadCipher();
- readMAC = handshaker.newReadMAC();
- } catch (GeneralSecurityException e) {
- // "can't happen"
- throw (SSLException)new SSLException
- ("Algorithm missing: ").initCause(e);
- }
-
- /*
- * Dispose of any intermediate state in the underlying cipher.
- * For PKCS11 ciphers, this will release any attached sessions,
- * and thus make finalization faster.
- *
- * Since MAC's doFinal() is called for every SSL/TLS packet, it's
- * not necessary to do the same with MAC's.
- */
- oldCipher.dispose();
- }
-
- // used by Handshaker
- void changeWriteCiphers() throws SSLException {
- if (connectionState != cs_HANDSHAKE
- && connectionState != cs_RENEGOTIATE) {
- throw new SSLProtocolException(
- "State error, change cipher specs");
- }
-
- // ... create compressor
-
- CipherBox oldCipher = writeCipher;
-
- try {
- writeCipher = handshaker.newWriteCipher();
- writeMAC = handshaker.newWriteMAC();
- } catch (GeneralSecurityException e) {
- // "can't happen"
- throw (SSLException)new SSLException
- ("Algorithm missing: ").initCause(e);
- }
-
- // See comment above.
- oldCipher.dispose();
-
- // reset the flag of the first application record
- isFirstAppOutputRecord = true;
- }
-
- /*
- * Updates the SSL version associated with this connection.
- * Called from Handshaker once it has determined the negotiated version.
- */
- synchronized void setVersion(ProtocolVersion protocolVersion) {
- this.protocolVersion = protocolVersion;
- output.r.setVersion(protocolVersion);
- }
-
- synchronized String getHost() {
- // Note that the host may be null or empty for localhost.
- if (host == null || host.length() == 0) {
- host = getInetAddress().getHostName();
- }
- return host;
- }
-
- synchronized String getRawHostname() {
- return rawHostname;
- }
-
- // ONLY used by HttpsClient to setup the URI specified hostname
- synchronized public void setHost(String host) {
- this.host = host;
- this.rawHostname = host;
- }
-
- /**
- * Gets an input stream to read from the peer on the other side.
- * Data read from this stream was always integrity protected in
- * transit, and will usually have been confidentiality protected.
- */
- synchronized public InputStream getInputStream() throws IOException {
- if (isClosed()) {
- throw new SocketException("Socket is closed");
- }
-
- /*
- * Can't call isConnected() here, because the Handshakers
- * do some initialization before we actually connect.
- */
- if (connectionState == cs_START) {
- throw new SocketException("Socket is not connected");
- }
-
- return input;
- }
-
- /**
- * Gets an output stream to write to the peer on the other side.
- * Data written on this stream is always integrity protected, and
- * will usually be confidentiality protected.
- */
- synchronized public OutputStream getOutputStream() throws IOException {
- if (isClosed()) {
- throw new SocketException("Socket is closed");
- }
-
- /*
- * Can't call isConnected() here, because the Handshakers
- * do some initialization before we actually connect.
- */
- if (connectionState == cs_START) {
- throw new SocketException("Socket is not connected");
- }
-
- return output;
- }
-
- /**
- * Returns the the SSL Session in use by this connection. These can
- * be long lived, and frequently correspond to an entire login session
- * for some user.
- */
- public SSLSession getSession() {
- /*
- * Force a synchronous handshake, if appropriate.
- */
- if (getConnectionState() == cs_HANDSHAKE) {
- try {
- // start handshaking, if failed, the connection will be closed.
- startHandshake(false);
- } catch (IOException e) {
- // handshake failed. log and return a nullSession
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println(threadName() +
- ", IOException in getSession(): " + e);
- }
- }
- }
- synchronized (this) {
- return sess;
- }
- }
-
- @Override
- synchronized public SSLSession getHandshakeSession() {
- return handshakeSession;
- }
-
- synchronized void setHandshakeSession(SSLSessionImpl session) {
- handshakeSession = session;
- }
-
- /**
- * Controls whether new connections may cause creation of new SSL
- * sessions.
- *
- * As long as handshaking has not started, we can change
- * whether we enable session creations. Otherwise,
- * we will need to wait for the next handshake.
- */
- synchronized public void setEnableSessionCreation(boolean flag) {
- enableSessionCreation = flag;
-
- if ((handshaker != null) && !handshaker.activated()) {
- handshaker.setEnableSessionCreation(enableSessionCreation);
- }
- }
-
- /**
- * Returns true if new connections may cause creation of new SSL
- * sessions.
- */
- synchronized public boolean getEnableSessionCreation() {
- return enableSessionCreation;
- }
-
-
- /**
- * Sets the flag controlling whether a server mode socket
- * *REQUIRES* SSL client authentication.
- *
- * As long as handshaking has not started, we can change
- * whether client authentication is needed. Otherwise,
- * we will need to wait for the next handshake.
- */
- synchronized public void setNeedClientAuth(boolean flag) {
- doClientAuth = (flag ?
- SSLEngineImpl.clauth_required : SSLEngineImpl.clauth_none);
-
- if ((handshaker != null) &&
- (handshaker instanceof ServerHandshaker) &&
- !handshaker.activated()) {
- ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
- }
- }
-
- synchronized public boolean getNeedClientAuth() {
- return (doClientAuth == SSLEngineImpl.clauth_required);
- }
-
- /**
- * Sets the flag controlling whether a server mode socket
- * *REQUESTS* SSL client authentication.
- *
- * As long as handshaking has not started, we can change
- * whether client authentication is requested. Otherwise,
- * we will need to wait for the next handshake.
- */
- synchronized public void setWantClientAuth(boolean flag) {
- doClientAuth = (flag ?
- SSLEngineImpl.clauth_requested : SSLEngineImpl.clauth_none);
-
- if ((handshaker != null) &&
- (handshaker instanceof ServerHandshaker) &&
- !handshaker.activated()) {
- ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
- }
- }
-
- synchronized public boolean getWantClientAuth() {
- return (doClientAuth == SSLEngineImpl.clauth_requested);
- }
-
-
- /**
- * Sets the flag controlling whether the socket is in SSL
- * client or server mode. Must be called before any SSL
- * traffic has started.
- */
- synchronized public void setUseClientMode(boolean flag) {
- switch (connectionState) {
-
- case cs_START:
- /*
- * If we need to change the socket mode and the enabled
- * protocols haven't specifically been set by the user,
- * change them to the corresponding default ones.
- */
- if (roleIsServer != (!flag) &&
- sslContext.isDefaultProtocolList(enabledProtocols)) {
- enabledProtocols = sslContext.getDefaultProtocolList(!flag);
- }
- roleIsServer = !flag;
- break;
-
- case cs_HANDSHAKE:
- /*
- * If we have a handshaker, but haven't started
- * SSL traffic, we can throw away our current
- * handshaker, and start from scratch. Don't
- * need to call doneConnect() again, we already
- * have the streams.
- */
- assert(handshaker != null);
- if (!handshaker.activated()) {
- /*
- * If we need to change the socket mode and the enabled
- * protocols haven't specifically been set by the user,
- * change them to the corresponding default ones.
- */
- if (roleIsServer != (!flag) &&
- sslContext.isDefaultProtocolList(enabledProtocols)) {
- enabledProtocols = sslContext.getDefaultProtocolList(!flag);
- }
- roleIsServer = !flag;
- connectionState = cs_START;
- initHandshaker();
- break;
- }
-
- // If handshake has started, that's an error. Fall through...
-
- default:
- if (debug != null && Debug.isOn("ssl")) {
- System.out.println(threadName() +
- ", setUseClientMode() invoked in state = " +
- connectionState);
- }
- throw new IllegalArgumentException(
- "Cannot change mode after SSL traffic has started");
- }
- }
-
- synchronized public boolean getUseClientMode() {
- return !roleIsServer;
- }
-
-
- /**
- * Returns the names of the cipher suites which could be enabled for use
- * on an SSL connection. Normally, only a subset of these will actually
- * be enabled by default, since this list may include cipher suites which
- * do not support the mutual authentication of servers and clients, or
- * which do not protect data confidentiality. Servers may also need
- * certain kinds of certificates to use certain cipher suites.
- *
- * @return an array of cipher suite names
- */
- public String[] getSupportedCipherSuites() {
- return sslContext.getSupportedCipherSuiteList().toStringArray();
- }
-
- /**
- * Controls which particular cipher suites are enabled for use on
- * this connection. The cipher suites must have been listed by
- * getCipherSuites() as being supported. Even if a suite has been
- * enabled, it might never be used if no peer supports it or the
- * requisite certificates (and private keys) are not available.
- *
- * @param suites Names of all the cipher suites to enable.
- */
- synchronized public void setEnabledCipherSuites(String[] suites) {
- enabledCipherSuites = new CipherSuiteList(suites);
- if ((handshaker != null) && !handshaker.activated()) {
- handshaker.setEnabledCipherSuites(enabledCipherSuites);
- }
- }
-
- /**
- * Returns the names of the SSL cipher suites which are currently enabled
- * for use on this connection. When an SSL socket is first created,
- * all enabled cipher suites <em>(a)</em> protect data confidentiality,
- * by traffic encryption, and <em>(b)</em> can mutually authenticate
- * both clients and servers. Thus, in some environments, this value
- * might be empty.
- *
- * @return an array of cipher suite names
- */
- synchronized public String[] getEnabledCipherSuites() {
- return enabledCipherSuites.toStringArray();
- }
-
-
- /**
- * Returns the protocols that are supported by this implementation.
- * A subset of the supported protocols may be enabled for this connection
- * @return an array of protocol names.
- */
- public String[] getSupportedProtocols() {
- return sslContext.getSuportedProtocolList().toStringArray();
- }
-
- /**
- * Controls which protocols are enabled for use on
- * this connection. The protocols must have been listed by
- * getSupportedProtocols() as being supported.
- *
- * @param protocols protocols to enable.
- * @exception IllegalArgumentException when one of the protocols
- * named by the parameter is not supported.
- */
- synchronized public void setEnabledProtocols(String[] protocols) {
- enabledProtocols = new ProtocolList(protocols);
- if ((handshaker != null) && !handshaker.activated()) {
- handshaker.setEnabledProtocols(enabledProtocols);
- }
- }
-
- synchronized public String[] getEnabledProtocols() {
- return enabledProtocols.toStringArray();
- }
-
- /**
- * Assigns the socket timeout.
- * @see java.net.Socket#setSoTimeout
- */
- public void setSoTimeout(int timeout) throws SocketException {
- if ((debug != null) && Debug.isOn("ssl")) {
- System.out.println(threadName() +
- ", setSoTimeout(" + timeout + ") called");
- }
- if (self == this) {
- super.setSoTimeout(timeout);
- } else {
- self.setSoTimeout(timeout);
- }
- }
-
- /**
- * Registers an event listener to receive notifications that an
- * SSL handshake has completed on this connection.
- */
- public synchronized void addHandshakeCompletedListener(
- HandshakeCompletedListener listener) {
- if (listener == null) {
- throw new IllegalArgumentException("listener is null");
- }
- if (handshakeListeners == null) {
- handshakeListeners = new
- HashMap<HandshakeCompletedListener, AccessControlContext>(4);
- }
- handshakeListeners.put(listener, AccessController.getContext());
- }
-
-
- /**
- * Removes a previously registered handshake completion listener.
- */
- public synchronized void removeHandshakeCompletedListener(
- HandshakeCompletedListener listener) {
- if (handshakeListeners == null) {
- throw new IllegalArgumentException("no listeners");
- }
- if (handshakeListeners.remove(listener) == null) {
- throw new IllegalArgumentException("listener not registered");
- }
- if (handshakeListeners.isEmpty()) {
- handshakeListeners = null;
- }
- }
-
- /**
- * Returns the SSLParameters in effect for this SSLSocket.
- */
- synchronized public SSLParameters getSSLParameters() {
- SSLParameters params = super.getSSLParameters();
-
- // the super implementation does not handle the following parameters
- params.setEndpointIdentificationAlgorithm(identificationProtocol);
- params.setAlgorithmConstraints(algorithmConstraints);
-
- return params;
- }
-
- /**
- * Applies SSLParameters to this socket.
- */
- synchronized public void setSSLParameters(SSLParameters params) {
- super.setSSLParameters(params);
-
- // the super implementation does not handle the following parameters
- identificationProtocol = params.getEndpointIdentificationAlgorithm();
- algorithmConstraints = params.getAlgorithmConstraints();
- if ((handshaker != null) && !handshaker.started()) {
- handshaker.setIdentificationProtocol(identificationProtocol);
- handshaker.setAlgorithmConstraints(algorithmConstraints);
- }
- }
-
- //
- // We allocate a separate thread to deliver handshake completion
- // events. This ensures that the notifications don't block the
- // protocol state machine.
- //
- private static class NotifyHandshakeThread extends Thread {
-
- private Set<Map.Entry<HandshakeCompletedListener,AccessControlContext>>
- targets; // who gets notified
- private HandshakeCompletedEvent event; // the notification
-
- NotifyHandshakeThread(
- Set<Map.Entry<HandshakeCompletedListener,AccessControlContext>>
- entrySet, HandshakeCompletedEvent e) {
-
- super("HandshakeCompletedNotify-Thread");
- targets = new HashSet<>(entrySet); // clone the entry set
- event = e;
- }
-
- public void run() {
- // Don't need to synchronize, as it only runs in one thread.
- for (Map.Entry<HandshakeCompletedListener,AccessControlContext>
- entry : targets) {
-
- final HandshakeCompletedListener l = entry.getKey();
- AccessControlContext acc = entry.getValue();
- AccessController.doPrivileged(new PrivilegedAction<Void>() {
- public Void run() {
- l.handshakeCompleted(event);
- return null;
- }
- }, acc);
- }
- }
- }
-
- /**
- * Return the name of the current thread. Utility method.
- */
- private static String threadName() {
- return Thread.currentThread().getName();
- }
-
- /**
- * Returns a printable representation of this end of the connection.
- */
- public String toString() {
- StringBuffer retval = new StringBuffer(80);
-
- retval.append(Integer.toHexString(hashCode()));
- retval.append("[");
- retval.append(sess.getCipherSuite());
- retval.append(": ");
-
- if (self == this) {
- retval.append(super.toString());
- } else {
- retval.append(self.toString());
- }
- retval.append("]");
-
- return retval.toString();
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/ServerHandshaker.java b/ojluni/src/main/java/sun/security/ssl/ServerHandshaker.java
deleted file mode 100755
index c651b44..0000000
--- a/ojluni/src/main/java/sun/security/ssl/ServerHandshaker.java
+++ /dev/null
@@ -1,1682 +0,0 @@
-/*
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.io.*;
-import java.util.*;
-import java.security.*;
-import java.security.cert.*;
-import java.security.interfaces.*;
-import java.security.spec.ECParameterSpec;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-
-import javax.net.ssl.*;
-
-import javax.security.auth.Subject;
-
-import sun.security.ssl.HandshakeMessage.*;
-import sun.security.ssl.CipherSuite.*;
-import sun.security.ssl.SignatureAndHashAlgorithm.*;
-import static sun.security.ssl.CipherSuite.*;
-import static sun.security.ssl.CipherSuite.KeyExchange.*;
-
-/**
- * ServerHandshaker does the protocol handshaking from the point
- * of view of a server. It is driven asychronously by handshake messages
- * as delivered by the parent Handshaker class, and also uses
- * common functionality (e.g. key generation) that is provided there.
- *
- * @author David Brownell
- */
-final class ServerHandshaker extends Handshaker {
-
- // is the server going to require the client to authenticate?
- private byte doClientAuth;
-
- // our authentication info
- private X509Certificate[] certs;
- private PrivateKey privateKey;
-
- private SecretKey[] kerberosKeys;
-
- // flag to check for clientCertificateVerify message
- private boolean needClientVerify = false;
-
- /*
- * For exportable ciphersuites using non-exportable key sizes, we use
- * ephemeral RSA keys. We could also do anonymous RSA in the same way
- * but there are no such ciphersuites currently defined.
- */
- private PrivateKey tempPrivateKey;
- private PublicKey tempPublicKey;
-
- /*
- * For anonymous and ephemeral Diffie-Hellman key exchange, we use
- * ephemeral Diffie-Hellman keys.
- */
- private DHCrypt dh;
-
- // Helper for ECDH based key exchanges
- private ECDHCrypt ecdh;
-
- // version request by the client in its ClientHello
- // we remember it for the RSA premaster secret version check
- private ProtocolVersion clientRequestedVersion;
-
- private SupportedEllipticCurvesExtension supportedCurves;
-
- // the preferable signature algorithm used by ServerKeyExchange message
- SignatureAndHashAlgorithm preferableSignatureAlgorithm;
-
- /*
- * Constructor ... use the keys found in the auth context.
- */
- ServerHandshaker(SSLSocketImpl socket, SSLContextImpl context,
- ProtocolList enabledProtocols, byte clientAuth,
- ProtocolVersion activeProtocolVersion, boolean isInitialHandshake,
- boolean secureRenegotiation,
- byte[] clientVerifyData, byte[] serverVerifyData) {
-
- super(socket, context, enabledProtocols,
- (clientAuth != SSLEngineImpl.clauth_none), false,
- activeProtocolVersion, isInitialHandshake, secureRenegotiation,
- clientVerifyData, serverVerifyData);
- doClientAuth = clientAuth;
- }
-
- /*
- * Constructor ... use the keys found in the auth context.
- */
- ServerHandshaker(SSLEngineImpl engine, SSLContextImpl context,
- ProtocolList enabledProtocols, byte clientAuth,
- ProtocolVersion activeProtocolVersion,
- boolean isInitialHandshake, boolean secureRenegotiation,
- byte[] clientVerifyData, byte[] serverVerifyData) {
-
- super(engine, context, enabledProtocols,
- (clientAuth != SSLEngineImpl.clauth_none), false,
- activeProtocolVersion, isInitialHandshake, secureRenegotiation,
- clientVerifyData, serverVerifyData);
- doClientAuth = clientAuth;
- }
-
- /*
- * As long as handshaking has not started, we can change
- * whether client authentication is required. Otherwise,
- * we will need to wait for the next handshake.
- */
- void setClientAuth(byte clientAuth) {
- doClientAuth = clientAuth;
- }
-
- /*
- * This routine handles all the server side handshake messages, one at
- * a time. Given the message type (and in some cases the pending cipher
- * spec) it parses the type-specific message. Then it calls a function
- * that handles that specific message.
- *
- * It updates the state machine as each message is processed, and writes
- * responses as needed using the connection in the constructor.
- */
- void processMessage(byte type, int message_len)
- throws IOException {
- //
- // In SSLv3 and TLS, messages follow strictly increasing
- // numerical order _except_ for one annoying special case.
- //
- if ((state >= type)
- && (state != HandshakeMessage.ht_client_key_exchange
- && type != HandshakeMessage.ht_certificate_verify)) {
- throw new SSLProtocolException(
- "Handshake message sequence violation, state = " + state
- + ", type = " + type);
- }
-
- switch (type) {
- case HandshakeMessage.ht_client_hello:
- ClientHello ch = new ClientHello(input, message_len);
- /*
- * send it off for processing.
- */
- this.clientHello(ch);
- break;
-
- case HandshakeMessage.ht_certificate:
- if (doClientAuth == SSLEngineImpl.clauth_none) {
- fatalSE(Alerts.alert_unexpected_message,
- "client sent unsolicited cert chain");
- // NOTREACHED
- }
- this.clientCertificate(new CertificateMsg(input));
- break;
-
- case HandshakeMessage.ht_client_key_exchange:
- SecretKey preMasterSecret;
- switch (keyExchange) {
- case K_RSA:
- case K_RSA_EXPORT:
- /*
- * The client's pre-master secret is decrypted using
- * either the server's normal private RSA key, or the
- * temporary one used for non-export or signing-only
- * certificates/keys.
- */
- RSAClientKeyExchange pms = new RSAClientKeyExchange(
- protocolVersion, clientRequestedVersion,
- sslContext.getSecureRandom(), input,
- message_len, privateKey);
- preMasterSecret = this.clientKeyExchange(pms);
- break;
- case K_KRB5:
- case K_KRB5_EXPORT:
- preMasterSecret = this.clientKeyExchange(
- new KerberosClientKeyExchange(protocolVersion,
- clientRequestedVersion,
- sslContext.getSecureRandom(),
- input,
- kerberosKeys));
- break;
- case K_DHE_RSA:
- case K_DHE_DSS:
- case K_DH_ANON:
- /*
- * The pre-master secret is derived using the normal
- * Diffie-Hellman calculation. Note that the main
- * protocol difference in these five flavors is in how
- * the ServerKeyExchange message was constructed!
- */
- preMasterSecret = this.clientKeyExchange(
- new DHClientKeyExchange(input));
- break;
- case K_ECDH_RSA:
- case K_ECDH_ECDSA:
- case K_ECDHE_RSA:
- case K_ECDHE_ECDSA:
- case K_ECDH_ANON:
- preMasterSecret = this.clientKeyExchange
- (new ECDHClientKeyExchange(input));
- break;
- default:
- throw new SSLProtocolException
- ("Unrecognized key exchange: " + keyExchange);
- }
-
- //
- // All keys are calculated from the premaster secret
- // and the exchanged nonces in the same way.
- //
- calculateKeys(preMasterSecret, clientRequestedVersion);
- break;
-
- case HandshakeMessage.ht_certificate_verify:
- this.clientCertificateVerify(new CertificateVerify(input,
- localSupportedSignAlgs, protocolVersion));
- break;
-
- case HandshakeMessage.ht_finished:
- this.clientFinished(
- new Finished(protocolVersion, input, cipherSuite));
- break;
-
- default:
- throw new SSLProtocolException(
- "Illegal server handshake msg, " + type);
- }
-
- //
- // Move state machine forward if the message handling
- // code didn't already do so
- //
- if (state < type) {
- if(type == HandshakeMessage.ht_certificate_verify) {
- state = type + 2; // an annoying special case
- } else {
- state = type;
- }
- }
- }
-
-
- /*
- * ClientHello presents the server with a bunch of options, to which the
- * server replies with a ServerHello listing the ones which this session
- * will use. If needed, it also writes its Certificate plus in some cases
- * a ServerKeyExchange message. It may also write a CertificateRequest,
- * to elicit a client certificate.
- *
- * All these messages are terminated by a ServerHelloDone message. In
- * most cases, all this can be sent in a single Record.
- */
- private void clientHello(ClientHello mesg) throws IOException {
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
-
- // Does the message include security renegotiation indication?
- boolean renegotiationIndicated = false;
-
- // check the TLS_EMPTY_RENEGOTIATION_INFO_SCSV
- CipherSuiteList cipherSuites = mesg.getCipherSuites();
- if (cipherSuites.contains(CipherSuite.C_SCSV)) {
- renegotiationIndicated = true;
- if (isInitialHandshake) {
- secureRenegotiation = true;
- } else {
- // abort the handshake with a fatal handshake_failure alert
- if (secureRenegotiation) {
- fatalSE(Alerts.alert_handshake_failure,
- "The SCSV is present in a secure renegotiation");
- } else {
- fatalSE(Alerts.alert_handshake_failure,
- "The SCSV is present in a insecure renegotiation");
- }
- }
- }
-
- // check the "renegotiation_info" extension
- RenegotiationInfoExtension clientHelloRI = (RenegotiationInfoExtension)
- mesg.extensions.get(ExtensionType.EXT_RENEGOTIATION_INFO);
- if (clientHelloRI != null) {
- renegotiationIndicated = true;
- if (isInitialHandshake) {
- // verify the length of the "renegotiated_connection" field
- if (!clientHelloRI.isEmpty()) {
- // abort the handshake with a fatal handshake_failure alert
- fatalSE(Alerts.alert_handshake_failure,
- "The renegotiation_info field is not empty");
- }
-
- secureRenegotiation = true;
- } else {
- if (!secureRenegotiation) {
- // unexpected RI extension for insecure renegotiation,
- // abort the handshake with a fatal handshake_failure alert
- fatalSE(Alerts.alert_handshake_failure,
- "The renegotiation_info is present in a insecure " +
- "renegotiation");
- }
-
- // verify the client_verify_data value
- if (!Arrays.equals(clientVerifyData,
- clientHelloRI.getRenegotiatedConnection())) {
- fatalSE(Alerts.alert_handshake_failure,
- "Incorrect verify data in ClientHello " +
- "renegotiation_info message");
- }
- }
- } else if (!isInitialHandshake && secureRenegotiation) {
- // if the connection's "secure_renegotiation" flag is set to TRUE
- // and the "renegotiation_info" extension is not present, abort
- // the handshake.
- fatalSE(Alerts.alert_handshake_failure,
- "Inconsistent secure renegotiation indication");
- }
-
- // if there is no security renegotiation indication or the previous
- // handshake is insecure.
- if (!renegotiationIndicated || !secureRenegotiation) {
- if (isInitialHandshake) {
- if (!allowLegacyHelloMessages) {
- // abort the handshake with a fatal handshake_failure alert
- fatalSE(Alerts.alert_handshake_failure,
- "Failed to negotiate the use of secure renegotiation");
- }
-
- // continue with legacy ClientHello
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println("Warning: No renegotiation " +
- "indication in ClientHello, allow legacy ClientHello");
- }
- } else if (!allowUnsafeRenegotiation) {
- // abort the handshake
- if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
- // response with a no_renegotiation warning,
- warningSE(Alerts.alert_no_renegotiation);
-
- // invalidate the handshake so that the caller can
- // dispose this object.
- invalidated = true;
-
- // If there is still unread block in the handshake
- // input stream, it would be truncated with the disposal
- // and the next handshake message will become incomplete.
- //
- // However, according to SSL/TLS specifications, no more
- // handshake message could immediately follow ClientHello
- // or HelloRequest. But in case of any improper messages,
- // we'd better check to ensure there is no remaining bytes
- // in the handshake input stream.
- if (input.available() > 0) {
- fatalSE(Alerts.alert_unexpected_message,
- "ClientHello followed by an unexpected " +
- "handshake message");
- }
-
- return;
- } else {
- // For SSLv3, send the handshake_failure fatal error.
- // Note that SSLv3 does not define a no_renegotiation
- // alert like TLSv1. However we cannot ignore the message
- // simply, otherwise the other side was waiting for a
- // response that would never come.
- fatalSE(Alerts.alert_handshake_failure,
- "Renegotiation is not allowed");
- }
- } else { // !isInitialHandshake && allowUnsafeRenegotiation
- // continue with unsafe renegotiation.
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println(
- "Warning: continue with insecure renegotiation");
- }
- }
- }
-
- /*
- * Always make sure this entire record has been digested before we
- * start emitting output, to ensure correct digesting order.
- */
- input.digestNow();
-
- /*
- * FIRST, construct the ServerHello using the options and priorities
- * from the ClientHello. Update the (pending) cipher spec as we do
- * so, and save the client's version to protect against rollback
- * attacks.
- *
- * There are a bunch of minor tasks here, and one major one: deciding
- * if the short or the full handshake sequence will be used.
- */
- ServerHello m1 = new ServerHello();
-
- clientRequestedVersion = mesg.protocolVersion;
-
- // select a proper protocol version.
- ProtocolVersion selectedVersion =
- selectProtocolVersion(clientRequestedVersion);
- if (selectedVersion == null ||
- selectedVersion.v == ProtocolVersion.SSL20Hello.v) {
- fatalSE(Alerts.alert_handshake_failure,
- "Client requested protocol " + clientRequestedVersion +
- " not enabled or not supported");
- }
-
- handshakeHash.protocolDetermined(selectedVersion);
- setVersion(selectedVersion);
-
- m1.protocolVersion = protocolVersion;
-
- //
- // random ... save client and server values for later use
- // in computing the master secret (from pre-master secret)
- // and thence the other crypto keys.
- //
- // NOTE: this use of three inputs to generating _each_ set
- // of ciphers slows things down, but it does increase the
- // security since each connection in the session can hold
- // its own authenticated (and strong) keys. One could make
- // creation of a session a rare thing...
- //
- clnt_random = mesg.clnt_random;
- svr_random = new RandomCookie(sslContext.getSecureRandom());
- m1.svr_random = svr_random;
-
- session = null; // forget about the current session
- //
- // Here we go down either of two paths: (a) the fast one, where
- // the client's asked to rejoin an existing session, and the server
- // permits this; (b) the other one, where a new session is created.
- //
- if (mesg.sessionId.length() != 0) {
- // client is trying to resume a session, let's see...
-
- SSLSessionImpl previous = ((SSLSessionContextImpl)sslContext
- .engineGetServerSessionContext())
- .get(mesg.sessionId.getId());
- //
- // Check if we can use the fast path, resuming a session. We
- // can do so iff we have a valid record for that session, and
- // the cipher suite for that session was on the list which the
- // client requested, and if we're not forgetting any needed
- // authentication on the part of the client.
- //
- if (previous != null) {
- resumingSession = previous.isRejoinable();
-
- if (resumingSession) {
- ProtocolVersion oldVersion = previous.getProtocolVersion();
- // cannot resume session with different version
- if (oldVersion != protocolVersion) {
- resumingSession = false;
- }
- }
-
- if (resumingSession &&
- (doClientAuth == SSLEngineImpl.clauth_required)) {
- try {
- previous.getPeerPrincipal();
- } catch (SSLPeerUnverifiedException e) {
- resumingSession = false;
- }
- }
-
- // validate subject identity
- if (resumingSession) {
- CipherSuite suite = previous.getSuite();
- if (suite.keyExchange == K_KRB5 ||
- suite.keyExchange == K_KRB5_EXPORT) {
- Principal localPrincipal = previous.getLocalPrincipal();
-
- Subject subject = null;
- try {
- subject = AccessController.doPrivileged(
- new PrivilegedExceptionAction<Subject>() {
- public Subject run() throws Exception {
- return
- Krb5Helper.getServerSubject(getAccSE());
- }});
- } catch (PrivilegedActionException e) {
- subject = null;
- if (debug != null && Debug.isOn("session")) {
- System.out.println("Attempt to obtain" +
- " subject failed!");
- }
- }
-
- if (subject != null) {
- // Eliminate dependency on KerberosPrincipal
- Set<Principal> principals =
- subject.getPrincipals(Principal.class);
- if (!principals.contains(localPrincipal)) {
- resumingSession = false;
- if (debug != null && Debug.isOn("session")) {
- System.out.println("Subject identity" +
- " is not the same");
- }
- } else {
- if (debug != null && Debug.isOn("session"))
- System.out.println("Subject identity" +
- " is same");
- }
- } else {
- resumingSession = false;
- if (debug != null && Debug.isOn("session"))
- System.out.println("Kerberos credentials are" +
- " not present in the current Subject;" +
- " check if " +
- " javax.security.auth.useSubjectAsCreds" +
- " system property has been set to false");
- }
- }
- }
-
- if (resumingSession) {
- CipherSuite suite = previous.getSuite();
- // verify that the ciphersuite from the cached session
- // is in the list of client requested ciphersuites and
- // we have it enabled
- if ((isNegotiable(suite) == false) ||
- (mesg.getCipherSuites().contains(suite) == false)) {
- resumingSession = false;
- } else {
- // everything looks ok, set the ciphersuite
- // this should be done last when we are sure we
- // will resume
- setCipherSuite(suite);
- }
- }
-
- if (resumingSession) {
- session = previous;
- if (debug != null &&
- (Debug.isOn("handshake") || Debug.isOn("session"))) {
- System.out.println("%% Resuming " + session);
- }
- }
- }
- } // else client did not try to resume
-
- //
- // If client hasn't specified a session we can resume, start a
- // new one and choose its cipher suite and compression options.
- // Unless new session creation is disabled for this connection!
- //
- if (session == null) {
- if (!enableNewSession) {
- throw new SSLException("Client did not resume a session");
- }
-
- supportedCurves = (SupportedEllipticCurvesExtension)
- mesg.extensions.get(ExtensionType.EXT_ELLIPTIC_CURVES);
-
- // We only need to handle the "signature_algorithm" extension
- // for full handshakes and TLS 1.2 or later.
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- SignatureAlgorithmsExtension signAlgs =
- (SignatureAlgorithmsExtension)mesg.extensions.get(
- ExtensionType.EXT_SIGNATURE_ALGORITHMS);
- if (signAlgs != null) {
- Collection<SignatureAndHashAlgorithm> peerSignAlgs =
- signAlgs.getSignAlgorithms();
- if (peerSignAlgs == null || peerSignAlgs.isEmpty()) {
- throw new SSLHandshakeException(
- "No peer supported signature algorithms");
- }
-
- Collection<SignatureAndHashAlgorithm>
- supportedPeerSignAlgs =
- SignatureAndHashAlgorithm.getSupportedAlgorithms(
- peerSignAlgs);
- if (supportedPeerSignAlgs.isEmpty()) {
- throw new SSLHandshakeException(
- "No supported signature and hash algorithm " +
- "in common");
- }
-
- setPeerSupportedSignAlgs(supportedPeerSignAlgs);
- } // else, need to use peer implicit supported signature algs
- }
-
- session = new SSLSessionImpl(protocolVersion, CipherSuite.C_NULL,
- getLocalSupportedSignAlgs(),
- sslContext.getSecureRandom(),
- getHostAddressSE(), getPortSE());
-
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- if (peerSupportedSignAlgs != null) {
- session.setPeerSupportedSignatureAlgorithms(
- peerSupportedSignAlgs);
- } // else, we will set the implicit peer supported signature
- // algorithms in chooseCipherSuite()
- }
-
- // set the handshake session
- setHandshakeSessionSE(session);
-
- // choose cipher suite and corresponding private key
- chooseCipherSuite(mesg);
-
- session.setSuite(cipherSuite);
- session.setLocalPrivateKey(privateKey);
-
- // chooseCompression(mesg);
- } else {
- // set the handshake session
- setHandshakeSessionSE(session);
- }
-
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- if (resumingSession) {
- handshakeHash.setCertificateVerifyAlg(null);
- }
- handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg());
- }
-
- m1.cipherSuite = cipherSuite;
- m1.sessionId = session.getSessionId();
- m1.compression_method = session.getCompression();
-
- if (secureRenegotiation) {
- // For ServerHellos that are initial handshakes, then the
- // "renegotiated_connection" field in "renegotiation_info"
- // extension is of zero length.
- //
- // For ServerHellos that are renegotiating, this field contains
- // the concatenation of client_verify_data and server_verify_data.
- //
- // Note that for initial handshakes, both the clientVerifyData
- // variable and serverVerifyData variable are of zero length.
- HelloExtension serverHelloRI = new RenegotiationInfoExtension(
- clientVerifyData, serverVerifyData);
- m1.extensions.add(serverHelloRI);
- }
-
- if (debug != null && Debug.isOn("handshake")) {
- m1.print(System.out);
- System.out.println("Cipher suite: " + session.getSuite());
- }
- m1.write(output);
-
- //
- // If we are resuming a session, we finish writing handshake
- // messages right now and then finish.
- //
- if (resumingSession) {
- calculateConnectionKeys(session.getMasterSecret());
- sendChangeCipherAndFinish(false);
- return;
- }
-
-
- /*
- * SECOND, write the server Certificate(s) if we need to.
- *
- * NOTE: while an "anonymous RSA" mode is explicitly allowed by
- * the protocol, we can't support it since all of the SSL flavors
- * defined in the protocol spec are explicitly stated to require
- * using RSA certificates.
- */
- if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
- // Server certificates are omitted for Kerberos ciphers
-
- } else if ((keyExchange != K_DH_ANON) && (keyExchange != K_ECDH_ANON)) {
- if (certs == null) {
- throw new RuntimeException("no certificates");
- }
-
- CertificateMsg m2 = new CertificateMsg(certs);
-
- /*
- * Set local certs in the SSLSession, output
- * debug info, and then actually write to the client.
- */
- session.setLocalCertificates(certs);
- if (debug != null && Debug.isOn("handshake")) {
- m2.print(System.out);
- }
- m2.write(output);
-
- // XXX has some side effects with OS TCP buffering,
- // leave it out for now
-
- // let client verify chain in the meantime...
- // output.flush();
- } else {
- if (certs != null) {
- throw new RuntimeException("anonymous keyexchange with certs");
- }
- }
-
- /*
- * THIRD, the ServerKeyExchange message ... iff it's needed.
- *
- * It's usually needed unless there's an encryption-capable
- * RSA cert, or a D-H cert. The notable exception is that
- * exportable ciphers used with big RSA keys need to downgrade
- * to use short RSA keys, even when the key/cert encrypts OK.
- */
-
- ServerKeyExchange m3;
- switch (keyExchange) {
- case K_RSA:
- case K_KRB5:
- case K_KRB5_EXPORT:
- // no server key exchange for RSA or KRB5 ciphersuites
- m3 = null;
- break;
- case K_RSA_EXPORT:
- if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
- try {
- m3 = new RSA_ServerKeyExchange(
- tempPublicKey, privateKey,
- clnt_random, svr_random,
- sslContext.getSecureRandom());
- privateKey = tempPrivateKey;
- } catch (GeneralSecurityException e) {
- throwSSLException
- ("Error generating RSA server key exchange", e);
- m3 = null; // make compiler happy
- }
- } else {
- // RSA_EXPORT with short key, don't need ServerKeyExchange
- m3 = null;
- }
- break;
- case K_DHE_RSA:
- case K_DHE_DSS:
- try {
- m3 = new DH_ServerKeyExchange(dh,
- privateKey,
- clnt_random.random_bytes,
- svr_random.random_bytes,
- sslContext.getSecureRandom(),
- preferableSignatureAlgorithm,
- protocolVersion);
- } catch (GeneralSecurityException e) {
- throwSSLException("Error generating DH server key exchange", e);
- m3 = null; // make compiler happy
- }
- break;
- case K_DH_ANON:
- m3 = new DH_ServerKeyExchange(dh, protocolVersion);
- break;
- case K_ECDHE_RSA:
- case K_ECDHE_ECDSA:
- case K_ECDH_ANON:
- try {
- m3 = new ECDH_ServerKeyExchange(ecdh,
- privateKey,
- clnt_random.random_bytes,
- svr_random.random_bytes,
- sslContext.getSecureRandom(),
- preferableSignatureAlgorithm,
- protocolVersion);
- } catch (GeneralSecurityException e) {
- throwSSLException(
- "Error generating ECDH server key exchange", e);
- m3 = null; // make compiler happy
- }
- break;
- case K_ECDH_RSA:
- case K_ECDH_ECDSA:
- // ServerKeyExchange not used for fixed ECDH
- m3 = null;
- break;
- default:
- throw new RuntimeException("internal error: " + keyExchange);
- }
- if (m3 != null) {
- if (debug != null && Debug.isOn("handshake")) {
- m3.print(System.out);
- }
- m3.write(output);
- }
-
- //
- // FOURTH, the CertificateRequest message. The details of
- // the message can be affected by the key exchange algorithm
- // in use. For example, certs with fixed Diffie-Hellman keys
- // are only useful with the DH_DSS and DH_RSA key exchange
- // algorithms.
- //
- // Needed only if server requires client to authenticate self.
- // Illegal for anonymous flavors, so we need to check that.
- //
- // CertificateRequest is omitted for Kerberos ciphers
- if (doClientAuth != SSLEngineImpl.clauth_none &&
- keyExchange != K_DH_ANON && keyExchange != K_ECDH_ANON &&
- keyExchange != K_KRB5 && keyExchange != K_KRB5_EXPORT) {
-
- CertificateRequest m4;
- X509Certificate caCerts[];
-
- Collection<SignatureAndHashAlgorithm> localSignAlgs = null;
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- // We currently use all local upported signature and hash
- // algorithms. However, to minimize the computation cost
- // of requested hash algorithms, we may use a restricted
- // set of signature algorithms in the future.
- localSignAlgs = getLocalSupportedSignAlgs();
- if (localSignAlgs.isEmpty()) {
- throw new SSLHandshakeException(
- "No supported signature algorithm");
- }
-
- Set<String> localHashAlgs =
- SignatureAndHashAlgorithm.getHashAlgorithmNames(
- localSignAlgs);
- if (localHashAlgs.isEmpty()) {
- throw new SSLHandshakeException(
- "No supported signature algorithm");
- }
- handshakeHash.restrictCertificateVerifyAlgs(localHashAlgs);
- }
-
- caCerts = sslContext.getX509TrustManager().getAcceptedIssuers();
- m4 = new CertificateRequest(caCerts, keyExchange,
- localSignAlgs, protocolVersion);
-
- if (debug != null && Debug.isOn("handshake")) {
- m4.print(System.out);
- }
- m4.write(output);
- } else {
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- handshakeHash.setCertificateVerifyAlg(null);
- }
- }
-
- /*
- * FIFTH, say ServerHelloDone.
- */
- ServerHelloDone m5 = new ServerHelloDone();
-
- if (debug != null && Debug.isOn("handshake")) {
- m5.print(System.out);
- }
- m5.write(output);
-
- /*
- * Flush any buffered messages so the client will see them.
- * Ideally, all the messages above go in a single network level
- * message to the client. Without big Certificate chains, it's
- * going to be the common case.
- */
- output.flush();
- }
-
- /*
- * Choose cipher suite from among those supported by client. Sets
- * the cipherSuite and keyExchange variables.
- */
- private void chooseCipherSuite(ClientHello mesg) throws IOException {
- for (CipherSuite suite : mesg.getCipherSuites().collection()) {
- if (isNegotiable(suite) == false) {
- continue;
- }
-
- if (doClientAuth == SSLEngineImpl.clauth_required) {
- if ((suite.keyExchange == K_DH_ANON) ||
- (suite.keyExchange == K_ECDH_ANON)) {
- continue;
- }
- }
- if (trySetCipherSuite(suite) == false) {
- continue;
- }
- return;
- }
- fatalSE(Alerts.alert_handshake_failure,
- "no cipher suites in common");
- }
-
- /**
- * Set the given CipherSuite, if possible. Return the result.
- * The call succeeds if the CipherSuite is available and we have
- * the necessary certificates to complete the handshake. We don't
- * check if the CipherSuite is actually enabled.
- *
- * If successful, this method also generates ephemeral keys if
- * required for this ciphersuite. This may take some time, so this
- * method should only be called if you really want to use the
- * CipherSuite.
- *
- * This method is called from chooseCipherSuite() in this class.
- */
- boolean trySetCipherSuite(CipherSuite suite) {
- /*
- * If we're resuming a session we know we can
- * support this key exchange algorithm and in fact
- * have already cached the result of it in
- * the session state.
- */
- if (resumingSession) {
- return true;
- }
-
- if (suite.isNegotiable() == false) {
- return false;
- }
-
- // must not negotiate the obsoleted weak cipher suites.
- if (protocolVersion.v >= suite.obsoleted) {
- return false;
- }
-
- // must not negotiate unsupported cipher suites.
- if (protocolVersion.v < suite.supported) {
- return false;
- }
-
- KeyExchange keyExchange = suite.keyExchange;
-
- // null out any existing references
- privateKey = null;
- certs = null;
- dh = null;
- tempPrivateKey = null;
- tempPublicKey = null;
-
- Collection<SignatureAndHashAlgorithm> supportedSignAlgs = null;
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- if (peerSupportedSignAlgs != null) {
- supportedSignAlgs = peerSupportedSignAlgs;
- } else {
- SignatureAndHashAlgorithm algorithm = null;
-
- // we may optimize the performance
- switch (keyExchange) {
- // If the negotiated key exchange algorithm is one of
- // (RSA, DHE_RSA, DH_RSA, RSA_PSK, ECDH_RSA, ECDHE_RSA),
- // behave as if client had sent the value {sha1,rsa}.
- case K_RSA:
- case K_DHE_RSA:
- case K_DH_RSA:
- // case K_RSA_PSK:
- case K_ECDH_RSA:
- case K_ECDHE_RSA:
- algorithm = SignatureAndHashAlgorithm.valueOf(
- HashAlgorithm.SHA1.value,
- SignatureAlgorithm.RSA.value, 0);
- break;
- // If the negotiated key exchange algorithm is one of
- // (DHE_DSS, DH_DSS), behave as if the client had
- // sent the value {sha1,dsa}.
- case K_DHE_DSS:
- case K_DH_DSS:
- algorithm = SignatureAndHashAlgorithm.valueOf(
- HashAlgorithm.SHA1.value,
- SignatureAlgorithm.DSA.value, 0);
- break;
- // If the negotiated key exchange algorithm is one of
- // (ECDH_ECDSA, ECDHE_ECDSA), behave as if the client
- // had sent value {sha1,ecdsa}.
- case K_ECDH_ECDSA:
- case K_ECDHE_ECDSA:
- algorithm = SignatureAndHashAlgorithm.valueOf(
- HashAlgorithm.SHA1.value,
- SignatureAlgorithm.ECDSA.value, 0);
- break;
- default:
- // no peer supported signature algorithms
- }
-
- if (algorithm == null) {
- supportedSignAlgs =
- Collections.<SignatureAndHashAlgorithm>emptySet();
- } else {
- supportedSignAlgs =
- new ArrayList<SignatureAndHashAlgorithm>(1);
- supportedSignAlgs.add(algorithm);
- }
-
- // Sets the peer supported signature algorithm to use in KM
- // temporarily.
- session.setPeerSupportedSignatureAlgorithms(supportedSignAlgs);
- }
- }
-
- switch (keyExchange) {
- case K_RSA:
- // need RSA certs for authentication
- if (setupPrivateKeyAndChain("RSA") == false) {
- return false;
- }
- break;
- case K_RSA_EXPORT:
- // need RSA certs for authentication
- if (setupPrivateKeyAndChain("RSA") == false) {
- return false;
- }
-
- try {
- if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
- if (!setupEphemeralRSAKeys(suite.exportable)) {
- return false;
- }
- }
- } catch (RuntimeException e) {
- // could not determine keylength, ignore key
- return false;
- }
- break;
- case K_DHE_RSA:
- // need RSA certs for authentication
- if (setupPrivateKeyAndChain("RSA") == false) {
- return false;
- }
-
- // get preferable peer signature algorithm for server key exchange
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- preferableSignatureAlgorithm =
- SignatureAndHashAlgorithm.getPreferableAlgorithm(
- supportedSignAlgs, "RSA", privateKey);
- if (preferableSignatureAlgorithm == null) {
- return false;
- }
- }
-
- setupEphemeralDHKeys(suite.exportable);
- break;
- case K_ECDHE_RSA:
- // need RSA certs for authentication
- if (setupPrivateKeyAndChain("RSA") == false) {
- return false;
- }
-
- // get preferable peer signature algorithm for server key exchange
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- preferableSignatureAlgorithm =
- SignatureAndHashAlgorithm.getPreferableAlgorithm(
- supportedSignAlgs, "RSA", privateKey);
- if (preferableSignatureAlgorithm == null) {
- return false;
- }
- }
-
- if (setupEphemeralECDHKeys() == false) {
- return false;
- }
- break;
- case K_DHE_DSS:
- // get preferable peer signature algorithm for server key exchange
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- preferableSignatureAlgorithm =
- SignatureAndHashAlgorithm.getPreferableAlgorithm(
- supportedSignAlgs, "DSA");
- if (preferableSignatureAlgorithm == null) {
- return false;
- }
- }
-
- // need DSS certs for authentication
- if (setupPrivateKeyAndChain("DSA") == false) {
- return false;
- }
- setupEphemeralDHKeys(suite.exportable);
- break;
- case K_ECDHE_ECDSA:
- // get preferable peer signature algorithm for server key exchange
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- preferableSignatureAlgorithm =
- SignatureAndHashAlgorithm.getPreferableAlgorithm(
- supportedSignAlgs, "ECDSA");
- if (preferableSignatureAlgorithm == null) {
- return false;
- }
- }
-
- // need EC cert signed using EC
- if (setupPrivateKeyAndChain("EC_EC") == false) {
- return false;
- }
- if (setupEphemeralECDHKeys() == false) {
- return false;
- }
- break;
- case K_ECDH_RSA:
- // need EC cert signed using RSA
- if (setupPrivateKeyAndChain("EC_RSA") == false) {
- return false;
- }
- setupStaticECDHKeys();
- break;
- case K_ECDH_ECDSA:
- // need EC cert signed using EC
- if (setupPrivateKeyAndChain("EC_EC") == false) {
- return false;
- }
- setupStaticECDHKeys();
- break;
- case K_KRB5:
- case K_KRB5_EXPORT:
- // need Kerberos Key
- if (!setupKerberosKeys()) {
- return false;
- }
- break;
- case K_DH_ANON:
- // no certs needed for anonymous
- setupEphemeralDHKeys(suite.exportable);
- break;
- case K_ECDH_ANON:
- // no certs needed for anonymous
- if (setupEphemeralECDHKeys() == false) {
- return false;
- }
- break;
- default:
- // internal error, unknown key exchange
- throw new RuntimeException("Unrecognized cipherSuite: " + suite);
- }
- setCipherSuite(suite);
-
- // set the peer implicit supported signature algorithms
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- if (peerSupportedSignAlgs == null) {
- setPeerSupportedSignAlgs(supportedSignAlgs);
- // we had alreay update the session
- }
- }
- return true;
- }
-
- /*
- * Get some "ephemeral" RSA keys for this context. This means
- * generating them if it's not already been done.
- *
- * Note that we currently do not implement any ciphersuites that use
- * strong ephemeral RSA. (We do not support the EXPORT1024 ciphersuites
- * and standard RSA ciphersuites prohibit ephemeral mode for some reason)
- * This means that export is always true and 512 bit keys are generated.
- */
- private boolean setupEphemeralRSAKeys(boolean export) {
- KeyPair kp = sslContext.getEphemeralKeyManager().
- getRSAKeyPair(export, sslContext.getSecureRandom());
- if (kp == null) {
- return false;
- } else {
- tempPublicKey = kp.getPublic();
- tempPrivateKey = kp.getPrivate();
- return true;
- }
- }
-
- /*
- * Acquire some "ephemeral" Diffie-Hellman keys for this handshake.
- * We don't reuse these, for improved forward secrecy.
- */
- private void setupEphemeralDHKeys(boolean export) {
- /*
- * Diffie-Hellman keys ... we use 768 bit private keys due
- * to the "use twice as many key bits as bits you want secret"
- * rule of thumb, assuming we want the same size premaster
- * secret with Diffie-Hellman and RSA key exchanges. Except
- * that exportable ciphers max out at 512 bits modulus values.
- */
- dh = new DHCrypt((export ? 512 : 768), sslContext.getSecureRandom());
- }
-
- // Setup the ephemeral ECDH parameters.
- // If we cannot continue because we do not support any of the curves that
- // the client requested, return false. Otherwise (all is well), return true.
- private boolean setupEphemeralECDHKeys() {
- int index = -1;
- if (supportedCurves != null) {
- // if the client sent the supported curves extension, pick the
- // first one that we support;
- for (int curveId : supportedCurves.curveIds()) {
- if (SupportedEllipticCurvesExtension.isSupported(curveId)) {
- index = curveId;
- break;
- }
- }
- if (index < 0) {
- // no match found, cannot use this ciphersuite
- return false;
- }
- } else {
- // pick our preference
- index = SupportedEllipticCurvesExtension.DEFAULT.curveIds()[0];
- }
- String oid = SupportedEllipticCurvesExtension.getCurveOid(index);
- ecdh = new ECDHCrypt(oid, sslContext.getSecureRandom());
- return true;
- }
-
- private void setupStaticECDHKeys() {
- // don't need to check whether the curve is supported, already done
- // in setupPrivateKeyAndChain().
- ecdh = new ECDHCrypt(privateKey, certs[0].getPublicKey());
- }
-
- /**
- * Retrieve the server key and certificate for the specified algorithm
- * from the KeyManager and set the instance variables.
- *
- * @return true if successful, false if not available or invalid
- */
- private boolean setupPrivateKeyAndChain(String algorithm) {
- X509ExtendedKeyManager km = sslContext.getX509KeyManager();
- String alias;
- if (conn != null) {
- alias = km.chooseServerAlias(algorithm, null, conn);
- } else {
- alias = km.chooseEngineServerAlias(algorithm, null, engine);
- }
- if (alias == null) {
- return false;
- }
- PrivateKey tempPrivateKey = km.getPrivateKey(alias);
- if (tempPrivateKey == null) {
- return false;
- }
- X509Certificate[] tempCerts = km.getCertificateChain(alias);
- if ((tempCerts == null) || (tempCerts.length == 0)) {
- return false;
- }
- String keyAlgorithm = algorithm.split("_")[0];
- PublicKey publicKey = tempCerts[0].getPublicKey();
- if ((tempPrivateKey.getAlgorithm().equals(keyAlgorithm) == false)
- || (publicKey.getAlgorithm().equals(keyAlgorithm) == false)) {
- return false;
- }
- // For ECC certs, check whether we support the EC domain parameters.
- // If the client sent a SupportedEllipticCurves ClientHello extension,
- // check against that too.
- if (keyAlgorithm.equals("EC")) {
- if (publicKey instanceof ECPublicKey == false) {
- return false;
- }
- ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
- int index = SupportedEllipticCurvesExtension.getCurveIndex(params);
- if (SupportedEllipticCurvesExtension.isSupported(index) == false) {
- return false;
- }
- if ((supportedCurves != null) && !supportedCurves.contains(index)) {
- return false;
- }
- }
- this.privateKey = tempPrivateKey;
- this.certs = tempCerts;
- return true;
- }
-
- /**
- * Retrieve the Kerberos key for the specified server principal
- * from the JAAS configuration file.
- *
- * @return true if successful, false if not available or invalid
- */
- private boolean setupKerberosKeys() {
- if (kerberosKeys != null) {
- return true;
- }
- try {
- final AccessControlContext acc = getAccSE();
- kerberosKeys = AccessController.doPrivileged(
- // Eliminate dependency on KerberosKey
- new PrivilegedExceptionAction<SecretKey[]>() {
- public SecretKey[] run() throws Exception {
- // get kerberos key for the default principal
- return Krb5Helper.getServerKeys(acc);
- }});
-
- // check permission to access and use the secret key of the
- // Kerberized "host" service
- if (kerberosKeys != null && kerberosKeys.length > 0) {
- if (debug != null && Debug.isOn("handshake")) {
- for (SecretKey k: kerberosKeys) {
- System.out.println("Using Kerberos key: " +
- k);
- }
- }
-
- String serverPrincipal =
- Krb5Helper.getServerPrincipalName(kerberosKeys[0]);
- SecurityManager sm = System.getSecurityManager();
- try {
- if (sm != null) {
- // Eliminate dependency on ServicePermission
- sm.checkPermission(Krb5Helper.getServicePermission(
- serverPrincipal, "accept"), acc);
- }
- } catch (SecurityException se) {
- kerberosKeys = null;
- // %%% destroy keys? or will that affect Subject?
- if (debug != null && Debug.isOn("handshake"))
- System.out.println("Permission to access Kerberos"
- + " secret key denied");
- return false;
- }
- }
- return (kerberosKeys != null && kerberosKeys.length > 0);
- } catch (PrivilegedActionException e) {
- // Likely exception here is LoginExceptin
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println("Attempt to obtain Kerberos key failed: "
- + e.toString());
- }
- return false;
- }
- }
-
- /*
- * For Kerberos ciphers, the premaster secret is encrypted using
- * the session key. See RFC 2712.
- */
- private SecretKey clientKeyExchange(KerberosClientKeyExchange mesg)
- throws IOException {
-
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
-
- // Record the principals involved in exchange
- session.setPeerPrincipal(mesg.getPeerPrincipal());
- session.setLocalPrincipal(mesg.getLocalPrincipal());
-
- byte[] b = mesg.getUnencryptedPreMasterSecret();
- return new SecretKeySpec(b, "TlsPremasterSecret");
- }
-
- /*
- * Diffie Hellman key exchange is used when the server presented
- * D-H parameters in its certificate (signed using RSA or DSS/DSA),
- * or else the server presented no certificate but sent D-H params
- * in a ServerKeyExchange message. Use of D-H is specified by the
- * cipher suite chosen.
- *
- * The message optionally contains the client's D-H public key (if
- * it wasn't not sent in a client certificate). As always with D-H,
- * if a client and a server have each other's D-H public keys and
- * they use common algorithm parameters, they have a shared key
- * that's derived via the D-H calculation. That key becomes the
- * pre-master secret.
- */
- private SecretKey clientKeyExchange(DHClientKeyExchange mesg)
- throws IOException {
-
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
- return dh.getAgreedSecret(mesg.getClientPublicKey(), false);
- }
-
- private SecretKey clientKeyExchange(ECDHClientKeyExchange mesg)
- throws IOException {
-
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
- return ecdh.getAgreedSecret(mesg.getEncodedPoint());
- }
-
- /*
- * Client wrote a message to verify the certificate it sent earlier.
- *
- * Note that this certificate isn't involved in key exchange. Client
- * authentication messages are included in the checksums used to
- * validate the handshake (e.g. Finished messages). Other than that,
- * the _exact_ identity of the client is less fundamental to protocol
- * security than its role in selecting keys via the pre-master secret.
- */
- private void clientCertificateVerify(CertificateVerify mesg)
- throws IOException {
-
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
-
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- SignatureAndHashAlgorithm signAlg =
- mesg.getPreferableSignatureAlgorithm();
- if (signAlg == null) {
- throw new SSLHandshakeException(
- "Illegal CertificateVerify message");
- }
-
- String hashAlg =
- SignatureAndHashAlgorithm.getHashAlgorithmName(signAlg);
- if (hashAlg == null || hashAlg.length() == 0) {
- throw new SSLHandshakeException(
- "No supported hash algorithm");
- }
-
- handshakeHash.setCertificateVerifyAlg(hashAlg);
- }
-
- try {
- PublicKey publicKey =
- session.getPeerCertificates()[0].getPublicKey();
-
- boolean valid = mesg.verify(protocolVersion, handshakeHash,
- publicKey, session.getMasterSecret());
- if (valid == false) {
- fatalSE(Alerts.alert_bad_certificate,
- "certificate verify message signature error");
- }
- } catch (GeneralSecurityException e) {
- fatalSE(Alerts.alert_bad_certificate,
- "certificate verify format error", e);
- }
-
- // reset the flag for clientCertificateVerify message
- needClientVerify = false;
- }
-
-
- /*
- * Client writes "finished" at the end of its handshake, after cipher
- * spec is changed. We verify it and then send ours.
- *
- * When we're resuming a session, we'll have already sent our own
- * Finished message so just the verification is needed.
- */
- private void clientFinished(Finished mesg) throws IOException {
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
-
- /*
- * Verify if client did send the certificate when client
- * authentication was required, otherwise server should not proceed
- */
- if (doClientAuth == SSLEngineImpl.clauth_required) {
- // get X500Principal of the end-entity certificate for X509-based
- // ciphersuites, or Kerberos principal for Kerberos ciphersuites
- session.getPeerPrincipal();
- }
-
- /*
- * Verify if client did send clientCertificateVerify message following
- * the client Certificate, otherwise server should not proceed
- */
- if (needClientVerify) {
- fatalSE(Alerts.alert_handshake_failure,
- "client did not send certificate verify message");
- }
-
- /*
- * Verify the client's message with the "before" digest of messages,
- * and forget about continuing to use that digest.
- */
- boolean verified = mesg.verify(handshakeHash, Finished.CLIENT,
- session.getMasterSecret());
-
- if (!verified) {
- fatalSE(Alerts.alert_handshake_failure,
- "client 'finished' message doesn't verify");
- // NOTREACHED
- }
-
- /*
- * save client verify data for secure renegotiation
- */
- if (secureRenegotiation) {
- clientVerifyData = mesg.getVerifyData();
- }
-
- /*
- * OK, it verified. If we're doing the full handshake, add that
- * "Finished" message to the hash of handshake messages, then send
- * the change_cipher_spec and Finished message.
- */
- if (!resumingSession) {
- input.digestNow();
- sendChangeCipherAndFinish(true);
- }
-
- /*
- * Update the session cache only after the handshake completed, else
- * we're open to an attack against a partially completed handshake.
- */
- session.setLastAccessedTime(System.currentTimeMillis());
- if (!resumingSession && session.isRejoinable()) {
- ((SSLSessionContextImpl)sslContext.engineGetServerSessionContext())
- .put(session);
- if (debug != null && Debug.isOn("session")) {
- System.out.println(
- "%% Cached server session: " + session);
- }
- } else if (!resumingSession &&
- debug != null && Debug.isOn("session")) {
- System.out.println(
- "%% Didn't cache non-resumable server session: "
- + session);
- }
- }
-
- /*
- * Compute finished message with the "server" digest (and then forget
- * about that digest, it can't be used again).
- */
- private void sendChangeCipherAndFinish(boolean finishedTag)
- throws IOException {
-
- output.flush();
-
- Finished mesg = new Finished(protocolVersion, handshakeHash,
- Finished.SERVER, session.getMasterSecret(), cipherSuite);
-
- /*
- * Send the change_cipher_spec record; then our Finished handshake
- * message will be the last handshake message. Flush, and now we
- * are ready for application data!!
- */
- sendChangeCipherSpec(mesg, finishedTag);
-
- /*
- * save server verify data for secure renegotiation
- */
- if (secureRenegotiation) {
- serverVerifyData = mesg.getVerifyData();
- }
-
- /*
- * Update state machine so client MUST send 'finished' next
- * The update should only take place if it is not in the fast
- * handshake mode since the server has to wait for a finished
- * message from the client.
- */
- if (finishedTag) {
- state = HandshakeMessage.ht_finished;
- }
- }
-
-
- /*
- * Returns a HelloRequest message to kickstart renegotiations
- */
- HandshakeMessage getKickstartMessage() {
- return new HelloRequest();
- }
-
-
- /*
- * Fault detected during handshake.
- */
- void handshakeAlert(byte description) throws SSLProtocolException {
-
- String message = Alerts.alertDescription(description);
-
- if (debug != null && Debug.isOn("handshake")) {
- System.out.println("SSL -- handshake alert: "
- + message);
- }
-
- /*
- * It's ok to get a no_certificate alert from a client of which
- * we *requested* authentication information.
- * However, if we *required* it, then this is not acceptable.
- *
- * Anyone calling getPeerCertificates() on the
- * session will get an SSLPeerUnverifiedException.
- */
- if ((description == Alerts.alert_no_certificate) &&
- (doClientAuth == SSLEngineImpl.clauth_requested)) {
- return;
- }
-
- throw new SSLProtocolException("handshake alert: " + message);
- }
-
- /*
- * RSA key exchange is normally used. The client encrypts a "pre-master
- * secret" with the server's public key, from the Certificate (or else
- * ServerKeyExchange) message that was sent to it by the server. That's
- * decrypted using the private key before we get here.
- */
- private SecretKey clientKeyExchange(RSAClientKeyExchange mesg)
- throws IOException {
-
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
- return mesg.preMaster;
- }
-
- /*
- * Verify the certificate sent by the client. We'll only get one if we
- * sent a CertificateRequest to request client authentication. If we
- * are in TLS mode, the client may send a message with no certificates
- * to indicate it does not have an appropriate chain. (In SSLv3 mode,
- * it would send a no certificate alert).
- */
- private void clientCertificate(CertificateMsg mesg) throws IOException {
- if (debug != null && Debug.isOn("handshake")) {
- mesg.print(System.out);
- }
-
- X509Certificate[] peerCerts = mesg.getCertificateChain();
-
- if (peerCerts.length == 0) {
- /*
- * If the client authentication is only *REQUESTED* (e.g.
- * not *REQUIRED*, this is an acceptable condition.)
- */
- if (doClientAuth == SSLEngineImpl.clauth_requested) {
- // Smart (aka stupid) to forecast that no CertificateVerify
- // message will be received.
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- handshakeHash.setCertificateVerifyAlg(null);
- }
- return;
- } else {
- fatalSE(Alerts.alert_bad_certificate,
- "null cert chain");
- }
- }
-
- // ask the trust manager to verify the chain
- X509TrustManager tm = sslContext.getX509TrustManager();
-
- try {
- // find out the types of client authentication used
- PublicKey key = peerCerts[0].getPublicKey();
- String keyAlgorithm = key.getAlgorithm();
- String authType;
- if (keyAlgorithm.equals("RSA")) {
- authType = "RSA";
- } else if (keyAlgorithm.equals("DSA")) {
- authType = "DSA";
- } else if (keyAlgorithm.equals("EC")) {
- authType = "EC";
- } else {
- // unknown public key type
- authType = "UNKNOWN";
- }
-
- if (tm instanceof X509ExtendedTrustManager) {
- if (conn != null) {
- ((X509ExtendedTrustManager)tm).checkClientTrusted(
- peerCerts.clone(),
- authType,
- conn);
- } else {
- ((X509ExtendedTrustManager)tm).checkClientTrusted(
- peerCerts.clone(),
- authType,
- engine);
- }
- } else {
- // Unlikely to happen, because we have wrapped the old
- // X509TrustManager with the new X509ExtendedTrustManager.
- throw new CertificateException(
- "Improper X509TrustManager implementation");
- }
- } catch (CertificateException e) {
- // This will throw an exception, so include the original error.
- fatalSE(Alerts.alert_certificate_unknown, e);
- }
- // set the flag for clientCertificateVerify message
- needClientVerify = true;
-
- session.setPeerCertificates(peerCerts);
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SessionId.java b/ojluni/src/main/java/sun/security/ssl/SessionId.java
deleted file mode 100755
index 1707d42..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SessionId.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) 1996, 2008, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.security.SecureRandom;
-
-/**
- * Encapsulates an SSL session ID. SSL Session IDs are not reused by
- * servers during the lifetime of any sessions it created. Sessions may
- * be used by many connections, either concurrently (for example, two
- * connections to a web server at the same time) or sequentially (over as
- * long a time period as is allowed by a given server).
- *
- * @author Satish Dharmaraj
- * @author David Brownell
- */
-final
-class SessionId
-{
- private byte sessionId []; // max 32 bytes
-
- /** Constructs a new session ID ... perhaps for a rejoinable session */
- SessionId (boolean isRejoinable, SecureRandom generator)
- {
- if (isRejoinable)
- // this will be unique, it's a timestamp plus much randomness
- sessionId = new RandomCookie (generator).random_bytes;
- else
- sessionId = new byte [0];
- }
-
- /** Constructs a session ID from a byte array (max size 32 bytes) */
- SessionId (byte sessionId [])
- { this.sessionId = sessionId; }
-
- /** Returns the length of the ID, in bytes */
- int length ()
- { return sessionId.length; }
-
- /** Returns the bytes in the ID. May be an empty array. */
- byte [] getId ()
- {
- return sessionId.clone ();
- }
-
- /** Returns the ID as a string */
- public String toString ()
- {
- int len = sessionId.length;
- StringBuffer s = new StringBuffer (10 + 2 * len);
-
- s.append ("{");
- for (int i = 0; i < len; i++) {
- s.append (0x0ff & sessionId [i]);
- if (i != (len - 1))
- s.append (", ");
- }
- s.append ("}");
- return s.toString ();
- }
-
-
- /** Returns a value which is the same for session IDs which are equal */
- public int hashCode ()
- {
- int retval = 0;
-
- for (int i = 0; i < sessionId.length; i++)
- retval += sessionId [i];
- return retval;
- }
-
- /** Returns true if the parameter is the same session ID */
- public boolean equals (Object obj)
- {
- if (!(obj instanceof SessionId))
- return false;
-
- SessionId s = (SessionId) obj;
- byte b [] = s.getId ();
-
- if (b.length != sessionId.length)
- return false;
- for (int i = 0; i < sessionId.length; i++) {
- if (b [i] != sessionId [i])
- return false;
- }
- return true;
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SignatureAndHashAlgorithm.java b/ojluni/src/main/java/sun/security/ssl/SignatureAndHashAlgorithm.java
deleted file mode 100755
index 043b9b1..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SignatureAndHashAlgorithm.java
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.security.AlgorithmConstraints;
-import java.security.CryptoPrimitive;
-import java.security.PrivateKey;
-
-import java.util.Set;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.EnumSet;
-import java.util.TreeMap;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.ArrayList;
-
-import sun.security.util.KeyUtil;
-
-/**
- * Signature and hash algorithm.
- *
- * [RFC5246] The client uses the "signature_algorithms" extension to
- * indicate to the server which signature/hash algorithm pairs may be
- * used in digital signatures. The "extension_data" field of this
- * extension contains a "supported_signature_algorithms" value.
- *
- * enum {
- * none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
- * sha512(6), (255)
- * } HashAlgorithm;
- *
- * enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
- * SignatureAlgorithm;
- *
- * struct {
- * HashAlgorithm hash;
- * SignatureAlgorithm signature;
- * } SignatureAndHashAlgorithm;
- */
-final class SignatureAndHashAlgorithm {
-
- // minimum priority for default enabled algorithms
- final static int SUPPORTED_ALG_PRIORITY_MAX_NUM = 0x00F0;
-
- // performance optimization
- private final static Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
- EnumSet.of(CryptoPrimitive.SIGNATURE);
-
- // supported pairs of signature and hash algorithm
- private final static Map<Integer, SignatureAndHashAlgorithm> supportedMap;
- private final static Map<Integer, SignatureAndHashAlgorithm> priorityMap;
-
- // the hash algorithm
- private HashAlgorithm hash;
-
- // the signature algorithm
- private SignatureAlgorithm signature;
-
- // id in 16 bit MSB format, i.e. 0x0603 for SHA512withECDSA
- private int id;
-
- // the standard algorithm name, for example "SHA512withECDSA"
- private String algorithm;
-
- // Priority for the preference order. The lower the better.
- //
- // If the algorithm is unsupported, its priority should be bigger
- // than SUPPORTED_ALG_PRIORITY_MAX_NUM.
- private int priority;
-
- // constructor for supported algorithm
- private SignatureAndHashAlgorithm(HashAlgorithm hash,
- SignatureAlgorithm signature, String algorithm, int priority) {
- this.hash = hash;
- this.signature = signature;
- this.algorithm = algorithm;
- this.id = ((hash.value & 0xFF) << 8) | (signature.value & 0xFF);
- this.priority = priority;
- }
-
- // constructor for unsupported algorithm
- private SignatureAndHashAlgorithm(String algorithm, int id, int sequence) {
- this.hash = HashAlgorithm.valueOf((id >> 8) & 0xFF);
- this.signature = SignatureAlgorithm.valueOf(id & 0xFF);
- this.algorithm = algorithm;
- this.id = id;
-
- // add one more to the sequece number, in case that the number is zero
- this.priority = SUPPORTED_ALG_PRIORITY_MAX_NUM + sequence + 1;
- }
-
- // Note that we do not use the sequence argument for supported algorithms,
- // so please don't sort by comparing the objects read from handshake
- // messages.
- static SignatureAndHashAlgorithm valueOf(int hash,
- int signature, int sequence) {
- hash &= 0xFF;
- signature &= 0xFF;
-
- int id = (hash << 8) | signature;
- SignatureAndHashAlgorithm signAlg = supportedMap.get(id);
- if (signAlg == null) {
- // unsupported algorithm
- signAlg = new SignatureAndHashAlgorithm(
- "Unknown (hash:0x" + Integer.toString(hash, 16) +
- ", signature:0x" + Integer.toString(signature, 16) + ")",
- id, sequence);
- }
-
- return signAlg;
- }
-
- int getHashValue() {
- return (id >> 8) & 0xFF;
- }
-
- int getSignatureValue() {
- return id & 0xFF;
- }
-
- String getAlgorithmName() {
- return algorithm;
- }
-
- // return the size of a SignatureAndHashAlgorithm structure in TLS record
- static int sizeInRecord() {
- return 2;
- }
-
- // Get local supported algorithm collection complying to
- // algorithm constraints
- static Collection<SignatureAndHashAlgorithm>
- getSupportedAlgorithms(AlgorithmConstraints constraints) {
-
- Collection<SignatureAndHashAlgorithm> supported = new ArrayList<>();
- synchronized (priorityMap) {
- for (SignatureAndHashAlgorithm sigAlg : priorityMap.values()) {
- if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM &&
- constraints.permits(SIGNATURE_PRIMITIVE_SET,
- sigAlg.algorithm, null)) {
- supported.add(sigAlg);
- }
- }
- }
-
- return supported;
- }
-
- // Get supported algorithm collection from an untrusted collection
- static Collection<SignatureAndHashAlgorithm> getSupportedAlgorithms(
- Collection<SignatureAndHashAlgorithm> algorithms ) {
- Collection<SignatureAndHashAlgorithm> supported = new ArrayList<>();
- for (SignatureAndHashAlgorithm sigAlg : algorithms) {
- if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM) {
- supported.add(sigAlg);
- }
- }
-
- return supported;
- }
-
- static String[] getAlgorithmNames(
- Collection<SignatureAndHashAlgorithm> algorithms) {
- ArrayList<String> algorithmNames = new ArrayList<>();
- if (algorithms != null) {
- for (SignatureAndHashAlgorithm sigAlg : algorithms) {
- algorithmNames.add(sigAlg.algorithm);
- }
- }
-
- String[] array = new String[algorithmNames.size()];
- return algorithmNames.toArray(array);
- }
-
- static Set<String> getHashAlgorithmNames(
- Collection<SignatureAndHashAlgorithm> algorithms) {
- Set<String> algorithmNames = new HashSet<>();
- if (algorithms != null) {
- for (SignatureAndHashAlgorithm sigAlg : algorithms) {
- if (sigAlg.hash.value > 0) {
- algorithmNames.add(sigAlg.hash.standardName);
- }
- }
- }
-
- return algorithmNames;
- }
-
- static String getHashAlgorithmName(SignatureAndHashAlgorithm algorithm) {
- return algorithm.hash.standardName;
- }
-
- private static void supports(HashAlgorithm hash,
- SignatureAlgorithm signature, String algorithm, int priority) {
-
- SignatureAndHashAlgorithm pair =
- new SignatureAndHashAlgorithm(hash, signature, algorithm, priority);
- if (supportedMap.put(pair.id, pair) != null) {
- throw new RuntimeException(
- "Duplicate SignatureAndHashAlgorithm definition, id: " +
- pair.id);
- }
- if (priorityMap.put(pair.priority, pair) != null) {
- throw new RuntimeException(
- "Duplicate SignatureAndHashAlgorithm definition, priority: " +
- pair.priority);
- }
- }
-
- static SignatureAndHashAlgorithm getPreferableAlgorithm(
- Collection<SignatureAndHashAlgorithm> algorithms, String expected) {
-
- return SignatureAndHashAlgorithm.getPreferableAlgorithm(
- algorithms, expected, null);
- }
-
- static SignatureAndHashAlgorithm getPreferableAlgorithm(
- Collection<SignatureAndHashAlgorithm> algorithms,
- String expected, PrivateKey signingKey) {
-
- if (expected == null && !algorithms.isEmpty()) {
- for (SignatureAndHashAlgorithm sigAlg : algorithms) {
- if (sigAlg.priority <= SUPPORTED_ALG_PRIORITY_MAX_NUM) {
- return sigAlg;
- }
- }
-
- return null; // no supported algorithm
- }
-
- if (expected == null ) {
- return null; // no expected algorithm, no supported algorithm
- }
-
- /*
- * Need to check RSA key length to match the length of hash value
- */
- int maxDigestLength = Integer.MAX_VALUE;
- if (signingKey != null &&
- "rsa".equalsIgnoreCase(signingKey.getAlgorithm()) &&
- expected.equalsIgnoreCase("rsa")) {
- /*
- * RSA keys of 512 bits have been shown to be practically
- * breakable, it does not make much sense to use the strong
- * hash algorithm for keys whose key size less than 512 bits.
- * So it is not necessary to caculate the required max digest
- * length exactly.
- *
- * If key size is greater than or equals to 768, there is no max
- * digest length limitation in currect implementation.
- *
- * If key size is greater than or equals to 512, but less than
- * 768, the digest length should be less than or equal to 32 bytes.
- *
- * If key size is less than 512, the digest length should be
- * less than or equal to 20 bytes.
- */
- int keySize = KeyUtil.getKeySize(signingKey);
- if (keySize >= 768) {
- maxDigestLength = HashAlgorithm.SHA512.length;
- } else if ((keySize >= 512) && (keySize < 768)) {
- maxDigestLength = HashAlgorithm.SHA256.length;
- } else if ((keySize > 0) && (keySize < 512)) {
- maxDigestLength = HashAlgorithm.SHA1.length;
- } // Otherwise, cannot determine the key size, prefer the most
- // perferable hash algorithm.
- }
-
- for (SignatureAndHashAlgorithm algorithm : algorithms) {
- int signValue = algorithm.id & 0xFF;
- if (expected.equalsIgnoreCase("rsa") &&
- signValue == SignatureAlgorithm.RSA.value) {
- if (algorithm.hash.length <= maxDigestLength) {
- return algorithm;
- }
- } else if (
- (expected.equalsIgnoreCase("dsa") &&
- signValue == SignatureAlgorithm.DSA.value) ||
- (expected.equalsIgnoreCase("ecdsa") &&
- signValue == SignatureAlgorithm.ECDSA.value) ||
- (expected.equalsIgnoreCase("ec") &&
- signValue == SignatureAlgorithm.ECDSA.value)) {
- return algorithm;
- }
- }
-
- return null;
- }
-
- static enum HashAlgorithm {
- UNDEFINED("undefined", "", -1, -1),
- NONE( "none", "NONE", 0, -1),
- MD5( "md5", "MD5", 1, 16),
- SHA1( "sha1", "SHA-1", 2, 20),
- SHA224( "sha224", "SHA-224", 3, 28),
- SHA256( "sha256", "SHA-256", 4, 32),
- SHA384( "sha384", "SHA-384", 5, 48),
- SHA512( "sha512", "SHA-512", 6, 64);
-
- final String name; // not the standard signature algorithm name
- // except the UNDEFINED, other names are defined
- // by TLS 1.2 protocol
- final String standardName; // the standard MessageDigest algorithm name
- final int value;
- final int length; // digest length in bytes, -1 means not applicable
-
- private HashAlgorithm(String name, String standardName,
- int value, int length) {
- this.name = name;
- this.standardName = standardName;
- this.value = value;
- this.length = length;
- }
-
- static HashAlgorithm valueOf(int value) {
- HashAlgorithm algorithm = UNDEFINED;
- switch (value) {
- case 0:
- algorithm = NONE;
- break;
- case 1:
- algorithm = MD5;
- break;
- case 2:
- algorithm = SHA1;
- break;
- case 3:
- algorithm = SHA224;
- break;
- case 4:
- algorithm = SHA256;
- break;
- case 5:
- algorithm = SHA384;
- break;
- case 6:
- algorithm = SHA512;
- break;
- }
-
- return algorithm;
- }
- }
-
- static enum SignatureAlgorithm {
- UNDEFINED("undefined", -1),
- ANONYMOUS("anonymous", 0),
- RSA( "rsa", 1),
- DSA( "dsa", 2),
- ECDSA( "ecdsa", 3);
-
- final String name; // not the standard signature algorithm name
- // except the UNDEFINED, other names are defined
- // by TLS 1.2 protocol
- final int value;
-
- private SignatureAlgorithm(String name, int value) {
- this.name = name;
- this.value = value;
- }
-
- static SignatureAlgorithm valueOf(int value) {
- SignatureAlgorithm algorithm = UNDEFINED;
- switch (value) {
- case 0:
- algorithm = ANONYMOUS;
- break;
- case 1:
- algorithm = RSA;
- break;
- case 2:
- algorithm = DSA;
- break;
- case 3:
- algorithm = ECDSA;
- break;
- }
-
- return algorithm;
- }
- }
-
- static {
- supportedMap = Collections.synchronizedSortedMap(
- new TreeMap<Integer, SignatureAndHashAlgorithm>());
- priorityMap = Collections.synchronizedSortedMap(
- new TreeMap<Integer, SignatureAndHashAlgorithm>());
-
- synchronized (supportedMap) {
- int p = SUPPORTED_ALG_PRIORITY_MAX_NUM;
- supports(HashAlgorithm.MD5, SignatureAlgorithm.RSA,
- "MD5withRSA", --p);
- supports(HashAlgorithm.SHA1, SignatureAlgorithm.DSA,
- "SHA1withDSA", --p);
- supports(HashAlgorithm.SHA1, SignatureAlgorithm.RSA,
- "SHA1withRSA", --p);
- supports(HashAlgorithm.SHA1, SignatureAlgorithm.ECDSA,
- "SHA1withECDSA", --p);
- supports(HashAlgorithm.SHA224, SignatureAlgorithm.RSA,
- "SHA224withRSA", --p);
- supports(HashAlgorithm.SHA224, SignatureAlgorithm.ECDSA,
- "SHA224withECDSA", --p);
- supports(HashAlgorithm.SHA256, SignatureAlgorithm.RSA,
- "SHA256withRSA", --p);
- supports(HashAlgorithm.SHA256, SignatureAlgorithm.ECDSA,
- "SHA256withECDSA", --p);
- supports(HashAlgorithm.SHA384, SignatureAlgorithm.RSA,
- "SHA384withRSA", --p);
- supports(HashAlgorithm.SHA384, SignatureAlgorithm.ECDSA,
- "SHA384withECDSA", --p);
- supports(HashAlgorithm.SHA512, SignatureAlgorithm.RSA,
- "SHA512withRSA", --p);
- supports(HashAlgorithm.SHA512, SignatureAlgorithm.ECDSA,
- "SHA512withECDSA", --p);
- }
- }
-}
-
diff --git a/ojluni/src/main/java/sun/security/ssl/SunJSSE.java b/ojluni/src/main/java/sun/security/ssl/SunJSSE.java
deleted file mode 100755
index 16cb35c..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SunJSSE.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.security.*;
-
-/**
- * The JSSE provider.
- *
- * The RSA implementation has been removed from JSSE, but we still need to
- * register the same algorithms for compatibility. We just point to the RSA
- * implementation in the SunRsaSign provider. This works because all classes
- * are in the bootclasspath and therefore loaded by the same classloader.
- *
- * SunJSSE now supports an experimental FIPS compliant mode when used with an
- * appropriate FIPS certified crypto provider. In FIPS mode, we:
- * . allow only TLS 1.0 or later
- * . allow only FIPS approved ciphersuites
- * . perform all crypto in the FIPS crypto provider
- *
- * It is currently not possible to use both FIPS compliant SunJSSE and
- * standard JSSE at the same time because of the various static data structures
- * we use.
- *
- * However, we do want to allow FIPS mode to be enabled at runtime and without
- * editing the java.security file. That means we need to allow
- * Security.removeProvider("SunJSSE") to work, which creates an instance of
- * this class in non-FIPS mode. That is why we delay the selection of the mode
- * as long as possible. This is until we open an SSL/TLS connection and the
- * data structures need to be initialized or until SunJSSE is initialized in
- * FIPS mode.
- *
- */
-public abstract class SunJSSE extends java.security.Provider {
-
- private static final long serialVersionUID = 3231825739635378733L;
-
- private static String info = "Sun JSSE provider" +
- "(PKCS12, SunX509 key/trust factories, SSLv3, TLSv1)";
-
- private static String fipsInfo =
- "Sun JSSE provider (FIPS mode, crypto provider ";
-
- // tri-valued flag:
- // null := no final decision made
- // false := data structures initialized in non-FIPS mode
- // true := data structures initialized in FIPS mode
- private static Boolean fips;
-
- // the FIPS certificate crypto provider that we use to perform all crypto
- // operations. null in non-FIPS mode
- static java.security.Provider cryptoProvider;
-
- protected static synchronized boolean isFIPS() {
- if (fips == null) {
- fips = false;
- }
- return fips;
- }
-
- // ensure we can use FIPS mode using the specified crypto provider.
- // enable FIPS mode if not already enabled.
- private static synchronized void ensureFIPS(java.security.Provider p) {
- if (fips == null) {
- fips = true;
- cryptoProvider = p;
- } else {
- if (fips == false) {
- throw new ProviderException
- ("SunJSSE already initialized in non-FIPS mode");
- }
- if (cryptoProvider != p) {
- throw new ProviderException
- ("SunJSSE already initialized with FIPS crypto provider "
- + cryptoProvider);
- }
- }
- }
-
- // standard constructor
- protected SunJSSE() {
- super("SunJSSE", 1.7d, info);
- subclassCheck();
- if (Boolean.TRUE.equals(fips)) {
- throw new ProviderException
- ("SunJSSE is already initialized in FIPS mode");
- }
- registerAlgorithms(false);
- }
-
- // prefered constructor to enable FIPS mode at runtime
- protected SunJSSE(java.security.Provider cryptoProvider){
- this(checkNull(cryptoProvider), cryptoProvider.getName());
- }
-
- // constructor to enable FIPS mode from java.security file
- protected SunJSSE(String cryptoProvider){
- this(null, checkNull(cryptoProvider));
- }
-
- private static <T> T checkNull(T t) {
- if (t == null) {
- throw new ProviderException("cryptoProvider must not be null");
- }
- return t;
- }
-
- private SunJSSE(java.security.Provider cryptoProvider,
- String providerName) {
- super("SunJSSE", 1.6d, fipsInfo + providerName + ")");
- subclassCheck();
- if (cryptoProvider == null) {
- // Calling Security.getProvider() will cause other providers to be
- // loaded. That is not good but unavoidable here.
- cryptoProvider = Security.getProvider(providerName);
- if (cryptoProvider == null) {
- throw new ProviderException
- ("Crypto provider not installed: " + providerName);
- }
- }
- ensureFIPS(cryptoProvider);
- registerAlgorithms(true);
- }
-
- private void registerAlgorithms(final boolean isfips) {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- doRegister(isfips);
- return null;
- }
- });
- }
-
- private void doRegister(boolean isfips) {
- if (isfips == false) {
- put("KeyFactory.RSA",
- "sun.security.rsa.RSAKeyFactory");
- put("Alg.Alias.KeyFactory.1.2.840.113549.1.1", "RSA");
- put("Alg.Alias.KeyFactory.OID.1.2.840.113549.1.1", "RSA");
-
- put("KeyPairGenerator.RSA",
- "sun.security.rsa.RSAKeyPairGenerator");
- put("Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1", "RSA");
- put("Alg.Alias.KeyPairGenerator.OID.1.2.840.113549.1.1", "RSA");
-
- put("Signature.MD2withRSA",
- "sun.security.rsa.RSASignature$MD2withRSA");
- put("Alg.Alias.Signature.1.2.840.113549.1.1.2", "MD2withRSA");
- put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.2",
- "MD2withRSA");
-
- put("Signature.MD5withRSA",
- "sun.security.rsa.RSASignature$MD5withRSA");
- put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5withRSA");
- put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.4",
- "MD5withRSA");
-
- put("Signature.SHA1withRSA",
- "sun.security.rsa.RSASignature$SHA1withRSA");
- put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1withRSA");
- put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.5",
- "SHA1withRSA");
- put("Alg.Alias.Signature.1.3.14.3.2.29", "SHA1withRSA");
- put("Alg.Alias.Signature.OID.1.3.14.3.2.29", "SHA1withRSA");
-
- }
- put("Signature.MD5andSHA1withRSA",
- "sun.security.ssl.RSASignature");
-
- put("KeyManagerFactory.SunX509",
- "sun.security.ssl.KeyManagerFactoryImpl$SunX509");
- put("KeyManagerFactory.NewSunX509",
- "sun.security.ssl.KeyManagerFactoryImpl$X509");
- put("Alg.Alias.KeyManagerFactory.PKIX", "NewSunX509");
-
- put("TrustManagerFactory.SunX509",
- "sun.security.ssl.TrustManagerFactoryImpl$SimpleFactory");
- put("TrustManagerFactory.PKIX",
- "sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory");
- put("Alg.Alias.TrustManagerFactory.SunPKIX", "PKIX");
- put("Alg.Alias.TrustManagerFactory.X509", "PKIX");
- put("Alg.Alias.TrustManagerFactory.X.509", "PKIX");
-
- put("SSLContext.TLSv1",
- "sun.security.ssl.SSLContextImpl$TLS10Context");
- put("Alg.Alias.SSLContext.TLS", "TLSv1");
- if (isfips == false) {
- put("Alg.Alias.SSLContext.SSL", "TLSv1");
- put("Alg.Alias.SSLContext.SSLv3", "TLSv1");
- }
-
- put("SSLContext.TLSv1.1",
- "sun.security.ssl.SSLContextImpl$TLS11Context");
- put("SSLContext.TLSv1.2",
- "sun.security.ssl.SSLContextImpl$TLS12Context");
- put("SSLContext.Default",
- "sun.security.ssl.SSLContextImpl$DefaultSSLContext");
-
- /*
- * KeyStore
- */
- put("KeyStore.PKCS12",
- "sun.security.pkcs12.PKCS12KeyStore");
- }
-
- private void subclassCheck() {
- if (getClass() != com.sun.net.ssl.internal.ssl.Provider.class) {
- throw new AssertionError("Illegal subclass: " + getClass());
- }
- }
-
- @Override
- protected final void finalize() throws Throwable {
- // empty
- super.finalize();
- }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/SunX509KeyManagerImpl.java b/ojluni/src/main/java/sun/security/ssl/SunX509KeyManagerImpl.java
deleted file mode 100755
index bdf113d..0000000
--- a/ojluni/src/main/java/sun/security/ssl/SunX509KeyManagerImpl.java
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import javax.net.ssl.*;
-import java.security.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-import java.util.*;
-import java.net.Socket;
-
-import javax.security.auth.x500.X500Principal;
-
-
-/**
- * An implemention of X509KeyManager backed by a KeyStore.
- *
- * The backing KeyStore is inspected when this object is constructed.
- * All key entries containing a PrivateKey and a non-empty chain of
- * X509Certificate are then copied into an internal store. This means
- * that subsequent modifications of the KeyStore have no effect on the
- * X509KeyManagerImpl object.
- *
- * Note that this class assumes that all keys are protected by the same
- * password.
- *
- * The JSSE handshake code currently calls into this class via
- * chooseClientAlias() and chooseServerAlias() to find the certificates to
- * use. As implemented here, both always return the first alias returned by
- * getClientAliases() and getServerAliases(). In turn, these methods are
- * implemented by calling getAliases(), which performs the actual lookup.
- *
- * Note that this class currently implements no checking of the local
- * certificates. In particular, it is *not* guaranteed that:
- * . the certificates are within their validity period and not revoked
- * . the signatures verify
- * . they form a PKIX compliant chain.
- * . the certificate extensions allow the certificate to be used for
- * the desired purpose.
- *
- * Chains that fail any of these criteria will probably be rejected by
- * the remote peer.
- *
- */
-final class SunX509KeyManagerImpl extends X509ExtendedKeyManager {
-
- private static final Debug debug = Debug.getInstance("ssl");
-
- private static final String[] STRING0 = new String[0];
-
- /*
- * The credentials from the KeyStore as
- * Map: String(alias) -> X509Credentials(credentials)
- */
- private Map<String,X509Credentials> credentialsMap;
-
- /*
- * Cached server aliases for the case issuers == null.
- * (in the current JSSE implementation, issuers are always null for
- * server certs). See chooseServerAlias() for details.
- *
- * Map: String(keyType) -> String[](alias)
- */
- private Map<String,String[]> serverAliasCache;
-
- /*
- * Basic container for credentials implemented as an inner class.
- */
- private static class X509Credentials {
- PrivateKey privateKey;
- X509Certificate[] certificates;
- private Set<X500Principal> issuerX500Principals;
-
- X509Credentials(PrivateKey privateKey, X509Certificate[] certificates) {
- // assert privateKey and certificates != null
- this.privateKey = privateKey;
- this.certificates = certificates;
- }
-
- synchronized Set<X500Principal> getIssuerX500Principals() {
- // lazy initialization
- if (issuerX500Principals == null) {
- issuerX500Principals = new HashSet<X500Principal>();
- for (int i = 0; i < certificates.length; i++) {
- issuerX500Principals.add(
- certificates[i].getIssuerX500Principal());
- }
- }
- return issuerX500Principals;
- }
- }
-
- SunX509KeyManagerImpl(KeyStore ks, char[] password) throws KeyStoreException,
- NoSuchAlgorithmException, UnrecoverableKeyException {
-
- credentialsMap = new HashMap<String,X509Credentials>();
- serverAliasCache = new HashMap<String,String[]>();
- if (ks == null) {
- return;
- }
-
- for (Enumeration<String> aliases = ks.aliases();
- aliases.hasMoreElements(); ) {
- String alias = aliases.nextElement();
- if (!ks.isKeyEntry(alias)) {
- continue;
- }
- Key key = ks.getKey(alias, password);
- if (key instanceof PrivateKey == false) {
- continue;
- }
- Certificate[] certs = ks.getCertificateChain(alias);
- if ((certs == null) || (certs.length == 0) ||
- !(certs[0] instanceof X509Certificate)) {
- continue;
- }
- if (!(certs instanceof X509Certificate[])) {
- Certificate[] tmp = new X509Certificate[certs.length];
- System.arraycopy(certs, 0, tmp, 0, certs.length);
- certs = tmp;
- }
-
- X509Credentials cred = new X509Credentials((PrivateKey)key,
- (X509Certificate[])certs);
- credentialsMap.put(alias, cred);
- if (debug != null && Debug.isOn("keymanager")) {
- System.out.println("***");
- System.out.println("found key for : " + alias);
- for (int i = 0; i < certs.length; i++) {
- System.out.println("chain [" + i + "] = "
- + certs[i]);
- }
- System.out.println("***");
- }
- }
- }
-
- /*
- * Returns the certificate chain associated with the given alias.
- *
- * @return the certificate chain (ordered with the user's certificate first
- * and the root certificate authority last)
- */
- public X509Certificate[] getCertificateChain(String alias) {
- if (alias == null) {
- return null;
- }
- X509Credentials cred = credentialsMap.get(alias);
- if (cred == null) {
- return null;
- } else {
- return cred.certificates.clone();
- }
- }
-
- /*
- * Returns the key associated with the given alias
- */
- public PrivateKey getPrivateKey(String alias) {
- if (alias == null) {
- return null;
- }
- X509Credentials cred = credentialsMap.get(alias);
- if (cred == null) {
- return null;
- } else {
- return cred.privateKey;
- }
- }
-
- /*
- * Choose an alias to authenticate the client side of a secure
- * socket given the public key type and the list of
- * certificate issuer authorities recognized by the peer (if any).
- */
- public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
- Socket socket) {
- /*
- * We currently don't do anything with socket, but
- * someday we might. It might be a useful hint for
- * selecting one of the aliases we get back from
- * getClientAliases().
- */
-
- if (keyTypes == null) {
- return null;
- }
-
- for (int i = 0; i < keyTypes.length; i++) {
- String[] aliases = getClientAliases(keyTypes[i], issuers);
- if ((aliases != null) && (aliases.length > 0)) {
- return aliases[0];
- }
- }
- return null;
- }
-
- /*
- * Choose an alias to authenticate the client side of an
- * <code>SSLEngine</code> connection given the public key type
- * and the list of certificate issuer authorities recognized by
- * the peer (if any).
- *
- * @since 1.5
- */
- public String chooseEngineClientAlias(String[] keyType,
- Principal[] issuers, SSLEngine engine) {
- /*
- * If we ever start using socket as a selection criteria,
- * we'll need to adjust this.
- */
- return chooseClientAlias(keyType, issuers, null);
- }
-
- /*
- * Choose an alias to authenticate the server side of a secure
- * socket given the public key type and the list of
- * certificate issuer authorities recognized by the peer (if any).
- */
- public String chooseServerAlias(String keyType,
- Principal[] issuers, Socket socket) {
- /*
- * We currently don't do anything with socket, but
- * someday we might. It might be a useful hint for
- * selecting one of the aliases we get back from
- * getServerAliases().
- */
- if (keyType == null) {
- return null;
- }
-
- String[] aliases;
-
- if (issuers == null || issuers.length == 0) {
- aliases = serverAliasCache.get(keyType);
- if (aliases == null) {
- aliases = getServerAliases(keyType, issuers);
- // Cache the result (positive and negative lookups)
- if (aliases == null) {
- aliases = STRING0;
- }
- serverAliasCache.put(keyType, aliases);
- }
- } else {
- aliases = getServerAliases(keyType, issuers);
- }
- if ((aliases != null) && (aliases.length > 0)) {
- return aliases[0];
- }
- return null;
- }
-
- /*
- * Choose an alias to authenticate the server side of an
- * <code>SSLEngine</code> connection given the public key type
- * and the list of certificate issuer authorities recognized by
- * the peer (if any).
- *
- * @since 1.5
- */
- public String chooseEngineServerAlias(String keyType,
- Principal[] issuers, SSLEngine engine) {
- /*
- * If we ever start using socket as a selection criteria,
- * we'll need to adjust this.
- */
- return chooseServerAlias(keyType, issuers, null);
- }
-
- /*
- * Get the matching aliases for authenticating the client side of a secure
- * socket given the public key type and the list of
- * certificate issuer authorities recognized by the peer (if any).
- */
- public String[] getClientAliases(String keyType, Principal[] issuers) {
- return getAliases(keyType, issuers);
- }
-
- /*
- * Get the matching aliases for authenticating the server side of a secure
- * socket given the public key type and the list of
- * certificate issuer authorities recognized by the peer (if any).
- */
- public String[] getServerAliases(String keyType, Principal[] issuers) {
- return getAliases(keyType, issuers);
- }
-
- /*
- * Get the matching aliases for authenticating the either side of a secure
- * socket given the public key type and the list of
- * certificate issuer authorities recognized by the peer (if any).
- *
- * Issuers comes to us in the form of X500Principal[].
- */
- private String[] getAliases(String keyType, Principal[] issuers) {
- if (keyType == null) {
- return null;
- }
- if (issuers == null) {
- issuers = new X500Principal[0];
- }
- if (issuers instanceof X500Principal[] == false) {
- // normally, this will never happen but try to recover if it does
- issuers = convertPrincipals(issuers);
- }
- String sigType;
- if (keyType.contains("_")) {
- int k = keyType.indexOf("_");
- sigType = keyType.substring(k + 1);
- keyType = keyType.substring(0, k);
- } else {
- sigType = null;
- }
-
- X500Principal[] x500Issuers = (X500Principal[])issuers;
- // the algorithm below does not produce duplicates, so avoid Set
- List<String> aliases = new ArrayList<>();
-
- for (Map.Entry<String,X509Credentials> entry :
- credentialsMap.entrySet()) {
-
- String alias = entry.getKey();
- X509Credentials credentials = entry.getValue();
- X509Certificate[] certs = credentials.certificates;
-
- if (!keyType.equals(certs[0].getPublicKey().getAlgorithm())) {
- continue;
- }
- if (sigType != null) {
- if (certs.length > 1) {
- // if possible, check the public key in the issuer cert
- if (!sigType.equals(certs[1].getPublicKey().getAlgorithm())) {
- continue;
- }
- } else {
- // Check the signature algorithm of the certificate itself.
- // Look for the "withRSA" in "SHA1withRSA", etc.
- String sigAlgName =
- certs[0].getSigAlgName().toUpperCase(Locale.ENGLISH);
- String pattern = "WITH" + sigType.toUpperCase(Locale.ENGLISH);
- if (sigAlgName.contains(pattern) == false) {
- continue;
- }
- }
- }
-
- if (issuers.length == 0) {
- // no issuer specified, match all
- aliases.add(alias);
- if (debug != null && Debug.isOn("keymanager")) {
- System.out.println("matching alias: " + alias);
- }
- } else {
- Set<X500Principal> certIssuers =
- credentials.getIssuerX500Principals();
- for (int i = 0; i < x500Issuers.length; i++) {
- if (certIssuers.contains(issuers[i])) {
- aliases.add(alias);
- if (debug != null && Debug.isOn("keymanager")) {
- System.out.println("matching alias: " + alias);
- }
- break;
- }
- }
- }
- }
-
- String[] aliasStrings = aliases.toArray(STRING0);
- return ((aliasStrings.length == 0) ? null : aliasStrings);
- }
-
- /*
- * Convert an array of Principals to an array of X500Principals, if
- * possible. Principals that cannot be converted are ignored.
- */
- private static X500Principal[] convertPrincipals(Principal[] principals) {
- List<X500Principal> list = new ArrayList<>(principals.length);
- for (int i = 0; i < principals.length; i++) {
- Principal p = principals[i];
- if (p instanceof X500Principal) {
- list.add((X500Principal)p);
- } else {
- try {
- list.add(new X500Principal(p.getName()));
- } catch (IllegalArgumentException e) {
- // ignore
- }
- }
- }
- return list.toArray(new X500Principal[list.size()]);
- }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/TrustManagerFactoryImpl.java b/ojluni/src/main/java/sun/security/ssl/TrustManagerFactoryImpl.java
deleted file mode 100755
index ee2142c..0000000
--- a/ojluni/src/main/java/sun/security/ssl/TrustManagerFactoryImpl.java
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.util.*;
-import java.io.*;
-import java.math.*;
-import java.security.*;
-import java.security.cert.*;
-import javax.net.ssl.*;
-import java.security.spec.AlgorithmParameterSpec;
-
-import sun.security.validator.Validator;
-
-abstract class TrustManagerFactoryImpl extends TrustManagerFactorySpi {
-
- private static final Debug debug = Debug.getInstance("ssl");
- private X509TrustManager trustManager = null;
- private boolean isInitialized = false;
-
- TrustManagerFactoryImpl() {
- // empty
- }
-
- protected void engineInit(KeyStore ks) throws KeyStoreException {
- if (ks == null) {
- try {
- ks = getCacertsKeyStore("trustmanager");
- } catch (SecurityException se) {
- // eat security exceptions but report other throwables
- if (debug != null && Debug.isOn("trustmanager")) {
- System.out.println(
- "SunX509: skip default keystore: " + se);
- }
- } catch (Error err) {
- if (debug != null && Debug.isOn("trustmanager")) {
- System.out.println(
- "SunX509: skip default keystore: " + err);
- }
- throw err;
- } catch (RuntimeException re) {
- if (debug != null && Debug.isOn("trustmanager")) {
- System.out.println(
- "SunX509: skip default keystore: " + re);
- }
- throw re;
- } catch (Exception e) {
- if (debug != null && Debug.isOn("trustmanager")) {
- System.out.println(
- "SunX509: skip default keystore: " + e);
- }
- throw new KeyStoreException(
- "problem accessing trust store" + e);
- }
- }
- trustManager = getInstance(ks);
- isInitialized = true;
- }
-
- abstract X509TrustManager getInstance(KeyStore ks) throws KeyStoreException;
-
- abstract X509TrustManager getInstance(ManagerFactoryParameters spec)
- throws InvalidAlgorithmParameterException;
-
- protected void engineInit(ManagerFactoryParameters spec) throws
- InvalidAlgorithmParameterException {
- trustManager = getInstance(spec);
- isInitialized = true;
- }
-
- /**
- * Returns one trust manager for each type of trust material.
- */
- protected TrustManager[] engineGetTrustManagers() {
- if (!isInitialized) {
- throw new IllegalStateException(
- "TrustManagerFactoryImpl is not initialized");
- }
- return new TrustManager[] { trustManager };
- }
-
- /*
- * Try to get an InputStream based on the file we pass in.
- */
- private static FileInputStream getFileInputStream(final File file)
- throws Exception {
- return AccessController.doPrivileged(
- new PrivilegedExceptionAction<FileInputStream>() {
- public FileInputStream run() throws Exception {
- try {
- if (file.exists()) {
- return new FileInputStream(file);
- } else {
- return null;
- }
- } catch (FileNotFoundException e) {
- // couldn't find it, oh well.
- return null;
- }
- }
- });
- }
-
- /**
- * Returns the keystore with the configured CA certificates.
- */
- static KeyStore getCacertsKeyStore(String dbgname) throws Exception
- {
- String storeFileName = null;
- File storeFile = null;
- FileInputStream fis = null;
- String defaultTrustStoreType;
- String defaultTrustStoreProvider;
- final HashMap<String,String> props = new HashMap<>();
- final String sep = File.separator;
- KeyStore ks = null;
-
- AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
- public Void run() throws Exception {
- props.put("trustStore", System.getProperty(
- "javax.net.ssl.trustStore"));
- props.put("javaHome", System.getProperty(
- "java.home"));
- props.put("trustStoreType", System.getProperty(
- "javax.net.ssl.trustStoreType",
- KeyStore.getDefaultType()));
- props.put("trustStoreProvider", System.getProperty(
- "javax.net.ssl.trustStoreProvider", ""));
- props.put("trustStorePasswd", System.getProperty(
- "javax.net.ssl.trustStorePassword", ""));
- return null;
- }
- });
-
- /*
- * Try:
- * javax.net.ssl.trustStore (if this variable exists, stop)
- * jssecacerts
- * cacerts
- *
- * If none exists, we use an empty keystore.
- */
-
- storeFileName = props.get("trustStore");
- if (!"NONE".equals(storeFileName)) {
- if (storeFileName != null) {
- storeFile = new File(storeFileName);
- fis = getFileInputStream(storeFile);
- } else {
- String javaHome = props.get("javaHome");
- storeFile = new File(javaHome + sep + "lib" + sep
- + "security" + sep +
- "jssecacerts");
- if ((fis = getFileInputStream(storeFile)) == null) {
- storeFile = new File(javaHome + sep + "lib" + sep
- + "security" + sep +
- "cacerts");
- fis = getFileInputStream(storeFile);
- }
- }
-
- if (fis != null) {
- storeFileName = storeFile.getPath();
- } else {
- storeFileName = "No File Available, using empty keystore.";
- }
- }
-
- defaultTrustStoreType = props.get("trustStoreType");
- defaultTrustStoreProvider = props.get("trustStoreProvider");
- if (debug != null && Debug.isOn(dbgname)) {
- System.out.println("trustStore is: " + storeFileName);
- System.out.println("trustStore type is : " +
- defaultTrustStoreType);
- System.out.println("trustStore provider is : " +
- defaultTrustStoreProvider);
- }
-
- /*
- * Try to initialize trust store.
- */
- if (defaultTrustStoreType.length() != 0) {
- if (debug != null && Debug.isOn(dbgname)) {
- System.out.println("init truststore");
- }
- if (defaultTrustStoreProvider.length() == 0) {
- ks = KeyStore.getInstance(defaultTrustStoreType);
- } else {
- ks = KeyStore.getInstance(defaultTrustStoreType,
- defaultTrustStoreProvider);
- }
- char[] passwd = null;
- String defaultTrustStorePassword = props.get("trustStorePasswd");
- if (defaultTrustStorePassword.length() != 0)
- passwd = defaultTrustStorePassword.toCharArray();
-
- // if trustStore is NONE, fis will be null
- ks.load(fis, passwd);
-
- // Zero out the temporary password storage
- if (passwd != null) {
- for (int i = 0; i < passwd.length; i++) {
- passwd[i] = (char)0;
- }
- }
- }
-
- if (fis != null) {
- fis.close();
- }
-
- return ks;
- }
-
- public static final class SimpleFactory extends TrustManagerFactoryImpl {
- X509TrustManager getInstance(KeyStore ks) throws KeyStoreException {
- return new X509TrustManagerImpl(Validator.TYPE_SIMPLE, ks);
- }
- X509TrustManager getInstance(ManagerFactoryParameters spec)
- throws InvalidAlgorithmParameterException {
- throw new InvalidAlgorithmParameterException
- ("SunX509 TrustManagerFactory does not use "
- + "ManagerFactoryParameters");
- }
- }
-
- public static final class PKIXFactory extends TrustManagerFactoryImpl {
- X509TrustManager getInstance(KeyStore ks) throws KeyStoreException {
- return new X509TrustManagerImpl(Validator.TYPE_PKIX, ks);
- }
- X509TrustManager getInstance(ManagerFactoryParameters spec)
- throws InvalidAlgorithmParameterException {
- if (spec instanceof CertPathTrustManagerParameters == false) {
- throw new InvalidAlgorithmParameterException
- ("Parameters must be CertPathTrustManagerParameters");
- }
- CertPathParameters params =
- ((CertPathTrustManagerParameters)spec).getParameters();
- if (params instanceof PKIXBuilderParameters == false) {
- throw new InvalidAlgorithmParameterException
- ("Encapsulated parameters must be PKIXBuilderParameters");
- }
- PKIXBuilderParameters pkixParams = (PKIXBuilderParameters)params;
- return new X509TrustManagerImpl(Validator.TYPE_PKIX, pkixParams);
- }
- }
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/X509KeyManagerImpl.java b/ojluni/src/main/java/sun/security/ssl/X509KeyManagerImpl.java
deleted file mode 100755
index 426f5bf..0000000
--- a/ojluni/src/main/java/sun/security/ssl/X509KeyManagerImpl.java
+++ /dev/null
@@ -1,741 +0,0 @@
-/*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.ssl;
-
-import java.lang.ref.*;
-import java.util.*;
-import static java.util.Locale.ENGLISH;
-import java.util.concurrent.atomic.AtomicLong;
-import java.net.Socket;
-
-import java.security.*;
-import java.security.KeyStore.*;
-import java.security.cert.*;
-import java.security.cert.Certificate;
-
-import javax.net.ssl.*;
-
-import sun.security.provider.certpath.AlgorithmChecker;
-
-/**
- * The new X509 key manager implementation. The main differences to the
- * old SunX509 key manager are:
- * . it is based around the KeyStore.Builder API. This allows it to use
- * other forms of KeyStore protection or password input (e.g. a
- * CallbackHandler) or to have keys within one KeyStore protected by
- * different keys.
- * . it can use multiple KeyStores at the same time.
- * . it is explicitly designed to accomodate KeyStores that change over
- * the lifetime of the process.
- * . it makes an effort to choose the key that matches best, i.e. one that
- * is not expired and has the appropriate certificate extensions.
- *
- * Note that this code is not explicitly performance optimzied yet.
- *
- * @author Andreas Sterbenz
- */
-final class X509KeyManagerImpl extends X509ExtendedKeyManager
- implements X509KeyManager {
-
- private static final Debug debug = Debug.getInstance("ssl");
-
- private final static boolean useDebug =
- (debug != null) && Debug.isOn("keymanager");
-
- // for unit testing only, set via privileged reflection
- private static Date verificationDate;
-
- // list of the builders
- private final List<Builder> builders;
-
- // counter to generate unique ids for the aliases
- private final AtomicLong uidCounter;
-
- // cached entries
- private final Map<String,Reference<PrivateKeyEntry>> entryCacheMap;
-
- X509KeyManagerImpl(Builder builder) {
- this(Collections.singletonList(builder));
- }
-
- X509KeyManagerImpl(List<Builder> builders) {
- this.builders = builders;
- uidCounter = new AtomicLong();
- entryCacheMap = Collections.synchronizedMap
- (new SizedMap<String,Reference<PrivateKeyEntry>>());
- }
-
- // LinkedHashMap with a max size of 10
- // see LinkedHashMap JavaDocs
- private static class SizedMap<K,V> extends LinkedHashMap<K,V> {
- @Override protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
- return size() > 10;
- }
- }
-
- //
- // public methods
- //
-
- public X509Certificate[] getCertificateChain(String alias) {
- PrivateKeyEntry entry = getEntry(alias);
- return entry == null ? null :
- (X509Certificate[])entry.getCertificateChain();
- }
-
- public PrivateKey getPrivateKey(String alias) {
- PrivateKeyEntry entry = getEntry(alias);
- return entry == null ? null : entry.getPrivateKey();
- }
-
- public String chooseClientAlias(String[] keyTypes, Principal[] issuers,
- Socket socket) {
- return chooseAlias(getKeyTypes(keyTypes), issuers, CheckType.CLIENT,
- getAlgorithmConstraints(socket));
- }
-
- public String chooseEngineClientAlias(String[] keyTypes,
- Principal[] issuers, SSLEngine engine) {
- return chooseAlias(getKeyTypes(keyTypes), issuers, CheckType.CLIENT,
- getAlgorithmConstraints(engine));
- }
-
- public String chooseServerAlias(String keyType,
- Principal[] issuers, Socket socket) {
- return chooseAlias(getKeyTypes(keyType), issuers, CheckType.SERVER,
- getAlgorithmConstraints(socket));
- }
-
- public String chooseEngineServerAlias(String keyType,
- Principal[] issuers, SSLEngine engine) {
- return chooseAlias(getKeyTypes(keyType), issuers, CheckType.SERVER,
- getAlgorithmConstraints(engine));
- }
-
- public String[] getClientAliases(String keyType, Principal[] issuers) {
- return getAliases(keyType, issuers, CheckType.CLIENT, null);
- }
-
- public String[] getServerAliases(String keyType, Principal[] issuers) {
- return getAliases(keyType, issuers, CheckType.SERVER, null);
- }
-
- //
- // implementation private methods
- //
-
- // Gets algorithm constraints of the socket.
- private AlgorithmConstraints getAlgorithmConstraints(Socket socket) {
- if (socket != null && socket.isConnected() &&
- socket instanceof SSLSocket) {
-
- SSLSocket sslSocket = (SSLSocket)socket;
- SSLSession session = sslSocket.getHandshakeSession();
-
- if (session != null) {
- ProtocolVersion protocolVersion =
- ProtocolVersion.valueOf(session.getProtocol());
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- String[] peerSupportedSignAlgs = null;
-
- if (session instanceof ExtendedSSLSession) {
- ExtendedSSLSession extSession =
- (ExtendedSSLSession)session;
- peerSupportedSignAlgs =
- extSession.getPeerSupportedSignatureAlgorithms();
- }
-
- return new SSLAlgorithmConstraints(
- sslSocket, peerSupportedSignAlgs, true);
- }
- }
-
- return new SSLAlgorithmConstraints(sslSocket, true);
- }
-
- return new SSLAlgorithmConstraints((SSLSocket)null, true);
- }
-
- // Gets algorithm constraints of the engine.
- private AlgorithmConstraints getAlgorithmConstraints(SSLEngine engine) {
- if (engine != null) {
- SSLSession session = engine.getHandshakeSession();
- if (session != null) {
- ProtocolVersion protocolVersion =
- ProtocolVersion.valueOf(session.getProtocol());
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- String[] peerSupportedSignAlgs = null;
-
- if (session instanceof ExtendedSSLSession) {
- ExtendedSSLSession extSession =
- (ExtendedSSLSession)session;
- peerSupportedSignAlgs =
- extSession.getPeerSupportedSignatureAlgorithms();
- }
-
- return new SSLAlgorithmConstraints(
- engine, peerSupportedSignAlgs, true);
- }
- }
- }
-
- return new SSLAlgorithmConstraints(engine, true);
- }
-
- // we construct the alias we return to JSSE as seen in the code below
- // a unique id is included to allow us to reliably cache entries
- // between the calls to getCertificateChain() and getPrivateKey()
- // even if tokens are inserted or removed
- private String makeAlias(EntryStatus entry) {
- return uidCounter.incrementAndGet() + "." + entry.builderIndex + "."
- + entry.alias;
- }
-
- private PrivateKeyEntry getEntry(String alias) {
- // if the alias is null, return immediately
- if (alias == null) {
- return null;
- }
-
- // try to get the entry from cache
- Reference<PrivateKeyEntry> ref = entryCacheMap.get(alias);
- PrivateKeyEntry entry = (ref != null) ? ref.get() : null;
- if (entry != null) {
- return entry;
- }
-
- // parse the alias
- int firstDot = alias.indexOf('.');
- int secondDot = alias.indexOf('.', firstDot + 1);
- if ((firstDot == -1) || (secondDot == firstDot)) {
- // invalid alias
- return null;
- }
- try {
- int builderIndex = Integer.parseInt
- (alias.substring(firstDot + 1, secondDot));
- String keyStoreAlias = alias.substring(secondDot + 1);
- Builder builder = builders.get(builderIndex);
- KeyStore ks = builder.getKeyStore();
- Entry newEntry = ks.getEntry
- (keyStoreAlias, builder.getProtectionParameter(alias));
- if (newEntry instanceof PrivateKeyEntry == false) {
- // unexpected type of entry
- return null;
- }
- entry = (PrivateKeyEntry)newEntry;
- entryCacheMap.put(alias, new SoftReference(entry));
- return entry;
- } catch (Exception e) {
- // ignore
- return null;
- }
- }
-
- // Class to help verify that the public key algorithm (and optionally
- // the signature algorithm) of a certificate matches what we need.
- private static class KeyType {
-
- final String keyAlgorithm;
-
- // In TLS 1.2, the signature algorithm has been obsoleted by the
- // supported_signature_algorithms, and the certificate type no longer
- // restricts the algorithm used to sign the certificate.
- // However, because we don't support certificate type checking other
- // than rsa_sign, dss_sign and ecdsa_sign, we don't have to check the
- // protocol version here.
- final String sigKeyAlgorithm;
-
- KeyType(String algorithm) {
- int k = algorithm.indexOf("_");
- if (k == -1) {
- keyAlgorithm = algorithm;
- sigKeyAlgorithm = null;
- } else {
- keyAlgorithm = algorithm.substring(0, k);
- sigKeyAlgorithm = algorithm.substring(k + 1);
- }
- }
-
- boolean matches(Certificate[] chain) {
- if (!chain[0].getPublicKey().getAlgorithm().equals(keyAlgorithm)) {
- return false;
- }
- if (sigKeyAlgorithm == null) {
- return true;
- }
- if (chain.length > 1) {
- // if possible, check the public key in the issuer cert
- return sigKeyAlgorithm.equals(
- chain[1].getPublicKey().getAlgorithm());
- } else {
- // Check the signature algorithm of the certificate itself.
- // Look for the "withRSA" in "SHA1withRSA", etc.
- X509Certificate issuer = (X509Certificate)chain[0];
- String sigAlgName = issuer.getSigAlgName().toUpperCase(ENGLISH);
- String pattern = "WITH" + sigKeyAlgorithm.toUpperCase(ENGLISH);
- return sigAlgName.contains(pattern);
- }
- }
- }
-
- private static List<KeyType> getKeyTypes(String ... keyTypes) {
- if ((keyTypes == null) ||
- (keyTypes.length == 0) || (keyTypes[0] == null)) {
- return null;
- }
- List<KeyType> list = new ArrayList<>(keyTypes.length);
- for (String keyType : keyTypes) {
- list.add(new KeyType(keyType));
- }
- return list;
- }
-
- /*
- * Return the best alias that fits the given parameters.
- * The algorithm we use is:
- * . scan through all the aliases in all builders in order
- * . as soon as we find a perfect match, return
- * (i.e. a match with a cert that has appropriate key usage
- * and is not expired).
- * . if we do not find a perfect match, keep looping and remember
- * the imperfect matches
- * . at the end, sort the imperfect matches. we prefer expired certs
- * with appropriate key usage to certs with the wrong key usage.
- * return the first one of them.
- */
- private String chooseAlias(List<KeyType> keyTypeList, Principal[] issuers,
- CheckType checkType, AlgorithmConstraints constraints) {
- if (keyTypeList == null || keyTypeList.size() == 0) {
- return null;
- }
-
- Set<Principal> issuerSet = getIssuerSet(issuers);
- List<EntryStatus> allResults = null;
- for (int i = 0, n = builders.size(); i < n; i++) {
- try {
- List<EntryStatus> results = getAliases(i, keyTypeList,
- issuerSet, false, checkType, constraints);
- if (results != null) {
- // the results will either be a single perfect match
- // or 1 or more imperfect matches
- // if it's a perfect match, return immediately
- EntryStatus status = results.get(0);
- if (status.checkResult == CheckResult.OK) {
- if (useDebug) {
- debug.println("KeyMgr: choosing key: " + status);
- }
- return makeAlias(status);
- }
- if (allResults == null) {
- allResults = new ArrayList<EntryStatus>();
- }
- allResults.addAll(results);
- }
- } catch (Exception e) {
- // ignore
- }
- }
- if (allResults == null) {
- if (useDebug) {
- debug.println("KeyMgr: no matching key found");
- }
- return null;
- }
- Collections.sort(allResults);
- if (useDebug) {
- debug.println("KeyMgr: no good matching key found, "
- + "returning best match out of:");
- debug.println(allResults.toString());
- }
- return makeAlias(allResults.get(0));
- }
-
- /*
- * Return all aliases that (approximately) fit the parameters.
- * These are perfect matches plus imperfect matches (expired certificates
- * and certificates with the wrong extensions).
- * The perfect matches will be first in the array.
- */
- public String[] getAliases(String keyType, Principal[] issuers,
- CheckType checkType, AlgorithmConstraints constraints) {
- if (keyType == null) {
- return null;
- }
-
- Set<Principal> issuerSet = getIssuerSet(issuers);
- List<KeyType> keyTypeList = getKeyTypes(keyType);
- List<EntryStatus> allResults = null;
- for (int i = 0, n = builders.size(); i < n; i++) {
- try {
- List<EntryStatus> results = getAliases(i, keyTypeList,
- issuerSet, true, checkType, constraints);
- if (results != null) {
- if (allResults == null) {
- allResults = new ArrayList<EntryStatus>();
- }
- allResults.addAll(results);
- }
- } catch (Exception e) {
- // ignore
- }
- }
- if (allResults == null || allResults.size() == 0) {
- if (useDebug) {
- debug.println("KeyMgr: no matching alias found");
- }
- return null;
- }
- Collections.sort(allResults);
- if (useDebug) {
- debug.println("KeyMgr: getting aliases: " + allResults);
- }
- return toAliases(allResults);
- }
-
- // turn candidate entries into unique aliases we can return to JSSE
- private String[] toAliases(List<EntryStatus> results) {
- String[] s = new String[results.size()];
- int i = 0;
- for (EntryStatus result : results) {
- s[i++] = makeAlias(result);
- }
- return s;
- }
-
- // make a Set out of the array
- private Set<Principal> getIssuerSet(Principal[] issuers) {
- if ((issuers != null) && (issuers.length != 0)) {
- return new HashSet<>(Arrays.asList(issuers));
- } else {
- return null;
- }
- }
-
- // a candidate match
- // identifies the entry by builder and alias
- // and includes the result of the certificate check
- private static class EntryStatus implements Comparable<EntryStatus> {
-
- final int builderIndex;
- final int keyIndex;
- final String alias;
- final CheckResult checkResult;
-
- EntryStatus(int builderIndex, int keyIndex, String alias,
- Certificate[] chain, CheckResult checkResult) {
- this.builderIndex = builderIndex;
- this.keyIndex = keyIndex;
- this.alias = alias;
- this.checkResult = checkResult;
- }
-
- public int compareTo(EntryStatus other) {
- int result = this.checkResult.compareTo(other.checkResult);
- return (result == 0) ? (this.keyIndex - other.keyIndex) : result;
- }
-
- public String toString() {
- String s = alias + " (verified: " + checkResult + ")";
- if (builderIndex == 0) {
- return s;
- } else {
- return "Builder #" + builderIndex + ", alias: " + s;
- }
- }
- }
-
- // enum for the type of certificate check we want to perform
- // (client or server)
- // also includes the check code itself
- private static enum CheckType {
-
- // enum constant for "no check" (currently not used)
- NONE(Collections.<String>emptySet()),
-
- // enum constant for "tls client" check
- // valid EKU for TLS client: any, tls_client
- CLIENT(new HashSet<String>(Arrays.asList(new String[] {
- "2.5.29.37.0", "1.3.6.1.5.5.7.3.2" }))),
-
- // enum constant for "tls server" check
- // valid EKU for TLS server: any, tls_server, ns_sgc, ms_sgc
- SERVER(new HashSet<String>(Arrays.asList(new String[] {
- "2.5.29.37.0", "1.3.6.1.5.5.7.3.1", "2.16.840.1.113730.4.1",
- "1.3.6.1.4.1.311.10.3.3" })));
-
- // set of valid EKU values for this type
- final Set<String> validEku;
-
- CheckType(Set<String> validEku) {
- this.validEku = validEku;
- }
-
- private static boolean getBit(boolean[] keyUsage, int bit) {
- return (bit < keyUsage.length) && keyUsage[bit];
- }
-
- // check if this certificate is appropriate for this type of use
- // first check extensions, if they match, check expiration
- // note: we may want to move this code into the sun.security.validator
- // package
- CheckResult check(X509Certificate cert, Date date) {
- if (this == NONE) {
- return CheckResult.OK;
- }
-
- // check extensions
- try {
- // check extended key usage
- List<String> certEku = cert.getExtendedKeyUsage();
- if ((certEku != null) &&
- Collections.disjoint(validEku, certEku)) {
- // if extension present and it does not contain any of
- // the valid EKU OIDs, return extension_mismatch
- return CheckResult.EXTENSION_MISMATCH;
- }
-
- // check key usage
- boolean[] ku = cert.getKeyUsage();
- if (ku != null) {
- String algorithm = cert.getPublicKey().getAlgorithm();
- boolean kuSignature = getBit(ku, 0);
- if (algorithm.equals("RSA")) {
- // require either signature bit
- // or if server also allow key encipherment bit
- if (kuSignature == false) {
- if ((this == CLIENT) || (getBit(ku, 2) == false)) {
- return CheckResult.EXTENSION_MISMATCH;
- }
- }
- } else if (algorithm.equals("DSA")) {
- // require signature bit
- if (kuSignature == false) {
- return CheckResult.EXTENSION_MISMATCH;
- }
- } else if (algorithm.equals("DH")) {
- // require keyagreement bit
- if (getBit(ku, 4) == false) {
- return CheckResult.EXTENSION_MISMATCH;
- }
- } else if (algorithm.equals("EC")) {
- // require signature bit
- if (kuSignature == false) {
- return CheckResult.EXTENSION_MISMATCH;
- }
- // For servers, also require key agreement.
- // This is not totally accurate as the keyAgreement bit
- // is only necessary for static ECDH key exchange and
- // not ephemeral ECDH. We leave it in for now until
- // there are signs that this check causes problems
- // for real world EC certificates.
- if ((this == SERVER) && (getBit(ku, 4) == false)) {
- return CheckResult.EXTENSION_MISMATCH;
- }
- }
- }
- } catch (CertificateException e) {
- // extensions unparseable, return failure
- return CheckResult.EXTENSION_MISMATCH;
- }
-
- try {
- cert.checkValidity(date);
- return CheckResult.OK;
- } catch (CertificateException e) {
- return CheckResult.EXPIRED;
- }
- }
- }
-
- // enum for the result of the extension check
- // NOTE: the order of the constants is important as they are used
- // for sorting, i.e. OK is best, followed by EXPIRED and EXTENSION_MISMATCH
- private static enum CheckResult {
- OK, // ok or not checked
- EXPIRED, // extensions valid but cert expired
- EXTENSION_MISMATCH, // extensions invalid (expiration not checked)
- }
-
- /*
- * Return a List of all candidate matches in the specified builder
- * that fit the parameters.
- * We exclude entries in the KeyStore if they are not:
- * . private key entries
- * . the certificates are not X509 certificates
- * . the algorithm of the key in the EE cert doesn't match one of keyTypes
- * . none of the certs is issued by a Principal in issuerSet
- * Using those entries would not be possible or they would almost
- * certainly be rejected by the peer.
- *
- * In addition to those checks, we also check the extensions in the EE
- * cert and its expiration. Even if there is a mismatch, we include
- * such certificates because they technically work and might be accepted
- * by the peer. This leads to more graceful failure and better error
- * messages if the cert expires from one day to the next.
- *
- * The return values are:
- * . null, if there are no matching entries at all
- * . if 'findAll' is 'false' and there is a perfect match, a List
- * with a single element (early return)
- * . if 'findAll' is 'false' and there is NO perfect match, a List
- * with all the imperfect matches (expired, wrong extensions)
- * . if 'findAll' is 'true', a List with all perfect and imperfect
- * matches
- */
- private List<EntryStatus> getAliases(int builderIndex,
- List<KeyType> keyTypes, Set<Principal> issuerSet,
- boolean findAll, CheckType checkType,
- AlgorithmConstraints constraints) throws Exception {
- Builder builder = builders.get(builderIndex);
- KeyStore ks = builder.getKeyStore();
- List<EntryStatus> results = null;
- Date date = verificationDate;
- boolean preferred = false;
- for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) {
- String alias = e.nextElement();
- // check if it is a key entry (private key or secret key)
- if (ks.isKeyEntry(alias) == false) {
- continue;
- }
-
- Certificate[] chain = ks.getCertificateChain(alias);
- if ((chain == null) || (chain.length == 0)) {
- // must be secret key entry, ignore
- continue;
- }
-
- boolean incompatible = false;
- for (Certificate cert : chain) {
- if (cert instanceof X509Certificate == false) {
- // not an X509Certificate, ignore this alias
- incompatible = true;
- break;
- }
- }
- if (incompatible) {
- continue;
- }
-
- // check keytype
- int keyIndex = -1;
- int j = 0;
- for (KeyType keyType : keyTypes) {
- if (keyType.matches(chain)) {
- keyIndex = j;
- break;
- }
- j++;
- }
- if (keyIndex == -1) {
- if (useDebug) {
- debug.println("Ignoring alias " + alias
- + ": key algorithm does not match");
- }
- continue;
- }
- // check issuers
- if (issuerSet != null) {
- boolean found = false;
- for (Certificate cert : chain) {
- X509Certificate xcert = (X509Certificate)cert;
- if (issuerSet.contains(xcert.getIssuerX500Principal())) {
- found = true;
- break;
- }
- }
- if (found == false) {
- if (useDebug) {
- debug.println("Ignoring alias " + alias
- + ": issuers do not match");
- }
- continue;
- }
- }
-
- // check the algorithm constraints
- if (constraints != null &&
- !conformsToAlgorithmConstraints(constraints, chain)) {
-
- if (useDebug) {
- debug.println("Ignoring alias " + alias +
- ": certificate list does not conform to " +
- "algorithm constraints");
- }
- continue;
- }
-
- if (date == null) {
- date = new Date();
- }
- CheckResult checkResult =
- checkType.check((X509Certificate)chain[0], date);
- EntryStatus status =
- new EntryStatus(builderIndex, keyIndex,
- alias, chain, checkResult);
- if (!preferred && checkResult == CheckResult.OK && keyIndex == 0) {
- preferred = true;
- }
- if (preferred && (findAll == false)) {
- // if we have a good match and do not need all matches,
- // return immediately
- return Collections.singletonList(status);
- } else {
- if (results == null) {
- results = new ArrayList<EntryStatus>();
- }
- results.add(status);
- }
- }
- return results;
- }
-
- private static boolean conformsToAlgorithmConstraints(
- AlgorithmConstraints constraints, Certificate[] chain) {
-
- AlgorithmChecker checker = new AlgorithmChecker(constraints);
- try {
- checker.init(false);
- } catch (CertPathValidatorException cpve) {
- // unlikely to happen
- return false;
- }
-
- // It is a forward checker, so we need to check from trust to target.
- for (int i = chain.length - 1; i >= 0; i--) {
- Certificate cert = chain[i];
- try {
- // We don't care about the unresolved critical extensions.
- checker.check(cert, Collections.<String>emptySet());
- } catch (CertPathValidatorException cpve) {
- return false;
- }
- }
-
- return true;
- }
-
-}
diff --git a/ojluni/src/main/java/sun/security/ssl/X509TrustManagerImpl.java b/ojluni/src/main/java/sun/security/ssl/X509TrustManagerImpl.java
deleted file mode 100755
index d38e727..0000000
--- a/ojluni/src/main/java/sun/security/ssl/X509TrustManagerImpl.java
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-
-package sun.security.ssl;
-
-import java.net.Socket;
-import javax.net.ssl.SSLSession;
-
-import java.util.*;
-import java.security.*;
-import java.security.cert.*;
-
-import javax.net.ssl.*;
-
-import sun.security.validator.*;
-
-import sun.security.util.HostnameChecker;
-
-/**
- * This class implements the SunJSSE X.509 trust manager using the internal
- * validator API in J2SE core. The logic in this class is minimal.<p>
- * <p>
- * This class supports both the Simple validation algorithm from previous
- * JSSE versions and PKIX validation. Currently, it is not possible for the
- * application to specify PKIX parameters other than trust anchors. This will
- * be fixed in a future release using new APIs. When that happens, it may also
- * make sense to separate the Simple and PKIX trust managers into separate
- * classes.
- *
- * @author Andreas Sterbenz
- */
-final class X509TrustManagerImpl extends X509ExtendedTrustManager
- implements X509TrustManager {
-
- private final String validatorType;
-
- /**
- * The Set of trusted X509Certificates.
- */
- private final Collection<X509Certificate> trustedCerts;
-
- private final PKIXBuilderParameters pkixParams;
-
- // note that we need separate validator for client and server due to
- // the different extension checks. They are initialized lazily on demand.
- private volatile Validator clientValidator, serverValidator;
-
- private static final Debug debug = Debug.getInstance("ssl");
-
- X509TrustManagerImpl(String validatorType, KeyStore ks)
- throws KeyStoreException {
- this.validatorType = validatorType;
- this.pkixParams = null;
- if (ks == null) {
- trustedCerts = Collections.<X509Certificate>emptySet();
- } else {
- trustedCerts = KeyStores.getTrustedCerts(ks);
- }
- showTrustedCerts();
- }
-
- X509TrustManagerImpl(String validatorType, PKIXBuilderParameters params) {
- this.validatorType = validatorType;
- this.pkixParams = params;
- // create server validator eagerly so that we can conveniently
- // get the trusted certificates
- // clients need it anyway eventually, and servers will not mind
- // the little extra footprint
- Validator v = getValidator(Validator.VAR_TLS_SERVER);
- trustedCerts = v.getTrustedCertificates();
- serverValidator = v;
- showTrustedCerts();
- }
-
- @Override
- public void checkClientTrusted(X509Certificate chain[], String authType)
- throws CertificateException {
- checkTrusted(chain, authType, (Socket)null, true);
- }
-
- @Override
- public void checkServerTrusted(X509Certificate chain[], String authType)
- throws CertificateException {
- checkTrusted(chain, authType, (Socket)null, false);
- }
-
- @Override
- public X509Certificate[] getAcceptedIssuers() {
- X509Certificate[] certsArray = new X509Certificate[trustedCerts.size()];
- trustedCerts.toArray(certsArray);
- return certsArray;
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] chain, String authType,
- Socket socket) throws CertificateException {
- checkTrusted(chain, authType, socket, true);
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] chain, String authType,
- Socket socket) throws CertificateException {
- checkTrusted(chain, authType, socket, false);
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] chain, String authType,
- SSLEngine engine) throws CertificateException {
- checkTrusted(chain, authType, engine, true);
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] chain, String authType,
- SSLEngine engine) throws CertificateException {
- checkTrusted(chain, authType, engine, false);
- }
-
- private Validator checkTrustedInit(X509Certificate[] chain,
- String authType, boolean isClient) {
- if (chain == null || chain.length == 0) {
- throw new IllegalArgumentException(
- "null or zero-length certificate chain");
- }
-
- if (authType == null || authType.length() == 0) {
- throw new IllegalArgumentException(
- "null or zero-length authentication type");
- }
-
- Validator v = null;
- if (isClient) {
- v = clientValidator;
- if (v == null) {
- synchronized (this) {
- v = clientValidator;
- if (v == null) {
- v = getValidator(Validator.VAR_TLS_CLIENT);
- clientValidator = v;
- }
- }
- }
- } else {
- // assume double checked locking with a volatile flag works
- // (guaranteed under the new Tiger memory model)
- v = serverValidator;
- if (v == null) {
- synchronized (this) {
- v = serverValidator;
- if (v == null) {
- v = getValidator(Validator.VAR_TLS_SERVER);
- serverValidator = v;
- }
- }
- }
- }
-
- return v;
- }
-
-
- private void checkTrusted(X509Certificate[] chain, String authType,
- Socket socket, boolean isClient) throws CertificateException {
- Validator v = checkTrustedInit(chain, authType, isClient);
-
- AlgorithmConstraints constraints = null;
- if ((socket != null) && socket.isConnected() &&
- (socket instanceof SSLSocket)) {
-
- SSLSocket sslSocket = (SSLSocket)socket;
- SSLSession session = sslSocket.getHandshakeSession();
- if (session == null) {
- throw new CertificateException("No handshake session");
- }
-
- // check endpoint identity
- String identityAlg = sslSocket.getSSLParameters().
- getEndpointIdentificationAlgorithm();
- if (identityAlg != null && identityAlg.length() != 0) {
- String hostname = session.getPeerHost();
- checkIdentity(hostname, chain[0], identityAlg);
- }
-
- // create the algorithm constraints
- ProtocolVersion protocolVersion =
- ProtocolVersion.valueOf(session.getProtocol());
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- if (session instanceof ExtendedSSLSession) {
- ExtendedSSLSession extSession =
- (ExtendedSSLSession)session;
- String[] localSupportedSignAlgs =
- extSession.getLocalSupportedSignatureAlgorithms();
-
- constraints = new SSLAlgorithmConstraints(
- sslSocket, localSupportedSignAlgs, false);
- } else {
- constraints =
- new SSLAlgorithmConstraints(sslSocket, false);
- }
- } else {
- constraints = new SSLAlgorithmConstraints(sslSocket, false);
- }
- }
-
- X509Certificate[] trustedChain = null;
- if (isClient) {
- trustedChain = validate(v, chain, constraints, null);
- } else {
- trustedChain = validate(v, chain, constraints, authType);
- }
- if (debug != null && Debug.isOn("trustmanager")) {
- System.out.println("Found trusted certificate:");
- System.out.println(trustedChain[trustedChain.length - 1]);
- }
- }
-
- private void checkTrusted(X509Certificate[] chain, String authType,
- SSLEngine engine, boolean isClient) throws CertificateException {
- Validator v = checkTrustedInit(chain, authType, isClient);
-
- AlgorithmConstraints constraints = null;
- if (engine != null) {
- SSLSession session = engine.getHandshakeSession();
- if (session == null) {
- throw new CertificateException("No handshake session");
- }
-
- // check endpoint identity
- String identityAlg = engine.getSSLParameters().
- getEndpointIdentificationAlgorithm();
- if (identityAlg != null && identityAlg.length() != 0) {
- String hostname = session.getPeerHost();
- checkIdentity(hostname, chain[0], identityAlg);
- }
-
- // create the algorithm constraints
- ProtocolVersion protocolVersion =
- ProtocolVersion.valueOf(session.getProtocol());
- if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
- if (session instanceof ExtendedSSLSession) {
- ExtendedSSLSession extSession =
- (ExtendedSSLSession)session;
- String[] localSupportedSignAlgs =
- extSession.getLocalSupportedSignatureAlgorithms();
-
- constraints = new SSLAlgorithmConstraints(
- engine, localSupportedSignAlgs, false);
- } else {
- constraints =
- new SSLAlgorithmConstraints(engine, false);
- }
- } else {
- constraints = new SSLAlgorithmConstraints(engine, false);
- }
- }
-
- X509Certificate[] trustedChain = null;
- if (isClient) {
- trustedChain = validate(v, chain, constraints, null);
- } else {
- trustedChain = validate(v, chain, constraints, authType);
- }
- if (debug != null && Debug.isOn("trustmanager")) {
- System.out.println("Found trusted certificate:");
- System.out.println(trustedChain[trustedChain.length - 1]);
- }
- }
-
- private void showTrustedCerts() {
- if (debug != null && Debug.isOn("trustmanager")) {
- for (X509Certificate cert : trustedCerts) {
- System.out.println("adding as trusted cert:");
- System.out.println(" Subject: "
- + cert.getSubjectX500Principal());
- System.out.println(" Issuer: "
- + cert.getIssuerX500Principal());
- System.out.println(" Algorithm: "
- + cert.getPublicKey().getAlgorithm()
- + "; Serial number: 0x"
- + cert.getSerialNumber().toString(16));
- System.out.println(" Valid from "
- + cert.getNotBefore() + " until "
- + cert.getNotAfter());
- System.out.println();
- }
- }
- }
-
- private Validator getValidator(String variant) {
- Validator v;
- if (pkixParams == null) {
- v = Validator.getInstance(validatorType, variant, trustedCerts);
- } else {
- v = Validator.getInstance(validatorType, variant, pkixParams);
- }
- return v;
- }
-
- private static X509Certificate[] validate(Validator v,
- X509Certificate[] chain, AlgorithmConstraints constraints,
- String authType) throws CertificateException {
- Object o = JsseJce.beginFipsProvider();
- try {
- return v.validate(chain, null, constraints, authType);
- } finally {
- JsseJce.endFipsProvider(o);
- }
- }
-
- /*
- * Identify the peer by its certificate and hostname.
- *
- * Lifted from sun.net.www.protocol.https.HttpsClient.
- */
- static void checkIdentity(String hostname, X509Certificate cert,
- String algorithm) throws CertificateException {
- if (algorithm != null && algorithm.length() != 0) {
- // if IPv6 strip off the "[]"
- if ((hostname != null) && hostname.startsWith("[") &&
- hostname.endsWith("]")) {
- hostname = hostname.substring(1, hostname.length() - 1);
- }
-
- if (algorithm.equalsIgnoreCase("HTTPS")) {
- HostnameChecker.getInstance(HostnameChecker.TYPE_TLS).match(
- hostname, cert);
- } else if (algorithm.equalsIgnoreCase("LDAP") ||
- algorithm.equalsIgnoreCase("LDAPS")) {
- HostnameChecker.getInstance(HostnameChecker.TYPE_LDAP).match(
- hostname, cert);
- } else {
- throw new CertificateException(
- "Unknown identification algorithm: " + algorithm);
- }
- }
- }
-}
diff --git a/ojluni/src/main/java/sun/security/util/DerIndefLenConverter.java b/ojluni/src/main/java/sun/security/util/DerIndefLenConverter.java
index 78d9e30..cbd5ecc 100755
--- a/ojluni/src/main/java/sun/security/util/DerIndefLenConverter.java
+++ b/ojluni/src/main/java/sun/security/util/DerIndefLenConverter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -156,12 +156,18 @@
}
if (isLongForm(lenByte)) {
lenByte &= LEN_MASK;
- if (lenByte > 4)
+ if (lenByte > 4) {
throw new IOException("Too much data");
- if ((dataSize - dataPos) < (lenByte + 1))
+ }
+ if ((dataSize - dataPos) < (lenByte + 1)) {
throw new IOException("Too little data");
- for (int i = 0; i < lenByte; i++)
+ }
+ for (int i = 0; i < lenByte; i++) {
curLen = (curLen << 8) + (data[dataPos++] & 0xff);
+ }
+ if (curLen < 0) {
+ throw new IOException("Invalid length bytes");
+ }
} else {
curLen = (lenByte & LEN_MASK);
}
@@ -188,10 +194,15 @@
}
if (isLongForm(lenByte)) {
lenByte &= LEN_MASK;
- for (int i = 0; i < lenByte; i++)
+ for (int i = 0; i < lenByte; i++) {
curLen = (curLen << 8) + (data[dataPos++] & 0xff);
- } else
+ }
+ if (curLen < 0) {
+ throw new IOException("Invalid length bytes");
+ }
+ } else {
curLen = (lenByte & LEN_MASK);
+ }
writeLength(curLen);
writeValue(curLen);
}
diff --git a/ojluni/src/main/java/sun/security/util/DerInputBuffer.java b/ojluni/src/main/java/sun/security/util/DerInputBuffer.java
index 786e791..b375c60 100755
--- a/ojluni/src/main/java/sun/security/util/DerInputBuffer.java
+++ b/ojluni/src/main/java/sun/security/util/DerInputBuffer.java
@@ -71,6 +71,16 @@
return retval;
}
+ int getPos() {
+ return pos;
+ }
+
+ byte[] getSlice(int startPos, int size) {
+ byte[] result = new byte[size];
+ System.arraycopy(buf, startPos, result, 0, size);
+ return result;
+ }
+
int peek() throws IOException {
if (pos >= count)
throw new IOException("out of data");
diff --git a/ojluni/src/main/java/sun/security/util/DerInputStream.java b/ojluni/src/main/java/sun/security/util/DerInputStream.java
index e0f77ee..dae8afd 100755
--- a/ojluni/src/main/java/sun/security/util/DerInputStream.java
+++ b/ojluni/src/main/java/sun/security/util/DerInputStream.java
@@ -291,11 +291,28 @@
* (used to initialize an auto-growing data structure)
* @return array of the values in the sequence
*/
- public DerValue[] getSequence(int startLen) throws IOException {
+ public DerValue[] getSequence(int startLen,
+ boolean originalEncodedFormRetained) throws IOException {
tag = (byte)buffer.read();
if (tag != DerValue.tag_Sequence)
throw new IOException("Sequence tag error");
- return readVector(startLen);
+ return readVector(startLen, originalEncodedFormRetained);
+ }
+
+ /**
+ * Return a sequence of encoded entities. ASN.1 sequences are
+ * ordered, and they are often used, like a "struct" in C or C++,
+ * to group data values. They may have optional or context
+ * specific values.
+ *
+ * @param startLen guess about how long the sequence will be
+ * (used to initialize an auto-growing data structure)
+ * @return array of the values in the sequence
+ */
+ public DerValue[] getSequence(int startLen) throws IOException {
+ return getSequence(
+ startLen,
+ false); // no need to retain original encoded form
}
/**
@@ -328,13 +345,22 @@
*/
public DerValue[] getSet(int startLen, boolean implicit)
throws IOException {
+ return getSet(
+ startLen,
+ implicit,
+ false); // no need to retain original encoded form
+ }
+
+ public DerValue[] getSet(int startLen, boolean implicit,
+ boolean originalEncodedFormRetained)
+ throws IOException {
tag = (byte)buffer.read();
if (!implicit) {
if (tag != DerValue.tag_Set) {
throw new IOException("Set tag error");
}
}
- return (readVector(startLen));
+ return (readVector(startLen, originalEncodedFormRetained));
}
/*
@@ -343,6 +369,18 @@
* this same helper routine.
*/
protected DerValue[] readVector(int startLen) throws IOException {
+ return readVector(
+ startLen,
+ false); // no need to retain original encoded form
+ }
+
+ /*
+ * Read a "vector" of values ... set or sequence have the
+ * same encoding, except for the initial tag, so both use
+ * this same helper routine.
+ */
+ protected DerValue[] readVector(int startLen,
+ boolean originalEncodedFormRetained) throws IOException {
DerInputStream newstr;
byte lenByte = (byte)buffer.read();
@@ -387,7 +425,7 @@
DerValue value;
do {
- value = new DerValue(newstr.buffer);
+ value = new DerValue(newstr.buffer, originalEncodedFormRetained);
vec.addElement(value);
} while (newstr.available() > 0);
@@ -566,6 +604,10 @@
value <<= 8;
value += 0x0ff & in.read();
}
+ if (value < 0) {
+ throw new IOException("DerInputStream.getLength(): "
+ + "Invalid length bytes");
+ }
}
return value;
}
diff --git a/ojluni/src/main/java/sun/security/util/DerValue.java b/ojluni/src/main/java/sun/security/util/DerValue.java
index beb51c1..6bca1f7 100755
--- a/ojluni/src/main/java/sun/security/util/DerValue.java
+++ b/ojluni/src/main/java/sun/security/util/DerValue.java
@@ -72,6 +72,12 @@
private int length;
+ /**
+ * The original encoded form of the whole value (tag, length, and value)
+ * or null if the form was not provided or was not retained during parsing.
+ */
+ private byte[] originalEncodedForm;
+
/*
* The type starts at the first byte of the encoding, and
* is one of these tag_* values. That may be all the type
@@ -243,10 +249,12 @@
/*
* package private
*/
- DerValue(DerInputBuffer in) throws IOException {
+ DerValue(DerInputBuffer in, boolean originalEncodedFormRetained)
+ throws IOException {
// XXX must also parse BER-encoded constructed
// values such as sequences, sets...
+ int startPosInInput = in.getPos();
tag = (byte)in.read();
byte lenByte = (byte)in.read();
length = DerInputStream.getLength((lenByte & 0xff), in);
@@ -281,6 +289,11 @@
in.skip(length);
}
+
+ if (originalEncodedFormRetained) {
+ int consumed = in.getPos() - startPosInInput;
+ originalEncodedForm = in.getSlice(startPosInInput, consumed);
+ }
}
/**
@@ -822,6 +835,15 @@
}
/**
+ * Returns the original encoded form or {@code null} if the form was not
+ * retained or is not available.
+ */
+ public byte[] getOriginalEncodedForm() {
+ return (originalEncodedForm != null)
+ ? originalEncodedForm.clone() : null;
+ }
+
+ /**
* Returns a DER-encoded value, such that if it's passed to the
* DerValue constructor, a value equivalent to "this" is returned.
*
diff --git a/ojluni/src/main/java/sun/security/util/HostnameChecker.java b/ojluni/src/main/java/sun/security/util/HostnameChecker.java
deleted file mode 100755
index b3e8971..0000000
--- a/ojluni/src/main/java/sun/security/util/HostnameChecker.java
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.util;
-
-import java.io.IOException;
-import java.util.*;
-
-import java.security.Principal;
-import java.security.cert.*;
-
-import javax.security.auth.x500.X500Principal;
-
-import sun.security.ssl.Krb5Helper;
-import sun.security.x509.X500Name;
-
-import sun.net.util.IPAddressUtil;
-
-/**
- * Class to check hostnames against the names specified in a certificate as
- * required for TLS and LDAP.
- *
- */
-public class HostnameChecker {
-
- // Constant for a HostnameChecker for TLS
- public final static byte TYPE_TLS = 1;
- private final static HostnameChecker INSTANCE_TLS =
- new HostnameChecker(TYPE_TLS);
-
- // Constant for a HostnameChecker for LDAP
- public final static byte TYPE_LDAP = 2;
- private final static HostnameChecker INSTANCE_LDAP =
- new HostnameChecker(TYPE_LDAP);
-
- // constants for subject alt names of type DNS and IP
- private final static int ALTNAME_DNS = 2;
- private final static int ALTNAME_IP = 7;
-
- // the algorithm to follow to perform the check. Currently unused.
- private final byte checkType;
-
- private HostnameChecker(byte checkType) {
- this.checkType = checkType;
- }
-
- /**
- * Get a HostnameChecker instance. checkType should be one of the
- * TYPE_* constants defined in this class.
- */
- public static HostnameChecker getInstance(byte checkType) {
- if (checkType == TYPE_TLS) {
- return INSTANCE_TLS;
- } else if (checkType == TYPE_LDAP) {
- return INSTANCE_LDAP;
- }
- throw new IllegalArgumentException("Unknown check type: " + checkType);
- }
-
- /**
- * Perform the check.
- *
- * @exception CertificateException if the name does not match any of
- * the names specified in the certificate
- */
- public void match(String expectedName, X509Certificate cert)
- throws CertificateException {
- if (isIpAddress(expectedName)) {
- matchIP(expectedName, cert);
- } else {
- matchDNS(expectedName, cert);
- }
- }
-
- /**
- * Perform the check for Kerberos.
- */
- public static boolean match(String expectedName, Principal principal) {
- String hostName = getServerName(principal);
- return (expectedName.equalsIgnoreCase(hostName));
- }
-
- /**
- * Return the Server name from Kerberos principal.
- */
- public static String getServerName(Principal principal) {
- return Krb5Helper.getPrincipalHostName(principal);
- }
-
- /**
- * Test whether the given hostname looks like a literal IPv4 or IPv6
- * address. The hostname does not need to be a fully qualified name.
- *
- * This is not a strict check that performs full input validation.
- * That means if the method returns true, name need not be a correct
- * IP address, rather that it does not represent a valid DNS hostname.
- * Likewise for IP addresses when it returns false.
- */
- private static boolean isIpAddress(String name) {
- if (IPAddressUtil.isIPv4LiteralAddress(name) ||
- IPAddressUtil.isIPv6LiteralAddress(name)) {
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Check if the certificate allows use of the given IP address.
- *
- * From RFC2818:
- * In some cases, the URI is specified as an IP address rather than a
- * hostname. In this case, the iPAddress subjectAltName must be present
- * in the certificate and must exactly match the IP in the URI.
- */
- private static void matchIP(String expectedIP, X509Certificate cert)
- throws CertificateException {
- Collection<List<?>> subjAltNames = cert.getSubjectAlternativeNames();
- if (subjAltNames == null) {
- throw new CertificateException
- ("No subject alternative names present");
- }
- for (List<?> next : subjAltNames) {
- // For IP address, it needs to be exact match
- if (((Integer)next.get(0)).intValue() == ALTNAME_IP) {
- String ipAddress = (String)next.get(1);
- if (expectedIP.equalsIgnoreCase(ipAddress)) {
- return;
- }
- }
- }
- throw new CertificateException("No subject alternative " +
- "names matching " + "IP address " +
- expectedIP + " found");
- }
-
- /**
- * Check if the certificate allows use of the given DNS name.
- *
- * From RFC2818:
- * If a subjectAltName extension of type dNSName is present, that MUST
- * be used as the identity. Otherwise, the (most specific) Common Name
- * field in the Subject field of the certificate MUST be used. Although
- * the use of the Common Name is existing practice, it is deprecated and
- * Certification Authorities are encouraged to use the dNSName instead.
- *
- * Matching is performed using the matching rules specified by
- * [RFC2459]. If more than one identity of a given type is present in
- * the certificate (e.g., more than one dNSName name, a match in any one
- * of the set is considered acceptable.)
- */
- private void matchDNS(String expectedName, X509Certificate cert)
- throws CertificateException {
- Collection<List<?>> subjAltNames = cert.getSubjectAlternativeNames();
- if (subjAltNames != null) {
- boolean foundDNS = false;
- for ( List<?> next : subjAltNames) {
- if (((Integer)next.get(0)).intValue() == ALTNAME_DNS) {
- foundDNS = true;
- String dnsName = (String)next.get(1);
- if (isMatched(expectedName, dnsName)) {
- return;
- }
- }
- }
- if (foundDNS) {
- // if certificate contains any subject alt names of type DNS
- // but none match, reject
- throw new CertificateException("No subject alternative DNS "
- + "name matching " + expectedName + " found.");
- }
- }
- X500Name subjectName = getSubjectX500Name(cert);
- DerValue derValue = subjectName.findMostSpecificAttribute
- (X500Name.commonName_oid);
- if (derValue != null) {
- try {
- if (isMatched(expectedName, derValue.getAsString())) {
- return;
- }
- } catch (IOException e) {
- // ignore
- }
- }
- String msg = "No name matching " + expectedName + " found";
- throw new CertificateException(msg);
- }
-
-
- /**
- * Return the subject of a certificate as X500Name, by reparsing if
- * necessary. X500Name should only be used if access to name components
- * is required, in other cases X500Principal is to be prefered.
- *
- * This method is currently used from within JSSE, do not remove.
- */
- public static X500Name getSubjectX500Name(X509Certificate cert)
- throws CertificateParsingException {
- try {
- Principal subjectDN = cert.getSubjectDN();
- if (subjectDN instanceof X500Name) {
- return (X500Name)subjectDN;
- } else {
- X500Principal subjectX500 = cert.getSubjectX500Principal();
- return new X500Name(subjectX500.getEncoded());
- }
- } catch (IOException e) {
- throw(CertificateParsingException)
- new CertificateParsingException().initCause(e);
- }
- }
-
-
- /**
- * Returns true if name matches against template.<p>
- *
- * The matching is performed as per RFC 2818 rules for TLS and
- * RFC 2830 rules for LDAP.<p>
- *
- * The <code>name</code> parameter should represent a DNS name.
- * The <code>template</code> parameter
- * may contain the wildcard character *
- */
- private boolean isMatched(String name, String template) {
- if (checkType == TYPE_TLS) {
- return matchAllWildcards(name, template);
- } else if (checkType == TYPE_LDAP) {
- return matchLeftmostWildcard(name, template);
- } else {
- return false;
- }
- }
-
-
- /**
- * Returns true if name matches against template.<p>
- *
- * According to RFC 2818, section 3.1 -
- * Names may contain the wildcard character * which is
- * considered to match any single domain name component
- * or component fragment.
- * E.g., *.a.com matches foo.a.com but not
- * bar.foo.a.com. f*.com matches foo.com but not bar.com.
- */
- private static boolean matchAllWildcards(String name,
- String template) {
- name = name.toLowerCase();
- template = template.toLowerCase();
- StringTokenizer nameSt = new StringTokenizer(name, ".");
- StringTokenizer templateSt = new StringTokenizer(template, ".");
-
- if (nameSt.countTokens() != templateSt.countTokens()) {
- return false;
- }
-
- while (nameSt.hasMoreTokens()) {
- if (!matchWildCards(nameSt.nextToken(),
- templateSt.nextToken())) {
- return false;
- }
- }
- return true;
- }
-
-
- /**
- * Returns true if name matches against template.<p>
- *
- * As per RFC 2830, section 3.6 -
- * The "*" wildcard character is allowed. If present, it applies only
- * to the left-most name component.
- * E.g. *.bar.com would match a.bar.com, b.bar.com, etc. but not
- * bar.com.
- */
- private static boolean matchLeftmostWildcard(String name,
- String template) {
- name = name.toLowerCase();
- template = template.toLowerCase();
-
- // Retreive leftmost component
- int templateIdx = template.indexOf(".");
- int nameIdx = name.indexOf(".");
-
- if (templateIdx == -1)
- templateIdx = template.length();
- if (nameIdx == -1)
- nameIdx = name.length();
-
- if (matchWildCards(name.substring(0, nameIdx),
- template.substring(0, templateIdx))) {
-
- // match rest of the name
- return template.substring(templateIdx).equals(
- name.substring(nameIdx));
- } else {
- return false;
- }
- }
-
-
- /**
- * Returns true if the name matches against the template that may
- * contain wildcard char * <p>
- */
- private static boolean matchWildCards(String name, String template) {
-
- int wildcardIdx = template.indexOf("*");
- if (wildcardIdx == -1)
- return name.equals(template);
-
- boolean isBeginning = true;
- String beforeWildcard = "";
- String afterWildcard = template;
-
- while (wildcardIdx != -1) {
-
- // match in sequence the non-wildcard chars in the template.
- beforeWildcard = afterWildcard.substring(0, wildcardIdx);
- afterWildcard = afterWildcard.substring(wildcardIdx + 1);
-
- int beforeStartIdx = name.indexOf(beforeWildcard);
- if ((beforeStartIdx == -1) ||
- (isBeginning && beforeStartIdx != 0)) {
- return false;
- }
- isBeginning = false;
-
- // update the match scope
- name = name.substring(beforeStartIdx + beforeWildcard.length());
- wildcardIdx = afterWildcard.indexOf("*");
- }
- return name.endsWith(afterWildcard);
- }
-}
diff --git a/ojluni/src/main/java/sun/security/x509/X509CertImpl.java b/ojluni/src/main/java/sun/security/x509/X509CertImpl.java
index 5ff1c9b..4f7f81b 100755
--- a/ojluni/src/main/java/sun/security/x509/X509CertImpl.java
+++ b/ojluni/src/main/java/sun/security/x509/X509CertImpl.java
@@ -315,6 +315,24 @@
}
/**
+ * Unmarshal a certificate from its encoded form, parsing a DER value.
+ * This form of constructor is used by agents which need to examine
+ * and use certificate contents.
+ *
+ * @param derVal the der value containing the encoded cert.
+ * @exception CertificateException on parsing and initialization errors.
+ */
+ public X509CertImpl(DerValue derVal, byte[] encoded)
+ throws CertificateException {
+ try {
+ parse(derVal, encoded);
+ } catch (IOException e) {
+ signedCert = null;
+ throw new CertificateException("Unable to initialize, " + e, e);
+ }
+ }
+
+ /**
* Appends the certificate to an output stream.
*
* @param out an input stream to which the certificate is appended.
@@ -1770,6 +1788,24 @@
*/
private void parse(DerValue val)
throws CertificateException, IOException {
+ parse(
+ val,
+ null // use re-encoded form of val as the encoded form
+ );
+ }
+
+ /*
+ * Cert is a SIGNED ASN.1 macro, a three elment sequence:
+ *
+ * - Data to be signed (ToBeSigned) -- the "raw" cert
+ * - Signature algorithm (SigAlgId)
+ * - The signature bits
+ *
+ * This routine unmarshals the certificate, saving the signature
+ * parts away for later verification.
+ */
+ private void parse(DerValue val, byte[] originalEncodedForm)
+ throws CertificateException, IOException {
// check if can over write the certificate
if (readOnly)
throw new CertificateParsingException(
@@ -1779,7 +1815,9 @@
throw new CertificateParsingException(
"invalid DER-encoded certificate data");
- signedCert = val.toByteArray();
+ signedCert =
+ (originalEncodedForm != null)
+ ? originalEncodedForm : val.toByteArray();
DerValue[] seq = new DerValue[3];
seq[0] = val.data.getDerValue();
diff --git a/ojluni/src/main/native/java_util_zip_ZipFile.c b/ojluni/src/main/native/java_util_zip_ZipFile.c
index 7280d97..5353ff4 100644
--- a/ojluni/src/main/native/java_util_zip_ZipFile.c
+++ b/ojluni/src/main/native/java_util_zip_ZipFile.c
@@ -156,6 +156,12 @@
ZIP_Close(jlong_to_ptr(zfile));
}
+JNIEXPORT jint JNICALL
+ZipFile_getFileDescriptor(JNIEnv *env, jclass cls, jlong zfile) {
+ jzfile *zip = jlong_to_ptr(zfile);
+ return zip->zfd;
+}
+
JNIEXPORT jlong JNICALL
ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile,
jbyteArray name, jboolean addSlash)
@@ -390,6 +396,7 @@
}
static JNINativeMethod gMethods[] = {
+ NATIVE_METHOD(ZipFile, getFileDescriptor, "(J)I"),
NATIVE_METHOD(ZipFile, getEntry, "(J[BZ)J"),
NATIVE_METHOD(ZipFile, freeEntry, "(JJ)V"),
NATIVE_METHOD(ZipFile, getNextEntry, "(JI)J"),
diff --git a/ojluni/src/main/native/zip_util.c b/ojluni/src/main/native/zip_util.c
index a4dbe14..5a2a0b8 100644
--- a/ojluni/src/main/native/zip_util.c
+++ b/ojluni/src/main/native/zip_util.c
@@ -142,7 +142,7 @@
}
static int
-ZFILE_read(ZFILE zfd, char *buf, jint nbytes) {
+ZFILE_read(ZFILE zfd, char *buf, jint nbytes, jlong offset) {
#ifdef WIN32
return (int) IO_Read(zfd, buf, nbytes);
#else
@@ -154,7 +154,7 @@
* JVM_IO_INTR is tricky and could cause undesired side effect. So we decided
* to simply call "read" on Solaris/Linux. See details in bug 6304463.
*/
- return read(zfd, buf, nbytes);
+ return pread(zfd, buf, nbytes, offset);
#endif
}
@@ -183,11 +183,11 @@
}
/*
- * Reads len bytes of data into buf.
+ * Reads len bytes of data from the specified offset into buf.
* Returns 0 if all bytes could be read, otherwise returns -1.
*/
static int
-readFully(ZFILE zfd, void *buf, jlong len) {
+readFullyAt(ZFILE zfd, void *buf, jlong len, jlong offset) {
char *bp = (char *) buf;
while (len > 0) {
@@ -195,9 +195,10 @@
jint count = (len < limit) ?
(jint) len :
(jint) limit;
- jint n = ZFILE_read(zfd, bp, count);
+ jint n = ZFILE_read(zfd, bp, count, offset);
if (n > 0) {
bp += n;
+ offset += n;
len -= n;
} else if (n == JVM_IO_ERR && errno == EINTR) {
/* Retry after EINTR (interrupted by signal).
@@ -210,19 +211,6 @@
return 0;
}
-/*
- * Reads len bytes of data from the specified offset into buf.
- * Returns 0 if all bytes could be read, otherwise returns -1.
- */
-static int
-readFullyAt(ZFILE zfd, void *buf, jlong len, jlong offset)
-{
- if (IO_Lseek(zfd, offset, SEEK_SET) == -1) {
- return -1; /* lseek failure. */
- }
-
- return readFully(zfd, buf, len);
-}
/*
* Allocates a new zip file object for the specified file name.
@@ -877,14 +865,17 @@
return NULL;
}
- // Assumption, zfd refers to start of file. Trivially, reuse errbuf.
- if (readFully(zfd, errbuf, 4) != -1) { // errors will be handled later
+ // Trivially, reuse errbuf.
+ if (readFullyAt(zfd, errbuf, 4, 0 /* offset */) != -1) { // errors will be handled later
if (GETSIG(errbuf) == LOCSIG)
zip->locsig = JNI_TRUE;
else
zip->locsig = JNI_FALSE;
}
+ // This lseek is safe because it happens during construction of the ZipFile
+ // object. We must take care not to perform any operations that change the
+ // offset after (see b/30407219).
len = zip->len = IO_Lseek(zfd, 0, SEEK_END);
if (len <= 0) {
if (len == 0) { /* zip file is empty */
@@ -984,7 +975,7 @@
censize = CENSIZE(cen);
if (censize <= bufsize) return cen;
if ((cen = realloc(cen, censize)) == NULL) goto Catch;
- if (readFully(zfd, cen+bufsize, censize-bufsize) == -1) goto Catch;
+ if (readFullyAt(zfd, cen+bufsize, censize-bufsize, cenpos + bufsize) == -1) goto Catch;
return cen;
Catch:
diff --git a/openjdk_java_files.mk b/openjdk_java_files.mk
index 7981058..d746447 100644
--- a/openjdk_java_files.mk
+++ b/openjdk_java_files.mk
@@ -1042,7 +1042,6 @@
ojluni/src/main/java/sun/reflect/CallerSensitive.java \
openjdk_java_files := \
- ojluni/src/main/java/com/sun/net/ssl/internal/ssl/Provider.java \
ojluni/src/main/java/com/sun/net/ssl/internal/ssl/X509ExtendedTrustManager.java \
ojluni/src/main/java/com/sun/security/cert/internal/x509/X509V1CertImpl.java \
ojluni/src/main/java/java/beans/ChangeListenerMap.java \
@@ -1168,11 +1167,6 @@
ojluni/src/main/java/sun/net/www/protocol/http/NegotiateAuthentication.java \
ojluni/src/main/java/sun/net/www/protocol/http/Negotiator.java \
ojluni/src/main/java/sun/net/www/protocol/http/NTLMAuthenticationProxy.java \
- ojluni/src/main/java/sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java \
- ojluni/src/main/java/sun/net/www/protocol/https/DelegateHttpsURLConnection.java \
- ojluni/src/main/java/sun/net/www/protocol/https/Handler.java \
- ojluni/src/main/java/sun/net/www/protocol/https/HttpsClient.java \
- ojluni/src/main/java/sun/net/www/protocol/https/HttpsURLConnectionImpl.java \
ojluni/src/main/java/sun/net/www/protocol/jar/Handler.java \
ojluni/src/main/java/sun/net/www/protocol/jar/JarFileFactory.java \
ojluni/src/main/java/sun/net/www/protocol/jar/JarURLConnection.java \
@@ -1309,61 +1303,6 @@
ojluni/src/main/java/sun/security/provider/certpath/X509CertificatePair.java \
ojluni/src/main/java/sun/security/provider/X509Factory.java \
ojluni/src/main/java/sun/security/rsa/SunRsaSignEntries.java \
- ojluni/src/main/java/sun/security/ssl/Alerts.java \
- ojluni/src/main/java/sun/security/ssl/AppInputStream.java \
- ojluni/src/main/java/sun/security/ssl/AppOutputStream.java \
- ojluni/src/main/java/sun/security/ssl/BaseSSLSocketImpl.java \
- ojluni/src/main/java/sun/security/ssl/ByteBufferInputStream.java \
- ojluni/src/main/java/sun/security/ssl/CipherBox.java \
- ojluni/src/main/java/sun/security/ssl/CipherSuite.java \
- ojluni/src/main/java/sun/security/ssl/CipherSuiteList.java \
- ojluni/src/main/java/sun/security/ssl/ClientHandshaker.java \
- ojluni/src/main/java/sun/security/ssl/Debug.java \
- ojluni/src/main/java/sun/security/ssl/DHClientKeyExchange.java \
- ojluni/src/main/java/sun/security/ssl/DHCrypt.java \
- ojluni/src/main/java/sun/security/ssl/ECDHClientKeyExchange.java \
- ojluni/src/main/java/sun/security/ssl/ECDHCrypt.java \
- ojluni/src/main/java/sun/security/ssl/EngineArgs.java \
- ojluni/src/main/java/sun/security/ssl/EngineInputRecord.java \
- ojluni/src/main/java/sun/security/ssl/EngineOutputRecord.java \
- ojluni/src/main/java/sun/security/ssl/EngineWriter.java \
- ojluni/src/main/java/sun/security/ssl/EphemeralKeyManager.java \
- ojluni/src/main/java/sun/security/ssl/HandshakeHash.java \
- ojluni/src/main/java/sun/security/ssl/HandshakeInStream.java \
- ojluni/src/main/java/sun/security/ssl/HandshakeMessage.java \
- ojluni/src/main/java/sun/security/ssl/HandshakeOutStream.java \
- ojluni/src/main/java/sun/security/ssl/Handshaker.java \
- ojluni/src/main/java/sun/security/ssl/HelloExtensions.java \
- ojluni/src/main/java/sun/security/ssl/InputRecord.java \
- ojluni/src/main/java/sun/security/ssl/JsseJce.java \
- ojluni/src/main/java/sun/security/ssl/KerberosClientKeyExchange.java \
- ojluni/src/main/java/sun/security/ssl/Krb5Helper.java \
- ojluni/src/main/java/sun/security/ssl/Krb5Proxy.java \
- ojluni/src/main/java/sun/security/ssl/MAC.java \
- ojluni/src/main/java/sun/security/ssl/OutputRecord.java \
- ojluni/src/main/java/sun/security/ssl/ProtocolList.java \
- ojluni/src/main/java/sun/security/ssl/ProtocolVersion.java \
- ojluni/src/main/java/sun/security/ssl/RandomCookie.java \
- ojluni/src/main/java/sun/security/ssl/Record.java \
- ojluni/src/main/java/sun/security/ssl/RSAClientKeyExchange.java \
- ojluni/src/main/java/sun/security/ssl/RSASignature.java \
- ojluni/src/main/java/sun/security/ssl/ServerHandshaker.java \
- ojluni/src/main/java/sun/security/ssl/SessionId.java \
- ojluni/src/main/java/sun/security/ssl/SignatureAndHashAlgorithm.java \
- ojluni/src/main/java/sun/security/ssl/SSLAlgorithmConstraints.java \
- ojluni/src/main/java/sun/security/ssl/SSLContextImpl.java \
- ojluni/src/main/java/sun/security/ssl/SSLEngineImpl.java \
- ojluni/src/main/java/sun/security/ssl/SSLServerSocketFactoryImpl.java \
- ojluni/src/main/java/sun/security/ssl/SSLServerSocketImpl.java \
- ojluni/src/main/java/sun/security/ssl/SSLSessionContextImpl.java \
- ojluni/src/main/java/sun/security/ssl/SSLSessionImpl.java \
- ojluni/src/main/java/sun/security/ssl/SSLSocketFactoryImpl.java \
- ojluni/src/main/java/sun/security/ssl/SSLSocketImpl.java \
- ojluni/src/main/java/sun/security/ssl/SunJSSE.java \
- ojluni/src/main/java/sun/security/ssl/SunX509KeyManagerImpl.java \
- ojluni/src/main/java/sun/security/ssl/TrustManagerFactoryImpl.java \
- ojluni/src/main/java/sun/security/ssl/X509KeyManagerImpl.java \
- ojluni/src/main/java/sun/security/ssl/X509TrustManagerImpl.java \
ojluni/src/main/java/sun/security/timestamp/TimestampToken.java \
ojluni/src/main/java/sun/security/util/BitArray.java \
ojluni/src/main/java/sun/security/util/ByteArrayLexOrder.java \
@@ -1377,7 +1316,6 @@
ojluni/src/main/java/sun/security/util/DerOutputStream.java \
ojluni/src/main/java/sun/security/util/DerValue.java \
ojluni/src/main/java/sun/security/util/DisabledAlgorithmConstraints.java \
- ojluni/src/main/java/sun/security/util/HostnameChecker.java \
ojluni/src/main/java/sun/security/util/KeyUtil.java \
ojluni/src/main/java/sun/security/util/Length.java \
ojluni/src/main/java/sun/security/util/ManifestDigester.java \
diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java
index d414d4b..675aa3d 100644
--- a/support/src/test/java/libcore/java/security/StandardNames.java
+++ b/support/src/test/java/libcore/java/security/StandardNames.java
@@ -988,6 +988,14 @@
"TLS_PSK_WITH_AES_256_CBC_SHA"
);
+ // Should be updated to match BoringSSL's defaults when they change.
+ // https://android.googlesource.com/platform/external/boringssl/+/master/src/ssl/t1_lib.c#305
+ public static final List<String> ELLIPTIC_CURVES_DEFAULT = Arrays.asList(
+ "secp256r1 (23)",
+ "secp384r1 (24)",
+ "secp521r1 (25)"
+ );
+
private static final Set<String> PERMITTED_DEFAULT_KEY_EXCHANGE_ALGS =
new HashSet<String>(Arrays.asList("RSA",
"DHE_RSA",
@@ -1154,6 +1162,10 @@
}
}
+ public static void assertDefaultEllipticCurves(String[] curves) {
+ assertEquals(ELLIPTIC_CURVES_DEFAULT, Arrays.asList(curves));
+ }
+
public static void assertSSLContextEnabledProtocols(String version, String[] protocols) {
assertEquals("For protocol \"" + version + "\"",
Arrays.toString(SSL_CONTEXT_PROTOCOLS_ENABLED.get(version)),
diff --git a/support/src/test/java/libcore/tlswire/handshake/EllipticCurve.java b/support/src/test/java/libcore/tlswire/handshake/EllipticCurve.java
new file mode 100644
index 0000000..a409c41
--- /dev/null
+++ b/support/src/test/java/libcore/tlswire/handshake/EllipticCurve.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.tlswire.handshake;
+
+/**
+ * {@code EllipticCurve} enum from RFC 4492 section 5.1.1. Curves are assigned
+ * via the
+ * <a href="https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8">IANA registry</a>.
+ */
+public enum EllipticCurve {
+ SECT163K1(1, "sect163k1"),
+ SECT163R1(2, "sect163r1"),
+ SECT163R2(3, "sect163r2"),
+ SECT193R1(4, "sect193r1"),
+ SECT193R2(5, "sect193r2"),
+ SECT233K1(6, "sect233k1"),
+ SECT233R1(7, "sect233r1"),
+ SECT239K1(8, "sect239k1"),
+ SECT283K1(9, "sect283k1"),
+ SECT283R1(10, "sect283r1"),
+ SECT409K1(11, "sect409k1"),
+ SECT409R1(12, "sect409r1"),
+ SECT571K1(13, "sect571k1"),
+ SECT571R1(14, "sect571r1"),
+ SECP160K1(15, "secp160k1"),
+ SECP160R1(16, "secp160r1"),
+ SECP160R2(17, "secp160r2"),
+ SECP192K1(18, "secp192k1"),
+ SECP192R1(19, "secp192r1"),
+ SECP224K1(20, "secp224k1"),
+ SECP256K1(22, "secp256k1"),
+ SECP256R1(23, "secp256r1"),
+ SECP384R1(24, "secp384r1"),
+ SECP521R1(25, "secp521r1"),
+ BRAINPOOLP256R1(26, "brainpoolP256r1"),
+ BRAINPOOLP384R1(27, "brainpoolP384r1"),
+ BRAINPOOLP521R1(28, "brainpoolP521r1"),
+ X25519(29, "x25519"),
+ X448(30, "x448"),
+ ARBITRARY_PRIME(0xFF01, "arbitrary_explicit_prime_curves"),
+ ARBITRARY_CHAR2(0xFF02, "arbitrary_explicit_char2_curves");
+
+ public final int identifier;
+ public final String name;
+
+ private EllipticCurve(int identifier, String name) {
+ this.identifier = identifier;
+ this.name = name;
+ }
+
+ public static EllipticCurve fromIdentifier(int identifier) {
+ for (EllipticCurve curve : values()) {
+ if (curve.identifier == identifier) {
+ return curve;
+ }
+ }
+ throw new AssertionError("Unknown curve identifier " + identifier);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(name);
+ sb.append(" (");
+ sb.append(identifier);
+ sb.append(')');
+ return sb.toString();
+ }
+}
diff --git a/support/src/test/java/libcore/tlswire/handshake/EllipticCurvesHelloExtension.java b/support/src/test/java/libcore/tlswire/handshake/EllipticCurvesHelloExtension.java
new file mode 100644
index 0000000..19749a3
--- /dev/null
+++ b/support/src/test/java/libcore/tlswire/handshake/EllipticCurvesHelloExtension.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.tlswire.handshake;
+
+import libcore.tlswire.util.IoUtils;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@code elliptic_curves} {@link HelloExtension} from RFC 4492 section 5.1.1.
+ */
+public class EllipticCurvesHelloExtension extends HelloExtension {
+ public List<EllipticCurve> supported;
+ public boolean wellFormed;
+
+ @Override
+ protected void parseData() throws IOException {
+ byte[] ellipticCurvesListBytes = IoUtils.readTlsVariableLengthByteVector(
+ new DataInputStream(new ByteArrayInputStream(data)), 0xffff);
+ ByteArrayInputStream ellipticCurvesListIn = new ByteArrayInputStream(ellipticCurvesListBytes);
+ DataInputStream in = new DataInputStream(ellipticCurvesListIn);
+ wellFormed = (ellipticCurvesListIn.available() % 2) == 0;
+ supported = new ArrayList<EllipticCurve>(ellipticCurvesListIn.available() / 2);
+ while (ellipticCurvesListIn.available() >= 2) {
+ int curve_id = in.readUnsignedShort();
+ supported.add(EllipticCurve.fromIdentifier(curve_id));
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("HelloExtension{type: elliptic_curves, wellFormed: ");
+ sb.append(wellFormed);
+ sb.append(", supported: ");
+ sb.append(supported);
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/support/src/test/java/libcore/tlswire/handshake/HelloExtension.java b/support/src/test/java/libcore/tlswire/handshake/HelloExtension.java
index a648cdf..2a77687 100644
--- a/support/src/test/java/libcore/tlswire/handshake/HelloExtension.java
+++ b/support/src/test/java/libcore/tlswire/handshake/HelloExtension.java
@@ -29,6 +29,7 @@
public class HelloExtension {
public static final int TYPE_SERVER_NAME = 0;
+ public static final int TYPE_ELLIPTIC_CURVES = 10;
public static final int TYPE_PADDING = 21;
public static final int TYPE_SESSION_TICKET = 35;
public static final int TYPE_RENEGOTIATION_INFO = 65281;
@@ -45,7 +46,7 @@
TYPE_TO_NAME.put(7, "client_authz");
TYPE_TO_NAME.put(8, "server_authz");
TYPE_TO_NAME.put(9, "cert_type");
- TYPE_TO_NAME.put(10, "elliptic_curves");
+ TYPE_TO_NAME.put(TYPE_ELLIPTIC_CURVES, "elliptic_curves");
TYPE_TO_NAME.put(11, "ec_point_formats");
TYPE_TO_NAME.put(12, "srp");
TYPE_TO_NAME.put(13, "signature_algorithms");
@@ -75,6 +76,9 @@
case TYPE_SERVER_NAME:
result = new ServerNameHelloExtension();
break;
+ case TYPE_ELLIPTIC_CURVES:
+ result = new EllipticCurvesHelloExtension();
+ break;
default:
result = new HelloExtension();
break;