< 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 >