1 /* 2 * Copyright (c) 2018, 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.nio.ByteBuffer; 30 import java.text.MessageFormat; 31 import java.util.Locale; 32 import sun.security.ssl.SSLHandshake.HandshakeMessage; 33 34 /** 35 * Pack of the EncryptedExtensions handshake message. 36 */ 37 final class EncryptedExtensions { 38 static final HandshakeProducer handshakeProducer = 39 new EncryptedExtensionsProducer(); 40 static final SSLConsumer handshakeConsumer = 41 new EncryptedExtensionsConsumer(); 42 43 /** 44 * The EncryptedExtensions handshake message. 45 */ 46 static final class EncryptedExtensionsMessage extends HandshakeMessage { 47 private final SSLExtensions extensions; 48 49 EncryptedExtensionsMessage( 50 HandshakeContext handshakeContext) throws IOException { 51 super(handshakeContext); 52 this.extensions = new SSLExtensions(this); 53 } 54 55 EncryptedExtensionsMessage(HandshakeContext handshakeContext, 56 ByteBuffer m) throws IOException { 57 super(handshakeContext); 58 59 // struct { 60 // Extension extensions<0..2^16-1>; 61 // } EncryptedExtensions; 62 if (m.remaining() < 2) { 63 handshakeContext.conContext.fatal(Alert.ILLEGAL_PARAMETER, 64 "Invalid EncryptedExtensions handshake message: " + 65 "no sufficient data"); 66 } 67 68 SSLExtension[] encryptedExtensions = 69 handshakeContext.sslConfig.getEnabledExtensions( 70 SSLHandshake.ENCRYPTED_EXTENSIONS); 71 this.extensions = new SSLExtensions(this, m, encryptedExtensions); 72 } 73 74 @Override 75 SSLHandshake handshakeType() { 76 return SSLHandshake.ENCRYPTED_EXTENSIONS; 77 } 78 79 @Override 80 int messageLength() { 81 int extLen = extensions.length(); 82 if (extLen == 0) { 83 extLen = 2; // empty extensions 84 } 85 return extLen; 86 } 87 88 @Override 89 void send(HandshakeOutStream hos) throws IOException { 90 // Is it an empty extensions? 91 if (extensions.length() == 0) { 92 hos.putInt16(0); 93 } else { 94 extensions.send(hos); 95 } 96 } 97 98 @Override 99 public String toString() { 100 MessageFormat messageFormat = new MessageFormat( 101 "\"EncryptedExtensions\": [\n" + 102 "{0}\n" + 103 "]", 104 Locale.ENGLISH); 105 Object[] messageFields = { 106 Utilities.indent(extensions.toString()) 107 }; 108 109 return messageFormat.format(messageFields); 110 } 111 } 112 113 /** 114 * The EncryptedExtensions handshake message consumer. 115 */ 116 private static final class EncryptedExtensionsProducer 117 implements HandshakeProducer { 118 // Prevent instantiation of this class. 119 private EncryptedExtensionsProducer() { 120 // blank 121 } 122 123 @Override 124 public byte[] produce(ConnectionContext context, 125 HandshakeMessage message) throws IOException { 126 // The producing happens in server side only. 127 ServerHandshakeContext shc = (ServerHandshakeContext)context; 128 129 // Change client/server handshake traffic secrets. 130 // TODO 131 132 EncryptedExtensionsMessage eem = 133 new EncryptedExtensionsMessage(shc); 134 SSLExtension[] extTypes = 135 shc.sslConfig.getEnabledExtensions( 136 SSLHandshake.ENCRYPTED_EXTENSIONS, 137 shc.negotiatedProtocol); 138 eem.extensions.produce(shc, extTypes); 139 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 140 SSLLogger.fine("Produced EncryptedExtensions message", eem); 141 } 142 143 // Output the handshake message. 144 eem.write(shc.handshakeOutput); 145 shc.handshakeOutput.flush(); 146 147 // The handshake message has been delivered. 148 return null; 149 } 150 } 151 152 /** 153 * The EncryptedExtensions handshake message consumer. 154 */ 155 private static final class EncryptedExtensionsConsumer 156 implements SSLConsumer { 157 // Prevent instantiation of this class. 158 private EncryptedExtensionsConsumer() { 159 // blank 160 } 161 162 @Override 163 public void consume(ConnectionContext context, 164 ByteBuffer message) throws IOException { 165 // The consuming happens in client side only. 166 ClientHandshakeContext chc = (ClientHandshakeContext)context; 167 168 // clean up this consumer 169 chc.handshakeConsumers.remove(SSLHandshake.ENCRYPTED_EXTENSIONS.id); 170 171 EncryptedExtensionsMessage eem = 172 new EncryptedExtensionsMessage(chc, message); 173 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 174 SSLLogger.fine( 175 "Consuming EncryptedExtensions handshake message", eem); 176 } 177 178 // 179 // validate 180 // 181 SSLExtension[] extTypes = chc.sslConfig.getEnabledExtensions( 182 SSLHandshake.ENCRYPTED_EXTENSIONS); 183 eem.extensions.consumeOnLoad(chc, extTypes); 184 185 // 186 // update 187 // 188 // TODO: all extensions should be considered. 189 eem.extensions.consumeOnTrade(chc, extTypes); 190 191 // 192 // produce 193 // 194 // Need no new handshake message producers here. 195 } 196 } 197 }