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.util.List; 31 import sun.security.ssl.SSLExtension.ExtensionConsumer; 32 import sun.security.ssl.SSLHandshake.HandshakeMessage; 33 import sun.security.ssl.SignatureAlgorithmsExtension.SignatureSchemesSpec; 34 35 /** 36 * Pack of the "signature_algorithms_cert" extensions. 37 */ 38 final class CertSignAlgsExtension { 39 static final HandshakeProducer chNetworkProducer = 40 new CHCertSignatureSchemesProducer(); 41 static final ExtensionConsumer chOnLoadConcumer = 42 new CHCertSignatureSchemesConsumer(); 43 static final HandshakeConsumer chOnTradeConsumer = 44 new CHCertSignatureSchemesUpdate(); 45 46 static final HandshakeProducer crNetworkProducer = 47 new CRCertSignatureSchemesProducer(); 48 static final ExtensionConsumer crOnLoadConcumer = 49 new CRCertSignatureSchemesConsumer(); 50 static final HandshakeConsumer crOnTradeConsumer = 51 new CRCertSignatureSchemesUpdate(); 52 53 static final SSLStringize ssStringize = 54 new CertSignatureSchemesStringize(); 55 56 private static final 57 class CertSignatureSchemesStringize implements SSLStringize { 58 @Override 59 public String toString(ByteBuffer buffer) { 60 try { 61 return (new SignatureSchemesSpec(buffer)).toString(); 62 } catch (IOException ioe) { 63 // For debug logging only, so please swallow exceptions. 64 return ioe.getMessage(); 65 } 66 } 67 } 68 69 /** 70 * Network data producer of a "signature_algorithms_cert" extension in 71 * the ClientHello handshake message. 72 */ 73 private static final 74 class CHCertSignatureSchemesProducer implements HandshakeProducer { 75 // Prevent instantiation of this class. 76 private CHCertSignatureSchemesProducer() { 77 // blank 78 } 79 80 @Override 81 public byte[] produce(ConnectionContext context, 82 HandshakeMessage message) throws IOException { 83 // The producing happens in client side only. 84 ClientHandshakeContext chc = (ClientHandshakeContext)context; 85 86 // Is it a supported and enabled extension? 87 if (!chc.sslConfig.isAvailable( 88 SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT)) { 89 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 90 SSLLogger.fine( 91 "Ignore unavailable " + 92 "signature_algorithms_cert extension"); 93 } 94 95 return null; // ignore the extension 96 } 97 98 // Produce the extension. 99 if (chc.localSupportedSignAlgs == null) { 100 chc.localSupportedSignAlgs = 101 SignatureScheme.getSupportedAlgorithms( 102 chc.algorithmConstraints, chc.activeProtocols); 103 } 104 105 int vectorLen = SignatureScheme.sizeInRecord() * 106 chc.localSupportedSignAlgs.size(); 107 byte[] extData = new byte[vectorLen + 2]; 108 ByteBuffer m = ByteBuffer.wrap(extData); 109 Record.putInt16(m, vectorLen); 110 for (SignatureScheme ss : chc.localSupportedSignAlgs) { 111 Record.putInt16(m, ss.id); 112 } 113 114 // Update the context. 115 chc.handshakeExtensions.put( 116 SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT, 117 new SignatureSchemesSpec(chc.localSupportedSignAlgs)); 118 119 return extData; 120 } 121 } 122 123 /** 124 * Network data consumer of a "signature_algorithms_cert" extension in 125 * the ClientHello handshake message. 126 */ 127 private static final 128 class CHCertSignatureSchemesConsumer implements ExtensionConsumer { 129 // Prevent instantiation of this class. 130 private CHCertSignatureSchemesConsumer() { 131 // blank 132 } 133 134 @Override 135 public void consume(ConnectionContext context, 136 HandshakeMessage message, ByteBuffer buffer) throws IOException { 137 // The comsuming happens in server side only. 138 ServerHandshakeContext shc = (ServerHandshakeContext)context; 139 140 // Is it a supported and enabled extension? 141 if (!shc.sslConfig.isAvailable( 142 SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT)) { 143 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 144 SSLLogger.fine( 145 "Ignore unavailable " + 146 "signature_algorithms_cert extension"); 147 } 148 return; // ignore the extension 149 } 150 151 // Parse the extension. 152 SignatureSchemesSpec spec; 153 try { 154 spec = new SignatureSchemesSpec(buffer); 155 } catch (IOException ioe) { 156 shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe); 157 return; // fatal() always throws, make the compiler happy. 158 } 159 160 // Update the context. 161 shc.handshakeExtensions.put( 162 SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT, spec); 163 164 // No impact on session resumption. 165 } 166 } 167 168 /** 169 * After session creation consuming of a "signature_algorithms_cert" 170 * extension in the ClientHello handshake message. 171 */ 172 private static final class CHCertSignatureSchemesUpdate 173 implements HandshakeConsumer { 174 // Prevent instantiation of this class. 175 private CHCertSignatureSchemesUpdate() { 176 // blank 177 } 178 179 @Override 180 public void consume(ConnectionContext context, 181 HandshakeMessage message) throws IOException { 182 // The comsuming happens in server side only. 183 ServerHandshakeContext shc = (ServerHandshakeContext)context; 184 185 SignatureSchemesSpec spec = (SignatureSchemesSpec) 186 shc.handshakeExtensions.get( 187 SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT); 188 if (spec == null) { 189 // Ignore, no signature_algorithms_cert extension requested. 190 return; 191 } 192 193 // update the context 194 List<SignatureScheme> shemes = 195 SignatureScheme.getSupportedAlgorithms( 196 shc.algorithmConstraints, shc.negotiatedProtocol, 197 spec.signatureSchemes); 198 shc.peerRequestedCertSignSchemes = shemes; 199 200 if (!shc.isResumption && shc.negotiatedProtocol.useTLS13PlusSpec()) { 201 if (shc.sslConfig.clientAuthType != 202 ClientAuthType.CLIENT_AUTH_NONE) { 203 shc.handshakeProducers.putIfAbsent( 204 SSLHandshake.CERTIFICATE_REQUEST.id, 205 SSLHandshake.CERTIFICATE_REQUEST); 206 } 207 shc.handshakeProducers.put(SSLHandshake.CERTIFICATE.id, 208 SSLHandshake.CERTIFICATE); 209 shc.handshakeProducers.putIfAbsent( 210 SSLHandshake.CERTIFICATE_VERIFY.id, 211 SSLHandshake.CERTIFICATE_VERIFY); 212 } 213 } 214 } 215 216 /** 217 * Network data producer of a "signature_algorithms_cert" extension in 218 * the CertificateRequest handshake message. 219 */ 220 private static final 221 class CRCertSignatureSchemesProducer implements HandshakeProducer { 222 // Prevent instantiation of this class. 223 private CRCertSignatureSchemesProducer() { 224 // blank 225 } 226 227 @Override 228 public byte[] produce(ConnectionContext context, 229 HandshakeMessage message) throws IOException { 230 // The producing happens in server side only. 231 ServerHandshakeContext shc = (ServerHandshakeContext)context; 232 233 // Is it a supported and enabled extension? 234 if (!shc.sslConfig.isAvailable( 235 SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT)) { 236 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 237 SSLLogger.fine( 238 "Ignore unavailable " + 239 "signature_algorithms_cert extension"); 240 } 241 return null; // ignore the extension 242 } 243 244 // Produce the extension. 245 if (shc.localSupportedSignAlgs == null) { 246 shc.localSupportedSignAlgs = 247 SignatureScheme.getSupportedAlgorithms( 248 shc.algorithmConstraints, shc.activeProtocols); 249 } 250 251 int vectorLen = SignatureScheme.sizeInRecord() * 252 shc.localSupportedSignAlgs.size(); 253 byte[] extData = new byte[vectorLen + 2]; 254 ByteBuffer m = ByteBuffer.wrap(extData); 255 Record.putInt16(m, vectorLen); 256 for (SignatureScheme ss : shc.localSupportedSignAlgs) { 257 Record.putInt16(m, ss.id); 258 } 259 260 // Update the context. 261 shc.handshakeExtensions.put( 262 SSLExtension.CR_SIGNATURE_ALGORITHMS_CERT, 263 new SignatureSchemesSpec(shc.localSupportedSignAlgs)); 264 265 return extData; 266 } 267 } 268 269 /** 270 * Network data consumer of a "signature_algorithms_cert" extension in 271 * the CertificateRequest handshake message. 272 */ 273 private static final 274 class CRCertSignatureSchemesConsumer implements ExtensionConsumer { 275 // Prevent instantiation of this class. 276 private CRCertSignatureSchemesConsumer() { 277 // blank 278 } 279 @Override 280 public void consume(ConnectionContext context, 281 HandshakeMessage message, ByteBuffer buffer) throws IOException { 282 // The comsuming happens in client side only. 283 ClientHandshakeContext chc = (ClientHandshakeContext)context; 284 285 // Is it a supported and enabled extension? 286 if (!chc.sslConfig.isAvailable( 287 SSLExtension.CH_SIGNATURE_ALGORITHMS_CERT)) { 288 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 289 SSLLogger.fine( 290 "Ignore unavailable " + 291 "signature_algorithms_cert extension"); 292 } 293 return; // ignore the extension 294 } 295 296 // Parse the extension. 297 SignatureSchemesSpec spec; 298 try { 299 spec = new SignatureSchemesSpec(buffer); 300 } catch (IOException ioe) { 301 chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe); 302 return; // fatal() always throws, make the compiler happy. 303 } 304 305 // Update the context. 306 chc.handshakeExtensions.put( 307 SSLExtension.CR_SIGNATURE_ALGORITHMS_CERT, spec); 308 309 // No impact on session resumption. 310 } 311 } 312 313 /** 314 * After session creation consuming of a "signature_algorithms_cert" 315 * extension in the CertificateRequest handshake message. 316 */ 317 private static final class CRCertSignatureSchemesUpdate 318 implements HandshakeConsumer { 319 // Prevent instantiation of this class. 320 private CRCertSignatureSchemesUpdate() { 321 // blank 322 } 323 324 @Override 325 public void consume(ConnectionContext context, 326 HandshakeMessage message) throws IOException { 327 // The comsuming happens in client side only. 328 ClientHandshakeContext chc = (ClientHandshakeContext)context; 329 330 SignatureSchemesSpec spec = (SignatureSchemesSpec) 331 chc.handshakeExtensions.get( 332 SSLExtension.CR_SIGNATURE_ALGORITHMS_CERT); 333 if (spec == null) { 334 // Ignore, no "signature_algorithms_cert" extension requested. 335 return; 336 } 337 338 // update the context 339 List<SignatureScheme> shemes = 340 SignatureScheme.getSupportedAlgorithms( 341 chc.algorithmConstraints, chc.negotiatedProtocol, 342 spec.signatureSchemes); 343 chc.peerRequestedCertSignSchemes = shemes; 344 } 345 } 346 }