• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * Copyright 2016 The Netty Project
19  *
20  * The Netty Project licenses this file to you under the Apache License,
21  * version 2.0 (the "License"); you may not use this file except in compliance
22  * with the License. You may obtain a copy of the License at:
23  *
24  *   http://www.apache.org/licenses/LICENSE-2.0
25  *
26  * Unless required by applicable law or agreed to in writing, software
27  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29  * License for the specific language governing permissions and limitations
30  * under the License.
31  */
32 
33 package org.conscrypt;
34 
35 import static java.lang.Math.min;
36 import static org.conscrypt.NativeConstants.SSL3_RT_ALERT;
37 import static org.conscrypt.NativeConstants.SSL3_RT_APPLICATION_DATA;
38 import static org.conscrypt.NativeConstants.SSL3_RT_CHANGE_CIPHER_SPEC;
39 import static org.conscrypt.NativeConstants.SSL3_RT_HANDSHAKE;
40 import static org.conscrypt.NativeConstants.SSL3_RT_HEADER_LENGTH;
41 import static org.conscrypt.NativeConstants.SSL3_RT_MAX_PACKET_SIZE;
42 
43 import java.nio.ByteBuffer;
44 import java.security.cert.CertificateEncodingException;
45 import java.security.cert.X509Certificate;
46 import java.util.HashSet;
47 import java.util.Set;
48 import javax.net.ssl.SSLException;
49 import javax.net.ssl.SSLHandshakeException;
50 import javax.net.ssl.SSLPeerUnverifiedException;
51 import javax.security.cert.CertificateException;
52 
53 /**
54  * Utility methods for SSL packet processing. Copied from the Netty project.
55  * <p>
56  * This is a public class to allow testing to occur on Android via CTS.
57  */
58 final class SSLUtils {
59     static final boolean USE_ENGINE_SOCKET_BY_DEFAULT = Boolean.parseBoolean(
60             System.getProperty("org.conscrypt.useEngineSocketByDefault", "false"));
61     private static final int MAX_PROTOCOL_LENGTH = 255;
62 
63     // TODO(nathanmittler): Should these be in NativeConstants?
64     enum SessionType {
65         /**
66          * Identifies OpenSSL sessions.
67          */
68         OPEN_SSL(1),
69 
70         /**
71          * Identifies OpenSSL sessions with OCSP stapled data.
72          */
73         OPEN_SSL_WITH_OCSP(2),
74 
75         /**
76          * Identifies OpenSSL sessions with TLS SCT data.
77          */
78         OPEN_SSL_WITH_TLS_SCT(3);
79 
SessionType(int value)80         SessionType(int value) {
81             this.value = value;
82         }
83 
isSupportedType(int type)84         static final boolean isSupportedType(int type) {
85             return type == OPEN_SSL.value || type == OPEN_SSL_WITH_OCSP.value
86                     || type == OPEN_SSL_WITH_TLS_SCT.value;
87         }
88 
89         final int value;
90     }
91 
92     /**
93      * States for SSL engines.
94      */
95     static final class EngineStates {
EngineStates()96         private EngineStates() {}
97 
98         /**
99          * The engine is constructed, but the initial handshake hasn't been started
100          */
101         static final int STATE_NEW = 0;
102 
103         /**
104          * The client/server mode of the engine has been set.
105          */
106         static final int STATE_MODE_SET = 1;
107 
108         /**
109          * The handshake has been started
110          */
111         static final int STATE_HANDSHAKE_STARTED = 2;
112 
113         /**
114          * Listeners of the handshake have been notified of completion but the handshake call
115          * hasn't returned.
116          */
117         static final int STATE_HANDSHAKE_COMPLETED = 3;
118 
119         /**
120          * The handshake call returned but the listeners have not yet been notified. This is expected
121          * behaviour in cut-through mode, where SSL_do_handshake returns before the handshake is
122          * complete. We can now start writing data to the socket.
123          */
124         static final int STATE_READY_HANDSHAKE_CUT_THROUGH = 4;
125 
126         /**
127          * The handshake call has returned and the listeners have been notified. Ready to begin
128          * writing data.
129          */
130         static final int STATE_READY = 5;
131 
132         /**
133          * The inbound direction of the engine has been closed.
134          */
135         static final int STATE_CLOSED_INBOUND = 6;
136 
137         /**
138          * The outbound direction of the engine has been closed.
139          */
140         static final int STATE_CLOSED_OUTBOUND = 7;
141 
142         /**
143          * The engine has been closed.
144          */
145         static final int STATE_CLOSED = 8;
146     }
147 
148     /**
149      * This is the maximum overhead when encrypting plaintext as defined by
150      * <a href="https://www.ietf.org/rfc/rfc5246.txt">rfc5264</a>,
151      * <a href="https://www.ietf.org/rfc/rfc5289.txt">rfc5289</a> and openssl implementation itself.
152      *
153      * Please note that we use a padding of 16 here as openssl uses PKC#5 which uses 16 bytes
154      * whilethe spec itself allow up to 255 bytes. 16 bytes is the max for PKC#5 (which handles it
155      * the same way as PKC#7) as we use a block size of 16. See <a
156      * href="https://tools.ietf.org/html/rfc5652#section-6.3">rfc5652#section-6.3</a>.
157      *
158      * 16 (IV) + 48 (MAC) + 1 (Padding_length field) + 15 (Padding) + 1 (ContentType) + 2
159      * (ProtocolVersion) + 2 (Length)
160      *
161      * TODO: We may need to review this calculation once TLS 1.3 becomes available.
162      */
163     private static final int MAX_ENCRYPTION_OVERHEAD_LENGTH = 15 + 48 + 1 + 16 + 1 + 2 + 2;
164 
165     private static final int MAX_ENCRYPTION_OVERHEAD_DIFF =
166             Integer.MAX_VALUE - MAX_ENCRYPTION_OVERHEAD_LENGTH;
167 
168     /** Key type: RSA certificate. */
169     private static final String KEY_TYPE_RSA = "RSA";
170 
171     /** Key type: Elliptic Curve certificate. */
172     private static final String KEY_TYPE_EC = "EC";
173 
174     /**
175      * Returns key type constant suitable for calling X509KeyManager.chooseServerAlias or
176      * X509ExtendedKeyManager.chooseEngineServerAlias. Returns {@code null} for key exchanges that
177      * do not use X.509 for server authentication.
178      */
getServerX509KeyType(long sslCipherNative)179     static String getServerX509KeyType(long sslCipherNative) throws SSLException {
180         String kx_name = NativeCrypto.SSL_CIPHER_get_kx_name(sslCipherNative);
181         if (kx_name.equals("RSA") || kx_name.equals("DHE_RSA") || kx_name.equals("ECDHE_RSA")) {
182             return KEY_TYPE_RSA;
183         } else if (kx_name.equals("ECDHE_ECDSA")) {
184             return KEY_TYPE_EC;
185         } else {
186             return null;
187         }
188     }
189 
190     /**
191      * Similar to getServerKeyType, but returns value given TLS
192      * ClientCertificateType byte values from a CertificateRequest
193      * message for use with X509KeyManager.chooseClientAlias or
194      * X509ExtendedKeyManager.chooseEngineClientAlias.
195      * <p>
196      * Visible for testing.
197      */
getClientKeyType(byte clientCertificateType)198     static String getClientKeyType(byte clientCertificateType) {
199         // See also http://www.ietf.org/assignments/tls-parameters/tls-parameters.xml
200         switch (clientCertificateType) {
201             case NativeConstants.TLS_CT_RSA_SIGN:
202                 return KEY_TYPE_RSA; // RFC rsa_sign
203             case NativeConstants.TLS_CT_ECDSA_SIGN:
204                 return KEY_TYPE_EC; // RFC ecdsa_sign
205             default:
206                 return null;
207         }
208     }
209 
210     /**
211      * Gets the supported key types for client certificates based on the
212      * {@code ClientCertificateType} values provided by the server.
213      *
214      * @param clientCertificateTypes {@code ClientCertificateType} values provided by the server.
215      *        See https://www.ietf.org/assignments/tls-parameters/tls-parameters.xml.
216      * @return supported key types that can be used in {@code X509KeyManager.chooseClientAlias} and
217      *         {@code X509ExtendedKeyManager.chooseEngineClientAlias}.
218      *
219      * Visible for testing.
220      */
getSupportedClientKeyTypes(byte[] clientCertificateTypes)221     static Set<String> getSupportedClientKeyTypes(byte[] clientCertificateTypes) {
222         Set<String> result = new HashSet<String>(clientCertificateTypes.length);
223         for (byte keyTypeCode : clientCertificateTypes) {
224             String keyType = SSLUtils.getClientKeyType(keyTypeCode);
225             if (keyType == null) {
226                 // Unsupported client key type -- ignore
227                 continue;
228             }
229             result.add(keyType);
230         }
231         return result;
232     }
233 
encodeIssuerX509Principals(X509Certificate[] certificates)234     static byte[][] encodeIssuerX509Principals(X509Certificate[] certificates)
235             throws CertificateEncodingException {
236         byte[][] principalBytes = new byte[certificates.length][];
237         for (int i = 0; i < certificates.length; i++) {
238             principalBytes[i] = certificates[i].getIssuerX500Principal().getEncoded();
239         }
240         return principalBytes;
241     }
242 
243     /**
244      * Converts the peer certificates into a cert chain.
245      */
toCertificateChain(X509Certificate[] certificates)246     static javax.security.cert.X509Certificate[] toCertificateChain(X509Certificate[] certificates)
247             throws SSLPeerUnverifiedException {
248         try {
249             javax.security.cert.X509Certificate[] chain =
250                     new javax.security.cert.X509Certificate[certificates.length];
251 
252             for (int i = 0; i < certificates.length; i++) {
253                 byte[] encoded = certificates[i].getEncoded();
254                 chain[i] = javax.security.cert.X509Certificate.getInstance(encoded);
255             }
256             return chain;
257         } catch (CertificateEncodingException e) {
258             SSLPeerUnverifiedException exception = new SSLPeerUnverifiedException(e.getMessage());
259             exception.initCause(exception);
260             throw exception;
261         } catch (CertificateException e) {
262             SSLPeerUnverifiedException exception = new SSLPeerUnverifiedException(e.getMessage());
263             exception.initCause(exception);
264             throw exception;
265         }
266     }
267 
268     /**
269      * Calculates the minimum bytes required in the encrypted output buffer for the given number of
270      * plaintext source bytes.
271      */
calculateOutNetBufSize(int pendingBytes)272     static int calculateOutNetBufSize(int pendingBytes) {
273         return min(SSL3_RT_MAX_PACKET_SIZE,
274                 MAX_ENCRYPTION_OVERHEAD_LENGTH + min(MAX_ENCRYPTION_OVERHEAD_DIFF, pendingBytes));
275     }
276 
277     /**
278      * Wraps the given exception if it's not already a {@link SSLHandshakeException}.
279      */
toSSLHandshakeException(Throwable e)280     static SSLHandshakeException toSSLHandshakeException(Throwable e) {
281         if (e instanceof SSLHandshakeException) {
282             return (SSLHandshakeException) e;
283         }
284 
285         return (SSLHandshakeException) new SSLHandshakeException(e.getMessage()).initCause(e);
286     }
287 
288     /**
289      * Wraps the given exception if it's not already a {@link SSLException}.
290      */
toSSLException(Throwable e)291     static SSLException toSSLException(Throwable e) {
292         if (e instanceof SSLException) {
293             return (SSLException) e;
294         }
295         return new SSLException(e);
296     }
297 
298     /**
299      * Return how much bytes can be read out of the encrypted data. Be aware that this method will
300      * not
301      * increase the readerIndex of the given {@link ByteBuffer}.
302      *
303      * @param buffers The {@link ByteBuffer}s to read from. Be aware that they must have at least
304      * {@link org.conscrypt.NativeConstants#SSL3_RT_HEADER_LENGTH} bytes to read, otherwise it will
305      * throw an {@link IllegalArgumentException}.
306      * @return length The length of the encrypted packet that is included in the buffer. This will
307      * return {@code -1} if the given {@link ByteBuffer} is not encrypted at all.
308      * @throws IllegalArgumentException Is thrown if the given {@link ByteBuffer} has not at least
309      * {@link org.conscrypt.NativeConstants#SSL3_RT_HEADER_LENGTH} bytes to read.
310      */
getEncryptedPacketLength(ByteBuffer[] buffers, int offset)311     static int getEncryptedPacketLength(ByteBuffer[] buffers, int offset) {
312         ByteBuffer buffer = buffers[offset];
313 
314         // Check if everything we need is in one ByteBuffer. If so we can make use of the fast-path.
315         if (buffer.remaining() >= SSL3_RT_HEADER_LENGTH) {
316             return getEncryptedPacketLength(buffer);
317         }
318 
319         // We need to copy 5 bytes into a temporary buffer so we can parse out the packet length
320         // easily.
321         ByteBuffer tmp = ByteBuffer.allocate(SSL3_RT_HEADER_LENGTH);
322         do {
323             buffer = buffers[offset++];
324             int pos = buffer.position();
325             int limit = buffer.limit();
326             if (buffer.remaining() > tmp.remaining()) {
327                 buffer.limit(pos + tmp.remaining());
328             }
329             try {
330                 tmp.put(buffer);
331             } finally {
332                 // Restore the original indices.
333                 buffer.limit(limit);
334                 buffer.position(pos);
335             }
336         } while (tmp.hasRemaining());
337 
338         // Done, flip the buffer so we can read from it.
339         tmp.flip();
340         return getEncryptedPacketLength(tmp);
341     }
342 
343     /**
344      * Encodes a list of protocols into the wire-format (length-prefixed 8-bit strings).
345      * Requires that all strings be encoded with US-ASCII.
346      *
347      * @param protocols the list of protocols to be encoded
348      * @return the encoded form of the protocol list.
349      */
toLengthPrefixedList(String... protocols)350     static byte[] toLengthPrefixedList(String... protocols) {
351         // Calculate the encoded length.
352         int length = 0;
353         for (int i = 0; i < protocols.length; ++i) {
354             int protocolLength = protocols[i].length();
355 
356             // Verify that the length is valid here, so that we don't attempt to allocate an array
357             // below if the threshold is violated.
358             if (protocolLength == 0 || protocolLength > MAX_PROTOCOL_LENGTH) {
359                 throw new IllegalArgumentException("Protocol has invalid length ("
360                         + protocolLength + "): " + protocols[i]);
361             }
362 
363             // Include a 1-byte prefix for each protocol.
364             length += 1 + protocolLength;
365         }
366 
367         byte[] data = new byte[length];
368         for (int dataIndex = 0, i = 0; i < protocols.length; ++i) {
369             String protocol = protocols[i];
370             int protocolLength = protocol.length();
371 
372             // Add the length prefix.
373             data[dataIndex++] = (byte) protocolLength;
374             for (int ci = 0; ci < protocolLength; ++ci) {
375                 char c = protocol.charAt(ci);
376                 if (c > Byte.MAX_VALUE) {
377                     // Enforce US-ASCII
378                     throw new IllegalArgumentException("Protocol contains invalid character: "
379                             + c + "(protocol=" + protocol + ")");
380                 }
381                 data[dataIndex++] = (byte) c;
382             }
383         }
384         return data;
385     }
386 
getEncryptedPacketLength(ByteBuffer buffer)387     private static int getEncryptedPacketLength(ByteBuffer buffer) {
388         int packetLength = 0;
389         int pos = buffer.position();
390         // SSLv3 or TLS - Check ContentType
391         switch (unsignedByte(buffer.get(pos))) {
392             case SSL3_RT_CHANGE_CIPHER_SPEC:
393             case SSL3_RT_ALERT:
394             case SSL3_RT_HANDSHAKE:
395             case SSL3_RT_APPLICATION_DATA:
396                 break;
397             default:
398                 // SSLv2 or bad data
399                 return -1;
400         }
401 
402         // SSLv3 or TLS - Check ProtocolVersion
403         int majorVersion = unsignedByte(buffer.get(pos + 1));
404         if (majorVersion != 3) {
405             // Neither SSLv3 or TLSv1 (i.e. SSLv2 or bad data)
406             return -1;
407         }
408 
409         // SSLv3 or TLS
410         packetLength = unsignedShort(buffer.getShort(pos + 3)) + SSL3_RT_HEADER_LENGTH;
411         if (packetLength <= SSL3_RT_HEADER_LENGTH) {
412             // Neither SSLv3 or TLSv1 (i.e. SSLv2 or bad data)
413             return -1;
414         }
415         return packetLength;
416     }
417 
unsignedByte(byte b)418     private static short unsignedByte(byte b) {
419         return (short) (b & 0xFF);
420     }
421 
unsignedShort(short s)422     private static int unsignedShort(short s) {
423         return s & 0xFFFF;
424     }
425 
SSLUtils()426     private SSLUtils() {}
427 }
428