src/java.base/share/classes/sun/security/ssl/Record.java
branchJDK-8145252-TLS13-branch
changeset 56542 56aaa6cb3693
parent 47216 71c04702a3d5
child 56694 aa54a1f8e426
--- 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.");
+        }
     }
 }