Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/ssl/ECPointFormatsExtension.java
38830 views
/*1* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.ssl;2627import java.io.IOException;28import java.nio.ByteBuffer;29import java.text.MessageFormat;30import java.util.Locale;31import javax.net.ssl.SSLProtocolException;32import static sun.security.ssl.SSLExtension.CH_EC_POINT_FORMATS;33import sun.security.ssl.SSLExtension.ExtensionConsumer;34import sun.security.ssl.SSLExtension.SSLExtensionSpec;35import sun.security.ssl.SSLHandshake.HandshakeMessage;36import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;3738/**39* Pack of the "ec_point_formats" extensions [RFC 4492].40*/41final class ECPointFormatsExtension {42static final HandshakeProducer chNetworkProducer =43new CHECPointFormatsProducer();44static final ExtensionConsumer chOnLoadConsumer =45new CHECPointFormatsConsumer();4647static final ExtensionConsumer shOnLoadConsumer =48new SHECPointFormatsConsumer();4950static final SSLStringizer epfStringizer =51new ECPointFormatsStringizer();5253/**54* The "ec_point_formats" extension.55*/56static class ECPointFormatsSpec implements SSLExtensionSpec {57static final ECPointFormatsSpec DEFAULT =58new ECPointFormatsSpec(new byte[] {ECPointFormat.UNCOMPRESSED.id});5960final byte[] formats;6162ECPointFormatsSpec(byte[] formats) {63this.formats = formats;64}6566private ECPointFormatsSpec(ByteBuffer m) throws IOException {67if (!m.hasRemaining()) {68throw new SSLProtocolException(69"Invalid ec_point_formats extension: " +70"insufficient data");71}7273this.formats = Record.getBytes8(m);74}7576private boolean hasUncompressedFormat() {77for (byte format : formats) {78if (format == ECPointFormat.UNCOMPRESSED.id) {79return true;80}81}8283return false;84}8586@Override87public String toString() {88MessageFormat messageFormat = new MessageFormat(89"\"formats\": '['{0}']'", Locale.ENGLISH);90if (formats == null || formats.length == 0) {91Object[] messageFields = {92"<no EC point format specified>"93};94return messageFormat.format(messageFields);95} else {96StringBuilder builder = new StringBuilder(512);97boolean isFirst = true;98for (byte pf : formats) {99if (isFirst) {100isFirst = false;101} else {102builder.append(", ");103}104105builder.append(ECPointFormat.nameOf(pf));106}107108Object[] messageFields = {109builder.toString()110};111112return messageFormat.format(messageFields);113}114}115}116117private static final class ECPointFormatsStringizer implements SSLStringizer {118@Override119public String toString(ByteBuffer buffer) {120try {121return (new ECPointFormatsSpec(buffer)).toString();122} catch (IOException ioe) {123// For debug logging only, so please swallow exceptions.124return ioe.getMessage();125}126}127}128129private static enum ECPointFormat {130UNCOMPRESSED ((byte)0, "uncompressed"),131ANSIX962_COMPRESSED_PRIME ((byte)1, "ansiX962_compressed_prime"),132FMT_ANSIX962_COMPRESSED_CHAR2 ((byte)2, "ansiX962_compressed_char2");133134final byte id;135final String name;136137private ECPointFormat(byte id, String name) {138this.id = id;139this.name = name;140}141142static String nameOf(int id) {143for (ECPointFormat pf: ECPointFormat.values()) {144if (pf.id == id) {145return pf.name;146}147}148return "UNDEFINED-EC-POINT-FORMAT(" + id + ")";149}150}151152/**153* Network data producer of a "ec_point_formats" extension in154* the ClientHello handshake message.155*/156private static final157class CHECPointFormatsProducer implements HandshakeProducer {158// Prevent instantiation of this class.159private CHECPointFormatsProducer() {160// blank161}162163@Override164public byte[] produce(ConnectionContext context,165HandshakeMessage message) throws IOException {166// The producing happens in client side only.167ClientHandshakeContext chc = (ClientHandshakeContext)context;168169// Is it a supported and enabled extension?170if (!chc.sslConfig.isAvailable(CH_EC_POINT_FORMATS)) {171if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {172SSLLogger.fine(173"Ignore unavailable ec_point_formats extension");174}175return null;176}177178// Produce the extension.179//180// produce the extension only if EC cipher suite is activated.181if (NamedGroupType.NAMED_GROUP_ECDHE.isSupported(182chc.activeCipherSuites)) {183// We are using uncompressed ECPointFormat only at present.184byte[] extData = new byte[] {0x01, 0x00};185186// Update the context.187chc.handshakeExtensions.put(188CH_EC_POINT_FORMATS, ECPointFormatsSpec.DEFAULT);189190return extData;191}192193if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {194SSLLogger.fine(195"Need no ec_point_formats extension");196}197return null;198}199}200201/**202* Network data consumer of a "ec_point_formats" extension in203* the ClientHello handshake message.204*/205private static final206class CHECPointFormatsConsumer implements ExtensionConsumer {207// Prevent instantiation of this class.208private CHECPointFormatsConsumer() {209// blank210}211212@Override213public void consume(ConnectionContext context,214HandshakeMessage message, ByteBuffer buffer) throws IOException {215216// The consuming happens in server side only.217ServerHandshakeContext shc = (ServerHandshakeContext)context;218219// Is it a supported and enabled extension?220if (!shc.sslConfig.isAvailable(CH_EC_POINT_FORMATS)) {221if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {222SSLLogger.fine(223"Ignore unavailable ec_point_formats extension");224}225return; // ignore the extension226}227228// Parse the extension.229ECPointFormatsSpec spec;230try {231spec = new ECPointFormatsSpec(buffer);232} catch (IOException ioe) {233throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);234}235236// per RFC 4492, uncompressed points must always be supported.237if (!spec.hasUncompressedFormat()) {238throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,239"Invalid ec_point_formats extension data: " +240"peer does not support uncompressed points");241}242243// Update the context.244shc.handshakeExtensions.put(CH_EC_POINT_FORMATS, spec);245246// No impact on session resumption, as only uncompressed points247// are supported at present.248}249}250251/**252* Network data consumer of a "ec_point_formats" extension in253* the ServerHello handshake message.254*/255private static final256class SHECPointFormatsConsumer implements ExtensionConsumer {257// Prevent instantiation of this class.258private SHECPointFormatsConsumer() {259// blank260}261262@Override263public void consume(ConnectionContext context,264HandshakeMessage message, ByteBuffer buffer) throws IOException {265266// The consuming happens in client side only.267ClientHandshakeContext chc = (ClientHandshakeContext)context;268269// In response to "ec_point_formats" extension request only270ECPointFormatsSpec requestedSpec = (ECPointFormatsSpec)271chc.handshakeExtensions.get(CH_EC_POINT_FORMATS);272if (requestedSpec == null) {273throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,274"Unexpected ec_point_formats extension in ServerHello");275}276277// Parse the extension.278ECPointFormatsSpec spec;279try {280spec = new ECPointFormatsSpec(buffer);281} catch (IOException ioe) {282throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);283}284285// per RFC 4492, uncompressed points must always be supported.286if (!spec.hasUncompressedFormat()) {287throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,288"Invalid ec_point_formats extension data: " +289"peer does not support uncompressed points");290}291292// Update the context.293chc.handshakeExtensions.put(CH_EC_POINT_FORMATS, spec);294295// No impact on session resumption, as only uncompressed points296// are supported at present.297}298}299}300301302