1 /* 2 * Copyright (c) 2006, 2017, 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 6066. Additional extensions are 37 * defined in the ECC RFC 4492 and the ALPN extension is defined in RFC 7301. 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 * . SupportedGroupsExtension: the supported groups extension. 53 * . EllipticPointFormatsExtension: the ECC supported point formats 54 * (compressed/uncompressed) extension. 55 * . ALPNExtension: the application_layer_protocol_negotiation extension. 56 * 57 * @since 1.6 58 * @author Andreas Sterbenz 59 */ 60 final class HelloExtensions { 61 62 private List<HelloExtension> extensions; 63 private int encodedLength; 64 65 HelloExtensions() { 66 extensions = Collections.emptyList(); 67 } 68 69 HelloExtensions(HandshakeInStream s) throws IOException { 70 int len = s.getInt16(); 71 extensions = new ArrayList<HelloExtension>(); 72 encodedLength = len + 2; 73 while (len > 0) { 74 int type = s.getInt16(); 75 int extlen = s.getInt16(); 76 ExtensionType extType = ExtensionType.get(type); 77 HelloExtension extension; 78 if (extType == ExtensionType.EXT_SERVER_NAME) { 79 extension = new ServerNameExtension(s, extlen); 80 } else if (extType == ExtensionType.EXT_SIGNATURE_ALGORITHMS) { 81 extension = new SignatureAlgorithmsExtension(s, extlen); 82 } else if (extType == ExtensionType.EXT_SUPPORTED_GROUPS) { 83 extension = new SupportedGroupsExtension(s, extlen); 84 } else if (extType == ExtensionType.EXT_EC_POINT_FORMATS) { 85 extension = new EllipticPointFormatsExtension(s, extlen); 86 } else if (extType == ExtensionType.EXT_RENEGOTIATION_INFO) { 87 extension = new RenegotiationInfoExtension(s, extlen); 88 } else if (extType == ExtensionType.EXT_ALPN) { 89 extension = new ALPNExtension(s, extlen); 90 } else if (extType == ExtensionType.EXT_MAX_FRAGMENT_LENGTH) { 91 extension = new MaxFragmentLengthExtension(s, extlen); 92 } else if (extType == ExtensionType.EXT_STATUS_REQUEST) { 93 extension = new CertStatusReqExtension(s, extlen); 94 } else if (extType == ExtensionType.EXT_STATUS_REQUEST_V2) { 95 extension = new CertStatusReqListV2Extension(s, extlen); 96 } else if (extType == ExtensionType.EXT_EXTENDED_MASTER_SECRET) { 97 extension = new ExtendedMasterSecretExtension(s, extlen); 98 } else { 99 extension = new UnknownExtension(s, extlen, extType); 100 } 101 extensions.add(extension); 102 len -= extlen + 4; 103 } 104 if (len != 0) { 105 throw new SSLProtocolException( 106 "Error parsing extensions: extra data"); 107 } 108 } 109 110 // Return the List of extensions. Must not be modified by the caller. 111 List<HelloExtension> list() { 112 return extensions; 113 } 114 115 void add(HelloExtension ext) { 116 if (extensions.isEmpty()) { 117 extensions = new ArrayList<HelloExtension>(); 118 } 119 extensions.add(ext); 120 encodedLength = -1; 121 } 122 123 HelloExtension get(ExtensionType type) { 124 for (HelloExtension ext : extensions) { 125 if (ext.type == type) { 126 return ext; 127 } 128 } 129 return null; 130 } 131 132 int length() { 133 if (encodedLength >= 0) { 134 return encodedLength; 135 } 136 if (extensions.isEmpty()) { 137 encodedLength = 0; 138 } else { 139 encodedLength = 2; 140 for (HelloExtension ext : extensions) { 141 encodedLength += ext.length(); 142 } 143 } 144 return encodedLength; 145 } 146 147 void send(HandshakeOutStream s) throws IOException { 148 int length = length(); 149 if (length == 0) { 150 return; 151 } 152 s.putInt16(length - 2); 153 for (HelloExtension ext : extensions) { 154 ext.send(s); 155 } 156 } 157 158 void print(PrintStream s) throws IOException { 159 for (HelloExtension ext : extensions) { 160 s.println(ext.toString()); 161 } 162 } 163 }