16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package sun.security.ssl;
27
28 import java.io.IOException;
29 import java.io.PrintStream;
30 import java.util.*;
31
32 import java.security.spec.ECParameterSpec;
33
34 import javax.net.ssl.SSLProtocolException;
35
36 /**
37 * This file contains all the classes relevant to TLS Extensions for the
38 * ClientHello and ServerHello messages. The extension mechanism and
39 * several extensions are defined in RFC 3546. Additional extensions are
40 * defined in the ECC RFC 4492.
41 *
42 * Currently, only the two ECC extensions are fully supported.
43 *
44 * The classes contained in this file are:
45 * . HelloExtensions: a List of extensions as used in the client hello
46 * and server hello messages.
47 * . ExtensionType: an enum style class for the extension type
48 * . HelloExtension: abstract base class for all extensions. All subclasses
49 * must be immutable.
50 *
51 * . UnknownExtension: used to represent all parsed extensions that we do not
52 * explicitly support.
53 * . ServerNameExtension: partially implemented server_name extension.
54 * . SupportedEllipticCurvesExtension: the ECC supported curves extension.
55 * . SupportedEllipticPointFormatsExtension: the ECC supported point formats
130 return encodedLength;
131 }
132
133 void send(HandshakeOutStream s) throws IOException {
134 int length = length();
135 if (length == 0) {
136 return;
137 }
138 s.putInt16(length - 2);
139 for (HelloExtension ext : extensions) {
140 ext.send(s);
141 }
142 }
143
144 void print(PrintStream s) throws IOException {
145 for (HelloExtension ext : extensions) {
146 s.println(ext.toString());
147 }
148 }
149 }
150
151 final class ExtensionType {
152
153 final int id;
154 final String name;
155
156 private ExtensionType(int id, String name) {
157 this.id = id;
158 this.name = name;
159 }
160
161 public String toString() {
162 return name;
163 }
164
165 static List<ExtensionType> knownExtensions = new ArrayList<ExtensionType>(8);
166
167 static ExtensionType get(int id) {
168 for (ExtensionType ext : knownExtensions) {
169 if (ext.id == id) {
170 return ext;
244 final class ServerNameExtension extends HelloExtension {
245
246 final static int NAME_HOST_NAME = 0;
247
248 private List<ServerName> names;
249
250 ServerNameExtension(HandshakeInStream s, int len)
251 throws IOException {
252 super(ExtensionType.EXT_SERVER_NAME);
253 names = new ArrayList<ServerName>();
254 while (len > 0) {
255 ServerName name = new ServerName(s);
256 names.add(name);
257 len -= name.length + 2;
258 }
259 if (len != 0) {
260 throw new SSLProtocolException("Invalid server_name extension");
261 }
262 }
263
264 static class ServerName {
265 final int length;
266 final int type;
267 final byte[] data;
268 final String hostname;
269
270 ServerName(HandshakeInStream s) throws IOException {
271 length = s.getInt16();
272 type = s.getInt8();
273 data = s.getBytes16();
274 if (type == NAME_HOST_NAME) {
275 hostname = new String(data, "UTF8");
276 } else {
277 hostname = null;
278 }
279 }
280
281 public String toString() {
282 if (type == NAME_HOST_NAME) {
283 return "host_name: " + hostname;
284 } else {
285 return "unknown-" + type + ": " + Debug.toString(data);
286 }
287 }
288 }
289
290 int length() {
291 throw new RuntimeException("not yet supported");
292 }
293
294 void send(HandshakeOutStream s) throws IOException {
295 throw new RuntimeException("not yet supported");
296 }
297
298 public String toString() {
299 return "Unsupported extension " + type + ", " + names.toString();
300 }
301 }
302
303 final class SupportedEllipticCurvesExtension extends HelloExtension {
304
305 // the extension value to send in the ClientHello message
306 static final SupportedEllipticCurvesExtension DEFAULT;
307
308 private static final boolean fips;
309
310 static {
311 int[] ids;
312 fips = SunJSSE.isFIPS();
313 if (fips == false) {
314 ids = new int[] {
315 // NIST curves first
316 // prefer NIST P-256, rest in order of increasing key length
317 23, 1, 3, 19, 21, 6, 7, 9, 10, 24, 11, 12, 25, 13, 14,
318 // non-NIST curves
319 15, 16, 17, 2, 18, 4, 5, 20, 8, 22,
|
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package sun.security.ssl;
27
28 import java.io.IOException;
29 import java.io.PrintStream;
30 import java.util.*;
31
32 import java.security.spec.ECParameterSpec;
33
34 import javax.net.ssl.SSLProtocolException;
35
36
37 /**
38 * This file contains all the classes relevant to TLS Extensions for the
39 * ClientHello and ServerHello messages. The extension mechanism and
40 * several extensions are defined in RFC 3546. Additional extensions are
41 * defined in the ECC RFC 4492.
42 *
43 * Currently, only the two ECC extensions are fully supported.
44 *
45 * The classes contained in this file are:
46 * . HelloExtensions: a List of extensions as used in the client hello
47 * and server hello messages.
48 * . ExtensionType: an enum style class for the extension type
49 * . HelloExtension: abstract base class for all extensions. All subclasses
50 * must be immutable.
51 *
52 * . UnknownExtension: used to represent all parsed extensions that we do not
53 * explicitly support.
54 * . ServerNameExtension: partially implemented server_name extension.
55 * . SupportedEllipticCurvesExtension: the ECC supported curves extension.
56 * . SupportedEllipticPointFormatsExtension: the ECC supported point formats
131 return encodedLength;
132 }
133
134 void send(HandshakeOutStream s) throws IOException {
135 int length = length();
136 if (length == 0) {
137 return;
138 }
139 s.putInt16(length - 2);
140 for (HelloExtension ext : extensions) {
141 ext.send(s);
142 }
143 }
144
145 void print(PrintStream s) throws IOException {
146 for (HelloExtension ext : extensions) {
147 s.println(ext.toString());
148 }
149 }
150 }
151 final class ExtensionType {
152
153 final int id;
154 final String name;
155
156 private ExtensionType(int id, String name) {
157 this.id = id;
158 this.name = name;
159 }
160
161 public String toString() {
162 return name;
163 }
164
165 static List<ExtensionType> knownExtensions = new ArrayList<ExtensionType>(8);
166
167 static ExtensionType get(int id) {
168 for (ExtensionType ext : knownExtensions) {
169 if (ext.id == id) {
170 return ext;
244 final class ServerNameExtension extends HelloExtension {
245
246 final static int NAME_HOST_NAME = 0;
247
248 private List<ServerName> names;
249
250 ServerNameExtension(HandshakeInStream s, int len)
251 throws IOException {
252 super(ExtensionType.EXT_SERVER_NAME);
253 names = new ArrayList<ServerName>();
254 while (len > 0) {
255 ServerName name = new ServerName(s);
256 names.add(name);
257 len -= name.length + 2;
258 }
259 if (len != 0) {
260 throw new SSLProtocolException("Invalid server_name extension");
261 }
262 }
263
264 ServerNameExtension(String serverName) {
265 super(ExtensionType.EXT_SERVER_NAME);
266 names = new ArrayList<ServerName>(1);
267 if ((serverName != null)&&(serverName.length()>0)) {
268 names.add(new ServerName(serverName));
269 }
270 }
271
272 static class ServerName {
273 final int length;
274 final int type;
275 final byte[] data;
276 final String hostname;
277
278 ServerName(HandshakeInStream s) throws IOException {
279 length = s.getInt16();
280 type = s.getInt8();
281 data = s.getBytes16();
282 if (type == NAME_HOST_NAME) {
283 hostname = new String(data, "UTF8");
284 } else {
285 hostname = null;
286 }
287 }
288
289 ServerName(String hostname) {
290 this.hostname = hostname;
291 byte[] hostnameAsUTF8 = null;
292 try {
293 hostnameAsUTF8 = hostname.getBytes("UTF-8");
294 } catch (java.io.UnsupportedEncodingException ex) {
295 // UTF-8 encoding should reliably be present.
296 throw new RuntimeException(ex);
297 }
298 this.data = hostnameAsUTF8;
299 this.type = NAME_HOST_NAME;
300 this.length = this.data.length + 3;
301 }
302
303 public String toString() {
304 if (type == NAME_HOST_NAME) {
305 return "host_name: " + hostname;
306 } else {
307 return "unknown-" + type + ": " + Debug.toString(data);
308 }
309 }
310 }
311
312 int length() {
313 if (names.size() == 0)
314 return 0;
315 int serverNameListLength = 0;
316 for (ServerName sn : names) {
317 serverNameListLength += sn.length + 2;
318 }
319 return serverNameListLength + 4;
320 }
321
322 void send(HandshakeOutStream s) throws IOException {
323 if (names.size() == 0)
324 return;
325 s.putInt16(type.id);
326 int serverNameListLength = 0;
327 for (ServerName sn : names) {
328 serverNameListLength += sn.length + 2;
329 }
330 s.putInt16(serverNameListLength);
331 for (ServerName sn : names) {
332 s.putInt16(sn.length);
333 s.putInt8(sn.type);
334 s.putBytes16(sn.data);
335 }
336 }
337
338 public String toString() {
339 StringBuilder sb = new StringBuilder();
340 sb.append("Extension " + type + ", host names:\n");
341 for (ServerName sn : names) {
342 sb.append(" " + sn + "\n");
343 }
344 return sb.toString();
345 }
346 }
347
348 final class SupportedEllipticCurvesExtension extends HelloExtension {
349
350 // the extension value to send in the ClientHello message
351 static final SupportedEllipticCurvesExtension DEFAULT;
352
353 private static final boolean fips;
354
355 static {
356 int[] ids;
357 fips = SunJSSE.isFIPS();
358 if (fips == false) {
359 ids = new int[] {
360 // NIST curves first
361 // prefer NIST P-256, rest in order of increasing key length
362 23, 1, 3, 19, 21, 6, 7, 9, 10, 24, 11, 12, 25, 13, 14,
363 // non-NIST curves
364 15, 16, 17, 2, 18, 4, 5, 20, 8, 22,
|