1 /* 2 * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.ssl; 27 28 import java.io.IOException; 29 import java.io.PrintStream; 30 import java.util.*; 31 import javax.net.ssl.*; 32 33 /** 34 * This file contains all the classes relevant to TLS Extensions for the 35 * ClientHello and ServerHello messages. The extension mechanism and 36 * several extensions are defined in RFC 3546. Additional extensions are 37 * defined in the ECC RFC 4492. 38 * 39 * Currently, only the two ECC extensions are fully supported. 40 * 41 * The classes contained in this file are: 42 * . HelloExtensions: a List of extensions as used in the client hello 43 * and server hello messages. 44 * . ExtensionType: an enum style class for the extension type 45 * . HelloExtension: abstract base class for all extensions. All subclasses 46 * must be immutable. 47 * 48 * . UnknownExtension: used to represent all parsed extensions that we do not 49 * explicitly support. 50 * . ServerNameExtension: the server_name extension. 51 * . SignatureAlgorithmsExtension: the signature_algorithms extension. 52 * . SupportedEllipticCurvesExtension: the ECC supported curves extension. 53 * . SupportedEllipticPointFormatsExtension: the ECC supported point formats 54 * (compressed/uncompressed) extension. 55 * 56 * @since 1.6 57 * @author Andreas Sterbenz 58 */ 59 final class HelloExtensions { 60 61 private List<HelloExtension> extensions; 62 private int encodedLength; 63 64 HelloExtensions() { 65 extensions = Collections.emptyList(); 66 } 67 68 HelloExtensions(HandshakeInStream s) throws IOException { 69 int len = s.getInt16(); 70 extensions = new ArrayList<HelloExtension>(); 71 encodedLength = len + 2; 72 while (len > 0) { 73 int type = s.getInt16(); 74 int extlen = s.getInt16(); 75 ExtensionType extType = ExtensionType.get(type); 76 HelloExtension extension; 77 if (extType == ExtensionType.EXT_SERVER_NAME) { 78 extension = new ServerNameExtension(s, extlen); 79 } else if (extType == ExtensionType.EXT_SIGNATURE_ALGORITHMS) { 80 extension = new SignatureAlgorithmsExtension(s, extlen); 81 } else if (extType == ExtensionType.EXT_ELLIPTIC_CURVES) { 82 extension = new SupportedEllipticCurvesExtension(s, extlen); 83 } else if (extType == ExtensionType.EXT_EC_POINT_FORMATS) { 84 extension = 85 new SupportedEllipticPointFormatsExtension(s, extlen); 86 } else if (extType == ExtensionType.EXT_RENEGOTIATION_INFO) { 87 extension = new RenegotiationInfoExtension(s, extlen); 88 } else if (extType == ExtensionType.EXT_MAX_FRAGMENT_LENGTH) { 89 extension = new MaxFragmentLengthExtension(s, extlen); 90 } else { 91 extension = new UnknownExtension(s, extlen, extType); 92 } 93 extensions.add(extension); 94 len -= extlen + 4; 95 } 96 if (len != 0) { 97 throw new SSLProtocolException( 98 "Error parsing extensions: extra data"); 99 } 100 } 101 102 // Return the List of extensions. Must not be modified by the caller. 103 List<HelloExtension> list() { 104 return extensions; 105 } 106 107 void add(HelloExtension ext) { 108 if (extensions.isEmpty()) { 109 extensions = new ArrayList<HelloExtension>(); 110 } 111 extensions.add(ext); 112 encodedLength = -1; 113 } 114 115 HelloExtension get(ExtensionType type) { 116 for (HelloExtension ext : extensions) { 117 if (ext.type == type) { 118 return ext; 119 } 120 } 121 return null; 122 } 123 124 int length() { 125 if (encodedLength >= 0) { 126 return encodedLength; 127 } 128 if (extensions.isEmpty()) { 129 encodedLength = 0; 130 } else { 131 encodedLength = 2; 132 for (HelloExtension ext : extensions) { 133 encodedLength += ext.length(); 134 } 135 } 136 return encodedLength; 137 } 138 139 void send(HandshakeOutStream s) throws IOException { 140 int length = length(); 141 if (length == 0) { 142 return; 143 } 144 s.putInt16(length - 2); 145 for (HelloExtension ext : extensions) { 146 ext.send(s); 147 } 148 } 149 150 void print(PrintStream s) throws IOException { 151 for (HelloExtension ext : extensions) { 152 s.println(ext.toString()); 153 } 154 } 155 }