--- a/src/java.base/share/classes/sun/security/ssl/Record.java Fri May 11 14:55:56 2018 -0700
+++ b/src/java.base/share/classes/sun/security/ssl/Record.java Fri May 11 15:53:12 2018 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -25,27 +25,19 @@
package sun.security.ssl;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import javax.net.ssl.SSLException;
+
/**
- * SSL/TLS/DTLS records, as pulled off (and put onto) a TCP stream. This is
- * the base interface, which defines common information and interfaces
+ * SSL/(D)TLS record.
+ *
+ * This is the base interface, which defines common information and interfaces
* used by both Input and Output records.
*
* @author David Brownell
*/
interface Record {
-
- /*
- * There are four record types, which are part of the interface
- * to this level (along with the maximum record size).
- *
- * enum { change_cipher_spec(20), alert(21), handshake(22),
- * application_data(23), (255) } ContentType;
- */
- static final byte ct_change_cipher_spec = 20;
- static final byte ct_alert = 21;
- static final byte ct_handshake = 22;
- static final byte ct_application_data = 23;
-
static final int maxMacSize = 48; // the max supported MAC or
// AEAD tag size
static final int maxDataSize = 16384; // 2^14 bytes of data
@@ -59,35 +51,146 @@
* System property to enable/disable CBC protection in SSL3/TLS1.
*/
static final boolean enableCBCProtection =
- Debug.getBooleanProperty("jsse.enableCBCProtection", true);
+ Utilities.getBooleanProperty("jsse.enableCBCProtection", true);
/*
* The overflow values of integers of 8, 16 and 24 bits.
*/
- static final int OVERFLOW_OF_INT08 = (1 << 8);
- static final int OVERFLOW_OF_INT16 = (1 << 16);
- static final int OVERFLOW_OF_INT24 = (1 << 24);
+ static final int OVERFLOW_OF_INT08 = (0x01 << 8);
+ static final int OVERFLOW_OF_INT16 = (0x01 << 16);
+ static final int OVERFLOW_OF_INT24 = (0x01 << 24);
+
+ /*
+ * Read 8, 16, 24, and 32 bit integer data types, encoded
+ * in standard big-endian form.
+ */
+ static int getInt8(ByteBuffer m) throws IOException {
+ Record.verifyLength(m, 1);
+ return (m.get() & 0xFF);
+ }
- /**
- * Return a description for the given content type.
+ static int getInt16(ByteBuffer m) throws IOException {
+ Record.verifyLength(m, 2);
+ return ((m.get() & 0xFF) << 8) |
+ (m.get() & 0xFF);
+ }
+
+ static int getInt24(ByteBuffer m) throws IOException {
+ Record.verifyLength(m, 3);
+ return ((m.get() & 0xFF) << 16) |
+ ((m.get() & 0xFF) << 8) |
+ (m.get() & 0xFF);
+ }
+
+ static int getInt32(ByteBuffer m) throws IOException {
+ Record.verifyLength(m, 4);
+ return ((m.get() & 0xFF) << 24) |
+ ((m.get() & 0xFF) << 16) |
+ ((m.get() & 0xFF) << 8) |
+ (m.get() & 0xFF);
+ }
+
+ /*
+ * Read byte vectors with 8, 16, and 24 bit length encodings.
*/
- static String contentName(byte contentType) {
- switch (contentType) {
- case ct_change_cipher_spec:
- return "Change Cipher Spec";
- case ct_alert:
- return "Alert";
- case ct_handshake:
- return "Handshake";
- case ct_application_data:
- return "Application Data";
- default:
- return "contentType = " + contentType;
+ static byte[] getBytes8(ByteBuffer m) throws IOException {
+ int len = Record.getInt8(m);
+ Record.verifyLength(m, len);
+ byte[] b = new byte[len];
+
+ m.get(b);
+ return b;
+ }
+
+ static byte[] getBytes16(ByteBuffer m) throws IOException {
+ int len = Record.getInt16(m);
+ Record.verifyLength(m, len);
+ byte[] b = new byte[len];
+
+ m.get(b);
+ return b;
+ }
+
+ static byte[] getBytes24(ByteBuffer m) throws IOException {
+ int len = Record.getInt24(m);
+ Record.verifyLength(m, len);
+ byte[] b = new byte[len];
+
+ m.get(b);
+ return b;
+ }
+
+ /*
+ * Write 8, 16, 24, and 32 bit integer data types, encoded
+ * in standard big-endian form.
+ */
+ static void putInt8(ByteBuffer m, int i) throws IOException {
+ Record.verifyLength(m, 1);
+ m.put((byte)(i & 0xFF));
+ }
+
+ static void putInt16(ByteBuffer m, int i) throws IOException {
+ Record.verifyLength(m, 2);
+ m.put((byte)((i >> 8) & 0xFF));
+ m.put((byte)(i & 0xFF));
+ }
+
+ static void putInt24(ByteBuffer m, int i) throws IOException {
+ Record.verifyLength(m, 3);
+ m.put((byte)((i >> 16) & 0xFF));
+ m.put((byte)((i >> 8) & 0xFF));
+ m.put((byte)(i & 0xFF));
+ }
+
+ static void putInt32(ByteBuffer m, int i) throws IOException {
+ m.put((byte)((i >> 24) & 0xFF));
+ m.put((byte)((i >> 16) & 0xFF));
+ m.put((byte)((i >> 8) & 0xFF));
+ m.put((byte)(i & 0xFF));
+ }
+
+ /*
+ * Write byte vectors with 8, 16, and 24 bit length encodings.
+ */
+ static void putBytes8(ByteBuffer m, byte[] s) throws IOException {
+ if (s == null || s.length == 0) {
+ Record.verifyLength(m, 1);
+ putInt8(m, 0);
+ } else {
+ Record.verifyLength(m, 1 + s.length);
+ putInt8(m, s.length);
+ m.put(s);
}
}
- static boolean isValidContentType(byte contentType) {
- return (contentType == 20) || (contentType == 21) ||
- (contentType == 22) || (contentType == 23);
+ static void putBytes16(ByteBuffer m, byte[] s) throws IOException {
+ if (s == null || s.length == 0) {
+ Record.verifyLength(m, 2);
+ putInt16(m, 0);
+ } else {
+ Record.verifyLength(m, 2 + s.length);
+ putInt16(m, s.length);
+ m.put(s);
+ }
+ }
+
+ static void putBytes24(ByteBuffer m, byte[] s) throws IOException {
+ if (s == null || s.length == 0) {
+ Record.verifyLength(m, 3);
+ putInt24(m, 0);
+ } else {
+ Record.verifyLength(m, 3 + s.length);
+ putInt24(m, s.length);
+ m.put(s);
+ }
+ }
+
+ // Verify that the buffer has sufficient remaining.
+ static void verifyLength(
+ ByteBuffer m, int len) throws SSLException {
+ if (len > m.remaining()) {
+ throw new SSLException("Insufficient space in the buffer, " +
+ "may be cause by unexpected end of handshake data.");
+ }
}
}