1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.ssl; 27 28 import java.io.EOFException; 29 import java.io.IOException; 30 import java.io.InterruptedIOException; 31 import java.nio.ByteBuffer; 32 import javax.crypto.AEADBadTagException; 33 import javax.crypto.BadPaddingException; 34 import javax.net.ssl.SSLHandshakeException; 35 36 /** 37 * Interface for SSL/TLS transportation. 38 */ 39 interface SSLTransport { 40 41 /** 42 * Returns the host name of the peer. 43 * 44 * @return the host name of the peer, or null if nothing is 45 * available. 46 */ 47 String getPeerHost(); 48 49 /** 50 * Returns the port number of the peer. 51 * 52 * @return the port number of the peer, or -1 if nothing is 53 * available. 54 */ 55 int getPeerPort(); 56 57 /** 58 * Shutdown the transport. 59 */ 60 default void shutdown() throws IOException { 61 // blank 62 } 63 64 /** 65 * Return true if delegated tasks used for handshaking operations. 66 * 67 * @return true if delegated tasks used for handshaking operations. 68 */ 69 boolean useDelegatedTask(); 70 71 /** 72 * Decodes an array of SSL/TLS network source data into the 73 * destination application data buffers. 74 * 75 * For SSL/TLS connections, if no source data, the network data may be 76 * received from the underlying underlying SSL/TLS input stream. 77 * 78 * @param context the transportation context 79 * @param srcs an array of {@code ByteBuffers} containing the 80 * inbound network data 81 * @param srcsOffset The offset within the {@code srcs} buffer array 82 * of the first buffer from which bytes are to be 83 * retrieved; it must be non-negative and no larger 84 * than {@code srcs.length}. 85 * @param srcsLength The maximum number of {@code srcs} buffers to be 86 * accessed; it must be non-negative and no larger than 87 * {@code srcs.length} - {@code srcsOffset}. 88 * @param dsts an array of {@code ByteBuffers} to hold inbound 89 * application data 90 * @param dstsOffset The offset within the {@code dsts} buffer array 91 * of the first buffer from which bytes are to be 92 * placed; it must be non-negative and no larger 93 * than {@code dsts.length}. 94 * @param dstsLength The maximum number of {@code dsts} buffers to be 95 * accessed; it must be non-negative and no larger than 96 * {@code dsts.length} - {@code dstsOffset}. 97 * 98 * @return a {@code Plaintext} describing the result of 99 * the operation 100 * @throws IOException if a problem was encountered while receiving or 101 * decoding networking data 102 */ 103 static Plaintext decode(TransportContext context, 104 ByteBuffer[] srcs, int srcsOffset, int srcsLength, 105 ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException { 106 107 Plaintext[] plaintexts = null; 108 try { 109 plaintexts = 110 context.inputRecord.decode(srcs, srcsOffset, srcsLength); 111 } catch (UnsupportedOperationException unsoe) { // SSLv2Hello 112 // Hack code to deliver SSLv2 error message for SSL/TLS connections. 113 context.outputRecord.encodeV2NoCipher(); 114 if (SSLLogger.isOn && SSLLogger.isOn("ssl")) { 115 SSLLogger.finest("may be talking to SSLv2"); 116 } 117 118 throw context.fatal(Alert.UNEXPECTED_MESSAGE, unsoe); 119 } catch (AEADBadTagException bte) { 120 throw context.fatal(Alert.BAD_RECORD_MAC, bte); 121 } catch (BadPaddingException bpe) { 122 /* 123 * The basic SSLv3 record protection involves (optional) 124 * encryption for privacy, and an integrity check ensuring 125 * data origin authentication. We do them both here, and 126 * throw a fatal alert if the integrity check fails. 127 */ 128 Alert alert = (context.handshakeContext != null) ? 129 Alert.HANDSHAKE_FAILURE : 130 Alert.BAD_RECORD_MAC; 131 throw context.fatal(alert, bpe); 132 } catch (SSLHandshakeException she) { 133 // may be record sequence number overflow 134 throw context.fatal(Alert.HANDSHAKE_FAILURE, she); 135 } catch (EOFException eofe) { 136 // rethrow EOFException, the call will handle it if neede. 137 throw eofe; 138 } catch (InterruptedIOException iioe) { 139 // don't close the Socket in case of timeouts or interrupts. 140 throw iioe; 141 } catch (IOException ioe) { 142 throw context.fatal(Alert.UNEXPECTED_MESSAGE, ioe); 143 } 144 145 if (plaintexts == null || plaintexts.length == 0) { 146 // Connection closed or record should be discarded. 147 return Plaintext.PLAINTEXT_NULL; 148 } 149 150 Plaintext finalPlaintext = Plaintext.PLAINTEXT_NULL; 151 for (Plaintext plainText : plaintexts) { 152 // plainText should never be null for TLS protocols 153 if (plainText != null && 154 plainText != Plaintext.PLAINTEXT_NULL && 155 plainText.contentType != ContentType.APPLICATION_DATA.id) { 156 context.dispatch(plainText); 157 } 158 159 if (plainText == null) { 160 plainText = Plaintext.PLAINTEXT_NULL; 161 } else if (plainText.contentType == 162 ContentType.APPLICATION_DATA.id) { 163 // check handshake status 164 // 165 // Note that JDK does not support 0-RTT yet. Otherwise, it is 166 // needed to check early_data. 167 if (!context.isNegotiated) { 168 if (SSLLogger.isOn && SSLLogger.isOn("ssl,verbose")) { 169 SSLLogger.warning("unexpected application data " + 170 "before handshake completion"); 171 } 172 173 throw context.fatal(Alert.UNEXPECTED_MESSAGE, 174 "Receiving application data before handshake complete"); 175 } 176 177 // Fill the destination buffers. 178 if ((dsts != null) && (dstsLength > 0)) { 179 ByteBuffer fragment = plainText.fragment; 180 int remains = fragment.remaining(); 181 182 // Should have enough room in the destination buffers. 183 int limit = dstsOffset + dstsLength; 184 for (int i = dstsOffset; 185 ((i < limit) && (remains > 0)); i++) { 186 187 int amount = Math.min(dsts[i].remaining(), remains); 188 fragment.limit(fragment.position() + amount); 189 dsts[i].put(fragment); 190 remains -= amount; 191 192 if (!dsts[i].hasRemaining()) { 193 dstsOffset++; 194 } 195 } 196 197 if (remains > 0) { 198 throw context.fatal(Alert.INTERNAL_ERROR, 199 "no sufficient room in the destination buffers"); 200 } 201 } 202 } 203 204 finalPlaintext = plainText; 205 } 206 207 return finalPlaintext; 208 } 209 }