| package org.bouncycastle.crypto.tls; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.util.Hashtable; |
| |
| import org.bouncycastle.util.Integers; |
| |
| public class TlsExtensionsUtils |
| { |
| public static final Integer EXT_encrypt_then_mac = Integers.valueOf(ExtensionType.encrypt_then_mac); |
| public static final Integer EXT_extended_master_secret = Integers.valueOf(ExtensionType.extended_master_secret); |
| public static final Integer EXT_heartbeat = Integers.valueOf(ExtensionType.heartbeat); |
| public static final Integer EXT_max_fragment_length = Integers.valueOf(ExtensionType.max_fragment_length); |
| public static final Integer EXT_padding = Integers.valueOf(ExtensionType.padding); |
| public static final Integer EXT_server_name = Integers.valueOf(ExtensionType.server_name); |
| public static final Integer EXT_status_request = Integers.valueOf(ExtensionType.status_request); |
| public static final Integer EXT_truncated_hmac = Integers.valueOf(ExtensionType.truncated_hmac); |
| |
| public static Hashtable ensureExtensionsInitialised(Hashtable extensions) |
| { |
| return extensions == null ? new Hashtable() : extensions; |
| } |
| |
| public static void addEncryptThenMACExtension(Hashtable extensions) |
| { |
| extensions.put(EXT_encrypt_then_mac, createEncryptThenMACExtension()); |
| } |
| |
| public static void addExtendedMasterSecretExtension(Hashtable extensions) |
| { |
| extensions.put(EXT_extended_master_secret, createExtendedMasterSecretExtension()); |
| } |
| |
| public static void addHeartbeatExtension(Hashtable extensions, HeartbeatExtension heartbeatExtension) |
| throws IOException |
| { |
| extensions.put(EXT_heartbeat, createHeartbeatExtension(heartbeatExtension)); |
| } |
| |
| public static void addMaxFragmentLengthExtension(Hashtable extensions, short maxFragmentLength) |
| throws IOException |
| { |
| extensions.put(EXT_max_fragment_length, createMaxFragmentLengthExtension(maxFragmentLength)); |
| } |
| |
| public static void addPaddingExtension(Hashtable extensions, int dataLength) |
| throws IOException |
| { |
| extensions.put(EXT_padding, createPaddingExtension(dataLength)); |
| } |
| |
| public static void addServerNameExtension(Hashtable extensions, ServerNameList serverNameList) |
| throws IOException |
| { |
| extensions.put(EXT_server_name, createServerNameExtension(serverNameList)); |
| } |
| |
| public static void addStatusRequestExtension(Hashtable extensions, CertificateStatusRequest statusRequest) |
| throws IOException |
| { |
| extensions.put(EXT_status_request, createStatusRequestExtension(statusRequest)); |
| } |
| |
| public static void addTruncatedHMacExtension(Hashtable extensions) |
| { |
| extensions.put(EXT_truncated_hmac, createTruncatedHMacExtension()); |
| } |
| |
| public static HeartbeatExtension getHeartbeatExtension(Hashtable extensions) |
| throws IOException |
| { |
| byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_heartbeat); |
| return extensionData == null ? null : readHeartbeatExtension(extensionData); |
| } |
| |
| public static short getMaxFragmentLengthExtension(Hashtable extensions) |
| throws IOException |
| { |
| byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_max_fragment_length); |
| return extensionData == null ? -1 : readMaxFragmentLengthExtension(extensionData); |
| } |
| |
| public static int getPaddingExtension(Hashtable extensions) |
| throws IOException |
| { |
| byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_padding); |
| return extensionData == null ? -1 : readPaddingExtension(extensionData); |
| } |
| |
| public static ServerNameList getServerNameExtension(Hashtable extensions) |
| throws IOException |
| { |
| byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_server_name); |
| return extensionData == null ? null : readServerNameExtension(extensionData); |
| } |
| |
| public static CertificateStatusRequest getStatusRequestExtension(Hashtable extensions) |
| throws IOException |
| { |
| byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_status_request); |
| return extensionData == null ? null : readStatusRequestExtension(extensionData); |
| } |
| |
| public static boolean hasEncryptThenMACExtension(Hashtable extensions) throws IOException |
| { |
| byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_encrypt_then_mac); |
| return extensionData == null ? false : readEncryptThenMACExtension(extensionData); |
| } |
| |
| public static boolean hasExtendedMasterSecretExtension(Hashtable extensions) throws IOException |
| { |
| byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_extended_master_secret); |
| return extensionData == null ? false : readExtendedMasterSecretExtension(extensionData); |
| } |
| |
| public static boolean hasTruncatedHMacExtension(Hashtable extensions) throws IOException |
| { |
| byte[] extensionData = TlsUtils.getExtensionData(extensions, EXT_truncated_hmac); |
| return extensionData == null ? false : readTruncatedHMacExtension(extensionData); |
| } |
| |
| public static byte[] createEmptyExtensionData() |
| { |
| return TlsUtils.EMPTY_BYTES; |
| } |
| |
| public static byte[] createEncryptThenMACExtension() |
| { |
| return createEmptyExtensionData(); |
| } |
| |
| public static byte[] createExtendedMasterSecretExtension() |
| { |
| return createEmptyExtensionData(); |
| } |
| |
| public static byte[] createHeartbeatExtension(HeartbeatExtension heartbeatExtension) |
| throws IOException |
| { |
| if (heartbeatExtension == null) |
| { |
| throw new TlsFatalAlert(AlertDescription.internal_error); |
| } |
| |
| ByteArrayOutputStream buf = new ByteArrayOutputStream(); |
| |
| heartbeatExtension.encode(buf); |
| |
| return buf.toByteArray(); |
| } |
| |
| public static byte[] createMaxFragmentLengthExtension(short maxFragmentLength) |
| throws IOException |
| { |
| TlsUtils.checkUint8(maxFragmentLength); |
| |
| byte[] extensionData = new byte[1]; |
| TlsUtils.writeUint8(maxFragmentLength, extensionData, 0); |
| return extensionData; |
| } |
| |
| public static byte[] createPaddingExtension(int dataLength) |
| throws IOException |
| { |
| TlsUtils.checkUint16(dataLength); |
| return new byte[dataLength]; |
| } |
| |
| public static byte[] createServerNameExtension(ServerNameList serverNameList) |
| throws IOException |
| { |
| if (serverNameList == null) |
| { |
| throw new TlsFatalAlert(AlertDescription.internal_error); |
| } |
| |
| ByteArrayOutputStream buf = new ByteArrayOutputStream(); |
| |
| serverNameList.encode(buf); |
| |
| return buf.toByteArray(); |
| } |
| |
| public static byte[] createStatusRequestExtension(CertificateStatusRequest statusRequest) |
| throws IOException |
| { |
| if (statusRequest == null) |
| { |
| throw new TlsFatalAlert(AlertDescription.internal_error); |
| } |
| |
| ByteArrayOutputStream buf = new ByteArrayOutputStream(); |
| |
| statusRequest.encode(buf); |
| |
| return buf.toByteArray(); |
| } |
| |
| public static byte[] createTruncatedHMacExtension() |
| { |
| return createEmptyExtensionData(); |
| } |
| |
| private static boolean readEmptyExtensionData(byte[] extensionData) throws IOException |
| { |
| if (extensionData == null) |
| { |
| throw new IllegalArgumentException("'extensionData' cannot be null"); |
| } |
| |
| if (extensionData.length != 0) |
| { |
| throw new TlsFatalAlert(AlertDescription.illegal_parameter); |
| } |
| |
| return true; |
| } |
| |
| public static boolean readEncryptThenMACExtension(byte[] extensionData) throws IOException |
| { |
| return readEmptyExtensionData(extensionData); |
| } |
| |
| public static boolean readExtendedMasterSecretExtension(byte[] extensionData) throws IOException |
| { |
| return readEmptyExtensionData(extensionData); |
| } |
| |
| public static HeartbeatExtension readHeartbeatExtension(byte[] extensionData) |
| throws IOException |
| { |
| if (extensionData == null) |
| { |
| throw new IllegalArgumentException("'extensionData' cannot be null"); |
| } |
| |
| ByteArrayInputStream buf = new ByteArrayInputStream(extensionData); |
| |
| HeartbeatExtension heartbeatExtension = HeartbeatExtension.parse(buf); |
| |
| TlsProtocol.assertEmpty(buf); |
| |
| return heartbeatExtension; |
| } |
| |
| public static short readMaxFragmentLengthExtension(byte[] extensionData) |
| throws IOException |
| { |
| if (extensionData == null) |
| { |
| throw new IllegalArgumentException("'extensionData' cannot be null"); |
| } |
| |
| if (extensionData.length != 1) |
| { |
| throw new TlsFatalAlert(AlertDescription.decode_error); |
| } |
| |
| return TlsUtils.readUint8(extensionData, 0); |
| } |
| |
| public static int readPaddingExtension(byte[] extensionData) |
| throws IOException |
| { |
| if (extensionData == null) |
| { |
| throw new IllegalArgumentException("'extensionData' cannot be null"); |
| } |
| for (int i = 0; i < extensionData.length; ++i) |
| { |
| if (extensionData[i] != 0) |
| { |
| throw new TlsFatalAlert(AlertDescription.illegal_parameter); |
| } |
| } |
| return extensionData.length; |
| } |
| |
| public static ServerNameList readServerNameExtension(byte[] extensionData) |
| throws IOException |
| { |
| if (extensionData == null) |
| { |
| throw new IllegalArgumentException("'extensionData' cannot be null"); |
| } |
| |
| ByteArrayInputStream buf = new ByteArrayInputStream(extensionData); |
| |
| ServerNameList serverNameList = ServerNameList.parse(buf); |
| |
| TlsProtocol.assertEmpty(buf); |
| |
| return serverNameList; |
| } |
| |
| public static CertificateStatusRequest readStatusRequestExtension(byte[] extensionData) |
| throws IOException |
| { |
| if (extensionData == null) |
| { |
| throw new IllegalArgumentException("'extensionData' cannot be null"); |
| } |
| |
| ByteArrayInputStream buf = new ByteArrayInputStream(extensionData); |
| |
| CertificateStatusRequest statusRequest = CertificateStatusRequest.parse(buf); |
| |
| TlsProtocol.assertEmpty(buf); |
| |
| return statusRequest; |
| } |
| |
| public static boolean readTruncatedHMacExtension(byte[] extensionData) throws IOException |
| { |
| return readEmptyExtensionData(extensionData); |
| } |
| } |