--- old/src/java.base/share/classes/sun/security/ssl/Record.java 2018-05-11 15:05:37.948218600 -0700 +++ new/src/java.base/share/classes/sun/security/ssl/Record.java 2018-05-11 15:05:37.407674400 -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); - - /** - * Return a description for the given content type. - */ - 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 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); + } + + 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 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."); + } } }