< prev index next >

src/java.base/share/classes/sun/security/ssl/ECPointFormatsExtension.java

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 24,103 **** */ package sun.security.ssl; import java.io.IOException; ! import java.util.ArrayList; ! import java.util.List; ! import javax.net.ssl.SSLProtocolException; ! final class EllipticPointFormatsExtension extends HelloExtension { ! static final int FMT_UNCOMPRESSED = 0; ! static final int FMT_ANSIX962_COMPRESSED_PRIME = 1; ! static final int FMT_ANSIX962_COMPRESSED_CHAR2 = 2; ! static final HelloExtension DEFAULT = ! new EllipticPointFormatsExtension(new byte[] {FMT_UNCOMPRESSED}); ! private final byte[] formats; ! private EllipticPointFormatsExtension(byte[] formats) { ! super(ExtensionType.EXT_EC_POINT_FORMATS); this.formats = formats; } ! EllipticPointFormatsExtension(HandshakeInStream s, int len) ! throws IOException { ! super(ExtensionType.EXT_EC_POINT_FORMATS); ! formats = s.getBytes8(); ! // RFC 4492 says uncompressed points must always be supported. ! // Check just to make sure. ! boolean uncompressed = false; ! for (int format : formats) { ! if (format == FMT_UNCOMPRESSED) { ! uncompressed = true; ! break; ! } ! } ! if (uncompressed == false) { ! throw new SSLProtocolException ! ("Peer does not support uncompressed points"); } } @Override ! int length() { ! return 5 + formats.length; } @Override ! void send(HandshakeOutStream s) throws IOException { ! s.putInt16(type.id); ! s.putInt16(formats.length + 1); ! s.putBytes8(formats); ! } ! ! private static String toString(byte format) { ! int f = format & 0xff; ! switch (f) { ! case FMT_UNCOMPRESSED: ! return "uncompressed"; ! case FMT_ANSIX962_COMPRESSED_PRIME: ! return "ansiX962_compressed_prime"; ! case FMT_ANSIX962_COMPRESSED_CHAR2: ! return "ansiX962_compressed_char2"; ! default: ! return "unknown-" + f; } } @Override ! public String toString() { ! List<String> list = new ArrayList<String>(); ! for (byte format : formats) { ! list.add(toString(format)); } - return "Extension " + type + ", formats: " + list; } } --- 24,302 ---- */ package sun.security.ssl; import java.io.IOException; ! import java.nio.ByteBuffer; ! import java.text.MessageFormat; ! import java.util.Locale; import javax.net.ssl.SSLProtocolException; + import static sun.security.ssl.SSLExtension.CH_EC_POINT_FORMATS; + import sun.security.ssl.SSLExtension.ExtensionConsumer; + import sun.security.ssl.SSLExtension.SSLExtensionSpec; + import sun.security.ssl.SSLHandshake.HandshakeMessage; + import sun.security.ssl.SupportedGroupsExtension.NamedGroupType; ! /** ! * Pack of the "ec_point_formats" extensions [RFC 4492]. ! */ ! final class ECPointFormatsExtension { ! static final HandshakeProducer chNetworkProducer = ! new CHECPointFormatsProducer(); ! static final ExtensionConsumer chOnLoadConcumer = ! new CHECPointFormatsConsumer(); ! static final ExtensionConsumer shOnLoadConcumer = ! new SHECPointFormatsConsumer(); ! static final SSLStringize epfStringize = ! new ECPointFormatsStringize(); ! /** ! * The "ec_point_formats" extension. ! */ ! static class ECPointFormatsSpec implements SSLExtensionSpec { ! static final ECPointFormatsSpec DEFAULT = ! new ECPointFormatsSpec(new byte[] {ECPointFormat.UNCOMPRESSED.id}); ! final byte[] formats; ! ! ECPointFormatsSpec(byte[] formats) { this.formats = formats; } ! private ECPointFormatsSpec(ByteBuffer m) throws IOException { ! if (!m.hasRemaining()) { ! throw new SSLProtocolException( ! "Invalid ec_point_formats extension: " + ! "insufficient data"); ! } ! ! this.formats = Record.getBytes8(m); ! } ! ! private boolean hasUncompressedFormat() { ! for (byte format : formats) { ! if (format == ECPointFormat.UNCOMPRESSED.id) { ! return true; } } + return false; + } + @Override ! public String toString() { ! MessageFormat messageFormat = new MessageFormat( ! "\"formats\": '['{0}']'", Locale.ENGLISH); ! if (formats == null || formats.length == 0) { ! Object[] messageFields = { ! "<no EC point format specified>" ! }; ! return messageFormat.format(messageFields); ! } else { ! StringBuilder builder = new StringBuilder(512); ! boolean isFirst = true; ! for (byte pf : formats) { ! if (isFirst) { ! isFirst = false; ! } else { ! builder.append(", "); ! } ! ! builder.append(ECPointFormat.nameOf(pf)); ! } ! ! Object[] messageFields = { ! builder.toString() ! }; ! ! return messageFormat.format(messageFields); ! } ! } } + private static final class ECPointFormatsStringize implements SSLStringize { @Override ! public String toString(ByteBuffer buffer) { ! try { ! return (new ECPointFormatsSpec(buffer)).toString(); ! } catch (IOException ioe) { ! // For debug logging only, so please swallow exceptions. ! return ioe.getMessage(); ! } ! } ! } ! ! private static enum ECPointFormat { ! UNCOMPRESSED ((byte)0, "uncompressed"), ! ANSIX962_COMPRESSED_PRIME ((byte)1, "ansiX962_compressed_prime"), ! FMT_ANSIX962_COMPRESSED_CHAR2 ((byte)2, "ansiX962_compressed_char2"); ! ! final byte id; ! final String name; ! ! private ECPointFormat(byte id, String name) { ! this.id = id; ! this.name = name; ! } ! ! static String nameOf(int id) { ! for (ECPointFormat pf: ECPointFormat.values()) { ! if (pf.id == id) { ! return pf.name; ! } ! } ! return "UNDEFINED-EC-POINT-FORMAT(" + id + ")"; } } + /** + * Network data producer of a "ec_point_formats" extension in + * the ClientHello handshake message. + */ + private static final + class CHECPointFormatsProducer implements HandshakeProducer { + // Prevent instantiation of this class. + private CHECPointFormatsProducer() { + // blank + } + @Override ! public byte[] produce(ConnectionContext context, ! HandshakeMessage message) throws IOException { ! // The producing happens in client side only. ! ClientHandshakeContext chc = (ClientHandshakeContext)context; ! ! // Is it a supported and enabled extension? ! if (!chc.sslConfig.isAvailable(CH_EC_POINT_FORMATS)) { ! if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { ! SSLLogger.fine( ! "Ignore unavailable ec_point_formats extension"); ! } ! return null; ! } ! ! // Produce the extension. ! // ! // produce the extension only if EC cipher suite is activated. ! if (NamedGroupType.NAMED_GROUP_ECDHE.isSupported( ! chc.activeCipherSuites)) { ! // We are using uncompressed ECPointFormat only at present. ! byte[] extData = new byte[] {0x01, 0x00}; ! ! // Update the context. ! chc.handshakeExtensions.put( ! CH_EC_POINT_FORMATS, ECPointFormatsSpec.DEFAULT); ! ! return extData; ! } ! ! if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { ! SSLLogger.fine( ! "Need no ec_point_formats extension"); ! } ! return null; ! } ! } ! ! /** ! * Network data consumer of a "ec_point_formats" extension in ! * the ClientHello handshake message. ! */ ! private static final ! class CHECPointFormatsConsumer implements ExtensionConsumer { ! // Prevent instantiation of this class. ! private CHECPointFormatsConsumer() { ! // blank ! } ! ! @Override ! public void consume(ConnectionContext context, ! HandshakeMessage message, ByteBuffer buffer) throws IOException { ! ! // The comsuming happens in server side only. ! ServerHandshakeContext shc = (ServerHandshakeContext)context; ! ! // Is it a supported and enabled extension? ! if (!shc.sslConfig.isAvailable(CH_EC_POINT_FORMATS)) { ! if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { ! SSLLogger.fine( ! "Ignore unavailable ec_point_formats extension"); ! } ! return; // ignore the extension ! } ! ! // Parse the extension. ! ECPointFormatsSpec spec; ! try { ! spec = new ECPointFormatsSpec(buffer); ! } catch (IOException ioe) { ! shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe); ! return; // fatal() always throws, make the compiler happy. ! } ! ! // per RFC 4492, uncompressed points must always be supported. ! if (!spec.hasUncompressedFormat()) { ! shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ! "Invalid ec_point_formats extension data: " + ! "peer does not support uncompressed points"); ! } ! ! // Update the context. ! shc.handshakeExtensions.put(CH_EC_POINT_FORMATS, spec); ! ! // No impact on session resumption, as only uncompressed points ! // are supported at present. ! } ! } ! ! /** ! * Network data consumer of a "ec_point_formats" extension in ! * the ServerHello handshake message. ! */ ! private static final ! class SHECPointFormatsConsumer implements ExtensionConsumer { ! // Prevent instantiation of this class. ! private SHECPointFormatsConsumer() { ! // blank ! } ! ! @Override ! public void consume(ConnectionContext context, ! HandshakeMessage message, ByteBuffer buffer) throws IOException { ! ! // The comsuming happens in client side only. ! ClientHandshakeContext chc = (ClientHandshakeContext)context; ! ! // In response to "ec_point_formats" extension request only ! ECPointFormatsSpec requestedSpec = (ECPointFormatsSpec) ! chc.handshakeExtensions.get(CH_EC_POINT_FORMATS); ! if (requestedSpec == null) { ! chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ! "Unexpected ec_point_formats extension in ServerHello"); ! } ! ! // Parse the extension. ! ECPointFormatsSpec spec; ! try { ! spec = new ECPointFormatsSpec(buffer); ! } catch (IOException ioe) { ! chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe); ! return; // fatal() always throws, make the compiler happy. ! } ! ! // per RFC 4492, uncompressed points must always be supported. ! if (!spec.hasUncompressedFormat()) { ! chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ! "Invalid ec_point_formats extension data: " + ! "peer does not support uncompressed points"); ! } ! ! // Update the context. ! chc.handshakeExtensions.put(CH_EC_POINT_FORMATS, spec); ! ! // No impact on session resumption, as only uncompressed points ! // are supported at present. } } }
< prev index next >