1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.ssl;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.ByteBufAllocator;
20 import io.netty.buffer.ReadOnlyByteBuf;
21 import io.netty.buffer.ByteBufUtil;
22 import io.netty.channel.ChannelHandlerContext;
23 import io.netty.handler.codec.base64.Base64;
24 import io.netty.handler.codec.base64.Base64Dialect;
25
26 import java.nio.ByteBuffer;
27 import java.nio.ByteOrder;
28 import java.util.List;
29 import java.util.Set;
30
31 import javax.net.ssl.SSLHandshakeException;
32
33 import static java.util.Arrays.asList;
34
35
36
37
38 final class SslUtils {
39
40
41 static final String PROTOCOL_SSL_V2_HELLO = "SSLv2Hello";
42 static final String PROTOCOL_SSL_V2 = "SSLv2";
43 static final String PROTOCOL_SSL_V3 = "SSLv3";
44 static final String PROTOCOL_TLS_V1 = "TLSv1";
45 static final String PROTOCOL_TLS_V1_1 = "TLSv1.1";
46 static final String PROTOCOL_TLS_V1_2 = "TLSv1.2";
47
48
49
50
51 static final int SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC = 20;
52
53
54
55
56 static final int SSL_CONTENT_TYPE_ALERT = 21;
57
58
59
60
61 static final int SSL_CONTENT_TYPE_HANDSHAKE = 22;
62
63
64
65
66 static final int SSL_CONTENT_TYPE_APPLICATION_DATA = 23;
67
68
69
70
71 static final int SSL_CONTENT_TYPE_EXTENSION_HEARTBEAT = 24;
72
73
74
75
76 static final int SSL_RECORD_HEADER_LENGTH = 5;
77
78
79
80
81 static final int NOT_ENOUGH_DATA = -1;
82
83
84
85
86 static final int NOT_ENCRYPTED = -2;
87
88 static final String[] DEFAULT_CIPHER_SUITES = {
89
90 "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
91 "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
92 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
93 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
94
95 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
96
97 "TLS_RSA_WITH_AES_128_GCM_SHA256",
98 "TLS_RSA_WITH_AES_128_CBC_SHA",
99
100 "TLS_RSA_WITH_AES_256_CBC_SHA"
101 };
102
103
104
105
106 static void addIfSupported(Set<String> supported, List<String> enabled, String... names) {
107 for (String n: names) {
108 if (supported.contains(n)) {
109 enabled.add(n);
110 }
111 }
112 }
113
114 static void useFallbackCiphersIfDefaultIsEmpty(List<String> defaultCiphers, Iterable<String> fallbackCiphers) {
115 if (defaultCiphers.isEmpty()) {
116 for (String cipher : fallbackCiphers) {
117 if (cipher.startsWith("SSL_") || cipher.contains("_RC4_")) {
118 continue;
119 }
120 defaultCiphers.add(cipher);
121 }
122 }
123 }
124
125 static void useFallbackCiphersIfDefaultIsEmpty(List<String> defaultCiphers, String... fallbackCiphers) {
126 useFallbackCiphersIfDefaultIsEmpty(defaultCiphers, asList(fallbackCiphers));
127 }
128
129
130
131
132 static SSLHandshakeException toSSLHandshakeException(Throwable e) {
133 if (e instanceof SSLHandshakeException) {
134 return (SSLHandshakeException) e;
135 }
136
137 return (SSLHandshakeException) new SSLHandshakeException(e.getMessage()).initCause(e);
138 }
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157 static int getEncryptedPacketLength(ByteBuf buffer, int offset) {
158 int packetLength = 0;
159
160
161 boolean tls;
162 switch (buffer.getUnsignedByte(offset)) {
163 case SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC:
164 case SSL_CONTENT_TYPE_ALERT:
165 case SSL_CONTENT_TYPE_HANDSHAKE:
166 case SSL_CONTENT_TYPE_APPLICATION_DATA:
167 case SSL_CONTENT_TYPE_EXTENSION_HEARTBEAT:
168 tls = true;
169 break;
170 default:
171
172 tls = false;
173 }
174
175 if (tls) {
176
177 int majorVersion = buffer.getUnsignedByte(offset + 1);
178 if (majorVersion == 3) {
179
180 packetLength = unsignedShortBE(buffer, offset + 3) + SSL_RECORD_HEADER_LENGTH;
181 if (packetLength <= SSL_RECORD_HEADER_LENGTH) {
182
183 tls = false;
184 }
185 } else {
186
187 tls = false;
188 }
189 }
190
191 if (!tls) {
192
193 int headerLength = (buffer.getUnsignedByte(offset) & 0x80) != 0 ? 2 : 3;
194 int majorVersion = buffer.getUnsignedByte(offset + headerLength + 1);
195 if (majorVersion == 2 || majorVersion == 3) {
196
197 packetLength = headerLength == 2 ?
198 (shortBE(buffer, offset) & 0x7FFF) + 2 : (shortBE(buffer, offset) & 0x3FFF) + 3;
199 if (packetLength <= headerLength) {
200 return NOT_ENOUGH_DATA;
201 }
202 } else {
203 return NOT_ENCRYPTED;
204 }
205 }
206 return packetLength;
207 }
208
209
210 @SuppressWarnings("deprecation")
211 private static int unsignedShortBE(ByteBuf buffer, int offset) {
212 return buffer.order() == ByteOrder.BIG_ENDIAN ?
213 buffer.getUnsignedShort(offset) : ByteBufUtil.swapShort(buffer.getShort(offset)) & 0xFFFF;
214 }
215
216
217 @SuppressWarnings("deprecation")
218 private static short shortBE(ByteBuf buffer, int offset) {
219 return buffer.order() == ByteOrder.BIG_ENDIAN ?
220 buffer.getShort(offset) : ByteBufUtil.swapShort(buffer.getShort(offset));
221 }
222
223 private static short unsignedByte(byte b) {
224 return (short) (b & 0xFF);
225 }
226
227
228 private static int unsignedShortBE(ByteBuffer buffer, int offset) {
229 return shortBE(buffer, offset) & 0xFFFF;
230 }
231
232
233 private static short shortBE(ByteBuffer buffer, int offset) {
234 return buffer.order() == ByteOrder.BIG_ENDIAN ?
235 buffer.getShort(offset) : ByteBufUtil.swapShort(buffer.getShort(offset));
236 }
237
238 static int getEncryptedPacketLength(ByteBuffer[] buffers, int offset) {
239 ByteBuffer buffer = buffers[offset];
240
241
242 if (buffer.remaining() >= SSL_RECORD_HEADER_LENGTH) {
243 return getEncryptedPacketLength(buffer);
244 }
245
246
247 ByteBuffer tmp = ByteBuffer.allocate(5);
248
249 do {
250 buffer = buffers[offset++].duplicate();
251 if (buffer.remaining() > tmp.remaining()) {
252 buffer.limit(buffer.position() + tmp.remaining());
253 }
254 tmp.put(buffer);
255 } while (tmp.hasRemaining());
256
257
258 tmp.flip();
259 return getEncryptedPacketLength(tmp);
260 }
261
262 private static int getEncryptedPacketLength(ByteBuffer buffer) {
263 int packetLength = 0;
264 int pos = buffer.position();
265
266 boolean tls;
267 switch (unsignedByte(buffer.get(pos))) {
268 case SSL_CONTENT_TYPE_CHANGE_CIPHER_SPEC:
269 case SSL_CONTENT_TYPE_ALERT:
270 case SSL_CONTENT_TYPE_HANDSHAKE:
271 case SSL_CONTENT_TYPE_APPLICATION_DATA:
272 case SSL_CONTENT_TYPE_EXTENSION_HEARTBEAT:
273 tls = true;
274 break;
275 default:
276
277 tls = false;
278 }
279
280 if (tls) {
281
282 int majorVersion = unsignedByte(buffer.get(pos + 1));
283 if (majorVersion == 3) {
284
285 packetLength = unsignedShortBE(buffer, pos + 3) + SSL_RECORD_HEADER_LENGTH;
286 if (packetLength <= SSL_RECORD_HEADER_LENGTH) {
287
288 tls = false;
289 }
290 } else {
291
292 tls = false;
293 }
294 }
295
296 if (!tls) {
297
298 int headerLength = (unsignedByte(buffer.get(pos)) & 0x80) != 0 ? 2 : 3;
299 int majorVersion = unsignedByte(buffer.get(pos + headerLength + 1));
300 if (majorVersion == 2 || majorVersion == 3) {
301
302 packetLength = headerLength == 2 ?
303 (shortBE(buffer, pos) & 0x7FFF) + 2 : (shortBE(buffer, pos) & 0x3FFF) + 3;
304 if (packetLength <= headerLength) {
305 return NOT_ENOUGH_DATA;
306 }
307 } else {
308 return NOT_ENCRYPTED;
309 }
310 }
311 return packetLength;
312 }
313
314 static void notifyHandshakeFailure(ChannelHandlerContext ctx, Throwable cause, boolean notify) {
315
316
317 ctx.flush();
318 if (notify) {
319 ctx.fireUserEventTriggered(new SslHandshakeCompletionEvent(cause));
320 }
321 ctx.close();
322 }
323
324
325
326
327 static void zeroout(ByteBuf buffer) {
328 if (!(buffer instanceof ReadOnlyByteBuf)) {
329 buffer.setZero(0, buffer.capacity());
330 }
331 }
332
333
334
335
336 static void zerooutAndRelease(ByteBuf buffer) {
337 zeroout(buffer);
338 buffer.release();
339 }
340
341
342
343
344
345
346 static ByteBuf toBase64(ByteBufAllocator allocator, ByteBuf src) {
347 ByteBuf dst = Base64.encode(src, src.readerIndex(),
348 src.readableBytes(), true, Base64Dialect.STANDARD, allocator);
349 src.readerIndex(src.writerIndex());
350 return dst;
351 }
352
353 private SslUtils() {
354 }
355 }