OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / libcore / luni / src / main / java / org / apache / harmony / xnet / provider / jsse / NativeCrypto.java
1 /*
2  * Copyright (C) 2008 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 package org.apache.harmony.xnet.provider.jsse;
18
19 import java.io.FileDescriptor;
20 import java.io.IOException;
21 import java.lang.reflect.Field;
22 import java.net.Socket;
23 import java.net.SocketImpl;
24 import java.net.SocketTimeoutException;
25 import java.security.cert.Certificate;
26 import java.security.cert.CertificateEncodingException;
27 import java.security.cert.CertificateException;
28 import java.security.cert.X509Certificate;
29 import java.security.interfaces.RSAPublicKey;
30 import java.util.ArrayList;
31 import java.util.HashMap;
32 import java.util.LinkedHashMap;
33 import java.util.List;
34 import java.util.Map;
35 import javax.net.ssl.SSLException;
36
37 /**
38  * Provides the Java side of our JNI glue for OpenSSL.
39  */
40 public final class NativeCrypto {
41
42     // --- OpenSSL library initialization --------------------------------------
43     static {
44         clinit();
45     }
46
47     private native static void clinit();
48
49     // --- DSA/RSA public/private key handling functions -----------------------
50
51     public static native int EVP_PKEY_new_DSA(byte[] p, byte[] q, byte[] g,
52                                               byte[] priv_key, byte[] pub_key);
53
54     public static native int EVP_PKEY_new_RSA(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q);
55
56     public static native void EVP_PKEY_free(int pkey);
57
58     // --- General context handling functions (despite the names) --------------
59
60     public static native int EVP_MD_CTX_create();
61
62     public static native void EVP_MD_CTX_destroy(int ctx);
63
64     public static native int EVP_MD_CTX_copy(int ctx);
65
66     // --- Digest handling functions -------------------------------------------
67
68     public static native void EVP_DigestInit(int ctx, String algorithm);
69
70     public static native void EVP_DigestUpdate(int ctx, byte[] buffer, int offset, int length);
71
72     public static native int EVP_DigestFinal(int ctx, byte[] hash, int offset);
73
74     public static native int EVP_MD_CTX_size(int ctx);
75
76     public static native int EVP_MD_CTX_block_size(int ctx);
77
78     // --- Signature handling functions ----------------------------------------
79
80     public static native void EVP_VerifyInit(int ctx, String algorithm);
81
82     public static native void EVP_VerifyUpdate(int ctx, byte[] buffer,
83                                                int offset, int length);
84
85     public static native int EVP_VerifyFinal(int ctx, byte[] signature,
86                                              int offset, int length, int key);
87
88     // --- Legacy Signature handling -------------------------------------------
89     // TODO rewrite/replace with EVP_Verify*
90     /**
91      * Verifies an RSA signature. Conceptually, this method doesn't really
92      * belong here, but due to its native code being closely tied to OpenSSL
93      * (just like the rest of this class), we put it here for the time being.
94      * This also solves potential problems with native library initialization.
95      *
96      * @param message The message to verify
97      * @param signature The signature to verify
98      * @param algorithm The hash/sign algorithm to use, i.e. "RSA-SHA1"
99      * @param key The RSA public key to use
100      * @return true if the verification succeeds, false otherwise
101      */
102     public static boolean verifySignature(
103             byte[] message, byte[] signature, String algorithm, RSAPublicKey key) {
104         byte[] modulus = key.getModulus().toByteArray();
105         byte[] exponent = key.getPublicExponent().toByteArray();
106
107         return verifySignature(message, signature, algorithm, modulus, exponent) == 1;
108     }
109
110     private static native int verifySignature(byte[] message, byte[] signature,
111             String algorithm, byte[] modulus, byte[] exponent);
112
113     // --- RAND seeding --------------------------------------------------------
114
115     public static final int RAND_SEED_LENGTH_IN_BYTES = 1024;
116
117     public static native void RAND_seed(byte[] seed);
118
119     public static native int RAND_load_file(String filename, long max_bytes);
120
121     // --- SSL handling --------------------------------------------------------
122
123     private static final Field JAVA_NET_SOCKET_IMPL;
124     private static final Field JAVA_NET_SOCKETIMPL_FD;
125     static {
126         try {
127             JAVA_NET_SOCKET_IMPL = Socket.class.getDeclaredField("impl");
128             JAVA_NET_SOCKET_IMPL.setAccessible(true);
129             JAVA_NET_SOCKETIMPL_FD = SocketImpl.class.getDeclaredField("fd");
130             JAVA_NET_SOCKETIMPL_FD.setAccessible(true);
131         } catch (Exception e) {
132             throw new AssertionError(e);
133         }
134     }
135     /**
136      * Return the FileDescriptor associated with the provided socket.
137      */
138     public static FileDescriptor getFileDescriptor(Socket socket) {
139         try {
140             SocketImpl socketImpl = (SocketImpl) JAVA_NET_SOCKET_IMPL.get(socket);
141             FileDescriptor fd = (FileDescriptor) JAVA_NET_SOCKETIMPL_FD.get(socketImpl);
142             return fd;
143         } catch (IllegalAccessException e) {
144             throw new AssertionError(e);
145         }
146     }
147
148     private static final String SUPPORTED_PROTOCOL_SSLV3 = "SSLv3";
149     private static final String SUPPORTED_PROTOCOL_TLSV1 = "TLSv1";
150
151     public static final Map<String, String> OPENSSL_TO_STANDARD_CIPHER_SUITES
152             = new HashMap<String, String>();
153     public static final Map<String, String> STANDARD_TO_OPENSSL_CIPHER_SUITES
154             = new LinkedHashMap<String, String>();
155
156     private static void add(String standard, String openssl) {
157         OPENSSL_TO_STANDARD_CIPHER_SUITES.put(openssl, standard);
158         STANDARD_TO_OPENSSL_CIPHER_SUITES.put(standard, openssl);
159     }
160
161     static {
162         // Note these are added in priority order
163         // Android doesn't currently support Elliptic Curve
164         add("SSL_RSA_WITH_RC4_128_MD5",              "RC4-MD5");
165         add("SSL_RSA_WITH_RC4_128_SHA",              "RC4-SHA");
166         add("TLS_RSA_WITH_AES_128_CBC_SHA",          "AES128-SHA");
167         add("TLS_RSA_WITH_AES_256_CBC_SHA",          "AES256-SHA");
168         // add("TLS_ECDH_ECDSA_WITH_RC4_128_SHA",       "ECDH-ECDSA-RC4-SHA");
169         // add("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",   "ECDH-ECDSA-AES128-SHA");
170         // add("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",   "ECDH-ECDSA-AES256-SHA");
171         // add("TLS_ECDH_RSA_WITH_RC4_128_SHA",         "ECDH-RSA-RC4-SHA");
172         // add("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",     "ECDH-RSA-AES128-SHA");
173         // add("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",     "ECDH-RSA-AES256-SHA");
174         // add("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",      "ECDHE-ECDSA-RC4-SHA");
175         // add("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",  "ECDHE-ECDSA-AES128-SHA");
176         // add("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",  "ECDHE-ECDSA-AES256-SHA");
177         // add("TLS_ECDHE_RSA_WITH_RC4_128_SHA",        "ECDHE-RSA-RC4-SHA");
178         // add("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",    "ECDHE-RSA-AES128-SHA");
179         // add("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",    "ECDHE-RSA-AES256-SHA");
180         add("TLS_DHE_RSA_WITH_AES_128_CBC_SHA",      "DHE-RSA-AES128-SHA");
181         add("TLS_DHE_RSA_WITH_AES_256_CBC_SHA",      "DHE-RSA-AES256-SHA");
182         add("TLS_DHE_DSS_WITH_AES_128_CBC_SHA",      "DHE-DSS-AES128-SHA");
183         add("TLS_DHE_DSS_WITH_AES_256_CBC_SHA",      "DHE-DSS-AES256-SHA");
184         add("SSL_RSA_WITH_3DES_EDE_CBC_SHA",         "DES-CBC3-SHA");
185         // add("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",  "ECDH-ECDSA-DES-CBC3-SHA");
186         // add("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",    "ECDH-RSA-DES-CBC3-SHA");
187         // add("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA", "ECDHE-ECDSA-DES-CBC3-SHA");
188         // add("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",   "ECDHE-RSA-DES-CBC3-SHA");
189         add("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",     "EDH-RSA-DES-CBC3-SHA");
190         add("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",     "EDH-DSS-DES-CBC3-SHA");
191         add("SSL_RSA_WITH_DES_CBC_SHA",              "DES-CBC-SHA");
192         add("SSL_DHE_RSA_WITH_DES_CBC_SHA",          "EDH-RSA-DES-CBC-SHA");
193         add("SSL_DHE_DSS_WITH_DES_CBC_SHA",          "EDH-DSS-DES-CBC-SHA");
194         add("SSL_RSA_EXPORT_WITH_RC4_40_MD5",        "EXP-RC4-MD5");
195         add("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",     "EXP-DES-CBC-SHA");
196         add("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "EXP-EDH-RSA-DES-CBC-SHA");
197         add("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", "EXP-EDH-DSS-DES-CBC-SHA");
198         add("SSL_RSA_WITH_NULL_MD5",                 "NULL-MD5");
199         add("SSL_RSA_WITH_NULL_SHA",                 "NULL-SHA");
200         // add("TLS_ECDH_ECDSA_WITH_NULL_SHA",          "ECDH-ECDSA-NULL-SHA");
201         // add("TLS_ECDH_RSA_WITH_NULL_SHA",            "ECDH-RSA-NULL-SHA");
202         // add("TLS_ECDHE_ECDSA_WITH_NULL_SHA",         "ECDHE-ECDSA-NULL-SHA");
203         // add("TLS_ECDHE_RSA_WITH_NULL_SHA",           "ECDHE-RSA-NULL-SHA");
204         add("SSL_DH_anon_WITH_RC4_128_MD5",          "ADH-RC4-MD5");
205         add("TLS_DH_anon_WITH_AES_128_CBC_SHA",      "ADH-AES128-SHA");
206         add("TLS_DH_anon_WITH_AES_256_CBC_SHA",      "ADH-AES256-SHA");
207         add("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA",     "ADH-DES-CBC3-SHA");
208         add("SSL_DH_anon_WITH_DES_CBC_SHA",          "ADH-DES-CBC-SHA");
209         // add("TLS_ECDH_anon_WITH_RC4_128_SHA",        "AECDH-RC4-SHA");
210         // add("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",    "AECDH-AES128-SHA");
211         // add("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",    "AECDH-AES256-SHA");
212         // add("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",   "AECDH-DES-CBC3-SHA");
213         add("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5",    "EXP-ADH-RC4-MD5");
214         add("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", "EXP-ADH-DES-CBC-SHA");
215         // add("TLS_ECDH_anon_WITH_NULL_SHA",           "AECDH-NULL-SHA");
216
217         // No Kerberos in Android
218         // add("TLS_KRB5_WITH_RC4_128_SHA",           "KRB5-RC4-SHA");
219         // add("TLS_KRB5_WITH_RC4_128_MD5",           "KRB5-RC4-MD5");
220         // add("TLS_KRB5_WITH_3DES_EDE_CBC_SHA",      "KRB5-DES-CBC3-SHA");
221         // add("TLS_KRB5_WITH_3DES_EDE_CBC_MD5",      "KRB5-DES-CBC3-MD5");
222         // add("TLS_KRB5_WITH_DES_CBC_SHA",           "KRB5-DES-CBC-SHA");
223         // add("TLS_KRB5_WITH_DES_CBC_MD5",           "KRB5-DES-CBC-MD5");
224         // add("TLS_KRB5_EXPORT_WITH_RC4_40_SHA",     "EXP-KRB5-RC4-SHA");
225         // add("TLS_KRB5_EXPORT_WITH_RC4_40_MD5",     "EXP-KRB5-RC4-MD5");
226         // add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA", "EXP-KRB5-DES-CBC-SHA");
227         // add("TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5", "EXP-KRB5-DES-CBC-MD5");
228
229         // not implemented by either RI or OpenSSL
230         // add("SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", null);
231         // add("SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", null);
232
233         // EXPORT1024 suites were never standardized but were widely implemented.
234         // OpenSSL 0.9.8c and later have disabled TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES
235         // add("SSL_RSA_EXPORT1024_WITH_DES_CBC_SHA", "EXP1024-DES-CBC-SHA");
236         // add("SSL_RSA_EXPORT1024_WITH_RC4_56_SHA",  "EXP1024-RC4-SHA");
237
238         // No RC2
239         // add("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5",  "EXP-RC2-CBC-MD5");
240         // add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA", "EXP-KRB5-RC2-CBC-SHA");
241         // add("TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5", "EXP-KRB5-RC2-CBC-MD5");
242
243         // PSK is Private Shared Key - didn't exist in Froyo's openssl - no JSSE equivalent
244         // add(null, "PSK-3DES-EDE-CBC-SHA");
245         // add(null, "PSK-AES128-CBC-SHA");
246         // add(null, "PSK-AES256-CBC-SHA");
247         // add(null, "PSK-RC4-SHA");
248     }
249
250     private static final String[] SUPPORTED_CIPHER_SUITES
251             = STANDARD_TO_OPENSSL_CIPHER_SUITES.keySet().toArray(new String[0]);
252
253     // SSL mode from ssl.h
254     public static long SSL_MODE_HANDSHAKE_CUTTHROUGH = 0x00000040L;
255
256     // SSL options from ssl.h
257     public static long SSL_OP_NO_TICKET      = 0x00004000L;
258     public static long SSL_OP_NO_COMPRESSION = 0x00020000L;
259     public static long SSL_OP_NO_SSLv3       = 0x02000000L;
260     public static long SSL_OP_NO_TLSv1       = 0x04000000L;
261
262     public static native int SSL_CTX_new();
263
264     public static String[] getDefaultCipherSuites() {
265         return new String[] {
266             "SSL_RSA_WITH_RC4_128_MD5",
267             "SSL_RSA_WITH_RC4_128_SHA",
268             "TLS_RSA_WITH_AES_128_CBC_SHA",
269             "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
270             "TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
271             "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
272             "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
273             "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
274             "SSL_RSA_WITH_DES_CBC_SHA",
275             "SSL_DHE_RSA_WITH_DES_CBC_SHA",
276             "SSL_DHE_DSS_WITH_DES_CBC_SHA",
277             "SSL_RSA_EXPORT_WITH_RC4_40_MD5",
278             "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA",
279             "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
280             "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"
281         };
282     }
283
284     public static String[] getSupportedCipherSuites() {
285         return SUPPORTED_CIPHER_SUITES.clone();
286     }
287
288     public static native void SSL_CTX_free(int ssl_ctx);
289
290     public static native int SSL_new(int ssl_ctx) throws SSLException;
291
292     public static final String[] KEY_TYPES = new String[] {
293         "RSA",
294         "DSA",
295         "DH_RSA",
296         "DH_DSA",
297         "EC"
298     };
299
300     public static String keyType(int keyType) {
301         switch (keyType) {
302             case 1: // TLS_CT_RSA_SIGN
303                 return "RSA";
304             case 2: // TLS_CT_DSS_SIGN
305                 return "DSA";
306             case 3: // TLS_CT_RSA_FIXED_DH
307                 return "DH_RSA";
308             case 4: // TLS_CT_DSS_FIXED_DH
309                 return "DH_DSA";
310             case 64: // TLS_CT_ECDSA_SIGN
311                 return "EC";
312             default:
313                 return null;
314         }
315     }
316
317     public static byte[][] encodeCertificates(Certificate[] certificates)
318             throws CertificateEncodingException {
319         byte[][] certificateBytes = new byte[certificates.length][];
320         for (int i = 0; i < certificates.length; i++) {
321             certificateBytes[i] = certificates[i].getEncoded();
322         }
323         return certificateBytes;
324     }
325
326     public static native void SSL_use_certificate(int ssl, byte[][] asn1DerEncodedCertificateChain);
327
328     public static native void SSL_use_PrivateKey(int ssl, byte[] pkcs8EncodedPrivateKey);
329
330     public static native void SSL_check_private_key(int ssl) throws SSLException;
331
332     public static byte[][] encodeIssuerX509Principals(X509Certificate[] certificates)
333             throws CertificateEncodingException {
334         byte[][] principalBytes = new byte[certificates.length][];
335         for (int i = 0; i < certificates.length; i++) {
336             principalBytes[i] = certificates[i].getIssuerX500Principal().getEncoded();
337         }
338         return principalBytes;
339     }
340
341     public static native void SSL_set_client_CA_list(int ssl, byte[][] asn1DerEncodedX500Principals);
342
343     public static native long SSL_get_mode(int ssl);
344
345     public static native long SSL_set_mode(int ssl, long mode);
346
347     public static native long SSL_clear_mode(int ssl, long mode);
348
349     public static native long SSL_get_options(int ssl);
350
351     public static native long SSL_set_options(int ssl, long options);
352
353     public static native long SSL_clear_options(int ssl, long options);
354
355     public static String[] getSupportedProtocols() {
356         return new String[] { SUPPORTED_PROTOCOL_SSLV3, SUPPORTED_PROTOCOL_TLSV1 };
357     }
358
359     public static void setEnabledProtocols(int ssl, String[] protocols) {
360         checkEnabledProtocols(protocols);
361         // openssl uses negative logic letting you disable protocols.
362         // so first, assume we need to set all (disable all) and clear none (enable none).
363         // in the loop, selectively move bits from set to clear (from disable to enable)
364         long optionsToSet = (SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1);
365         long optionsToClear = 0;
366         for (int i = 0; i < protocols.length; i++) {
367             String protocol = protocols[i];
368             if (protocol.equals(SUPPORTED_PROTOCOL_SSLV3)) {
369                 optionsToSet &= ~SSL_OP_NO_SSLv3;
370                 optionsToClear |= SSL_OP_NO_SSLv3;
371             } else if (protocol.equals(SUPPORTED_PROTOCOL_TLSV1)) {
372                 optionsToSet &= ~SSL_OP_NO_TLSv1;
373                 optionsToClear |= SSL_OP_NO_TLSv1;
374             } else {
375                 // error checked by checkEnabledProtocols
376                 throw new IllegalStateException();
377             }
378         }
379
380         SSL_set_options(ssl, optionsToSet);
381         SSL_clear_options(ssl, optionsToClear);
382     }
383
384     public static String[] checkEnabledProtocols(String[] protocols) {
385         if (protocols == null) {
386             throw new IllegalArgumentException("protocols == null");
387         }
388         for (int i = 0; i < protocols.length; i++) {
389             String protocol = protocols[i];
390             if (protocol == null) {
391                 throw new IllegalArgumentException("protocols[" + i + "] == null");
392             }
393             if ((!protocol.equals(SUPPORTED_PROTOCOL_SSLV3))
394                     && (!protocol.equals(SUPPORTED_PROTOCOL_TLSV1))) {
395                 throw new IllegalArgumentException("protocol " + protocol
396                                                    + " is not supported");
397             }
398         }
399         return protocols;
400     }
401
402     public static native void SSL_set_cipher_lists(int ssl, String[] ciphers);
403
404     public static void setEnabledCipherSuites(int ssl, String[] cipherSuites) {
405         checkEnabledCipherSuites(cipherSuites);
406         List<String> opensslSuites = new ArrayList<String>();
407         for (int i = 0; i < cipherSuites.length; i++) {
408             String cipherSuite = cipherSuites[i];
409             String openssl = STANDARD_TO_OPENSSL_CIPHER_SUITES.get(cipherSuite);
410             String cs = (openssl == null) ? cipherSuite : openssl;
411             opensslSuites.add(cs);
412         }
413         SSL_set_cipher_lists(ssl, opensslSuites.toArray(new String[opensslSuites.size()]));
414     }
415
416     public static String[] checkEnabledCipherSuites(String[] cipherSuites) {
417         if (cipherSuites == null) {
418             throw new IllegalArgumentException("cipherSuites == null");
419         }
420         // makes sure all suites are valid, throwing on error
421         for (int i = 0; i < cipherSuites.length; i++) {
422             String cipherSuite = cipherSuites[i];
423             if (cipherSuite == null) {
424                 throw new IllegalArgumentException("cipherSuites[" + i + "] == null");
425             }
426             if (STANDARD_TO_OPENSSL_CIPHER_SUITES.containsKey(cipherSuite)) {
427                 continue;
428             }
429             if (OPENSSL_TO_STANDARD_CIPHER_SUITES.containsKey(cipherSuite)) {
430                 // TODO log warning about using backward compatability
431                 continue;
432             }
433             throw new IllegalArgumentException("cipherSuite " + cipherSuite + " is not supported.");
434         }
435         return cipherSuites;
436     }
437
438     private static final String SUPPORTED_COMPRESSION_METHOD_ZLIB = "ZLIB";
439     private static final String SUPPORTED_COMPRESSION_METHOD_NULL = "NULL";
440
441     private static final String[] SUPPORTED_COMPRESSION_METHODS
442             = { SUPPORTED_COMPRESSION_METHOD_ZLIB, SUPPORTED_COMPRESSION_METHOD_NULL };
443
444     public static String[] getSupportedCompressionMethods() {
445         return SUPPORTED_COMPRESSION_METHODS.clone();
446     }
447
448     public static final String[] getDefaultCompressionMethods() {
449         return new String[] { SUPPORTED_COMPRESSION_METHOD_NULL };
450     }
451
452     public static String[] checkEnabledCompressionMethods(String[] methods) {
453         if (methods == null) {
454             throw new IllegalArgumentException("methods == null");
455         }
456         if (methods.length < 1
457                 && !methods[methods.length-1].equals(SUPPORTED_COMPRESSION_METHOD_NULL)) {
458             throw new IllegalArgumentException("last method must be NULL");
459         }
460         for (int i = 0; i < methods.length; i++) {
461             String method = methods[i];
462             if (method == null) {
463                 throw new IllegalArgumentException("methods[" + i + "] == null");
464             }
465             if (!method.equals(SUPPORTED_COMPRESSION_METHOD_ZLIB)
466                     && !method.equals(SUPPORTED_COMPRESSION_METHOD_NULL)) {
467                 throw new IllegalArgumentException("method " + method
468                                                    + " is not supported");
469             }
470         }
471         return methods;
472     }
473
474     public static void setEnabledCompressionMethods(int ssl, String[] methods) {
475         checkEnabledCompressionMethods(methods);
476         // openssl uses negative logic letting you disable compression.
477         // so first, assume we need to set all (disable all) and clear none (enable none).
478         // in the loop, selectively move bits from set to clear (from disable to enable)
479         long optionsToSet = (SSL_OP_NO_COMPRESSION);
480         long optionsToClear = 0;
481         for (int i = 0; i < methods.length; i++) {
482             String method = methods[i];
483             if (method.equals(SUPPORTED_COMPRESSION_METHOD_NULL)) {
484                 // nothing to do to support NULL
485             } else if (method.equals(SUPPORTED_COMPRESSION_METHOD_ZLIB)) {
486                 optionsToSet &= ~SSL_OP_NO_COMPRESSION;
487                 optionsToClear |= SSL_OP_NO_COMPRESSION;
488             } else {
489                 // error checked by checkEnabledCompressionMethods
490                 throw new IllegalStateException();
491             }
492         }
493
494         SSL_set_options(ssl, optionsToSet);
495         SSL_clear_options(ssl, optionsToClear);
496     }
497
498     /*
499      * See the OpenSSL ssl.h header file for more information.
500      */
501     public static final int SSL_VERIFY_NONE =                 0x00;
502     public static final int SSL_VERIFY_PEER =                 0x01;
503     public static final int SSL_VERIFY_FAIL_IF_NO_PEER_CERT = 0x02;
504
505     public static native void SSL_set_verify(int sslNativePointer, int mode);
506
507     public static native void SSL_set_session(int sslNativePointer, int sslSessionNativePointer)
508         throws SSLException;
509
510     public static native void SSL_set_session_creation_enabled(
511             int sslNativePointer, boolean creationEnabled) throws SSLException;
512
513     public static native void SSL_set_tlsext_host_name(int sslNativePointer, String hostname)
514             throws SSLException;
515     public static native String SSL_get_servername(int sslNativePointer);
516
517     /**
518      * Returns the sslSessionNativePointer of the negotiated session
519      */
520     public static native int SSL_do_handshake(int sslNativePointer,
521                                               FileDescriptor fd,
522                                               SSLHandshakeCallbacks shc,
523                                               int timeout,
524                                               boolean client_mode)
525         throws SSLException, SocketTimeoutException, CertificateException;
526
527     /**
528      * Currently only intended for forcing renegotiation for testing.
529      * Not used within OpenSSLSocketImpl.
530      */
531     public static native void SSL_renegotiate(int sslNativePointer) throws SSLException;
532
533     /**
534      * Returns the local ASN.1 DER encoded X509 certificates.
535      */
536     public static native byte[][] SSL_get_certificate(int sslNativePointer);
537
538     /**
539      * Returns the peer ASN.1 DER encoded X509 certificates.
540      */
541     public static native byte[][] SSL_get_peer_cert_chain(int sslNativePointer);
542
543     /**
544      * Reads with the native SSL_read function from the encrypted data stream
545      * @return -1 if error or the end of the stream is reached.
546      */
547     public static native int SSL_read_byte(int sslNativePointer,
548                                            FileDescriptor fd,
549                                            SSLHandshakeCallbacks shc,
550                                            int timeout) throws IOException;
551     public static native int SSL_read(int sslNativePointer,
552                                       FileDescriptor fd,
553                                       SSLHandshakeCallbacks shc,
554                                       byte[] b, int off, int len, int timeout)
555         throws IOException;
556
557     /**
558      * Writes with the native SSL_write function to the encrypted data stream.
559      */
560     public static native void SSL_write_byte(int sslNativePointer,
561                                              FileDescriptor fd,
562                                              SSLHandshakeCallbacks shc,
563                                              int b) throws IOException;
564     public static native void SSL_write(int sslNativePointer,
565                                         FileDescriptor fd,
566                                         SSLHandshakeCallbacks shc,
567                                         byte[] b, int off, int len)
568         throws IOException;
569
570     public static native void SSL_interrupt(int sslNativePointer) throws IOException;
571     public static native void SSL_shutdown(int sslNativePointer,
572                                            FileDescriptor fd,
573                                            SSLHandshakeCallbacks shc) throws IOException;
574
575     public static native void SSL_free(int sslNativePointer);
576
577     public static native byte[] SSL_SESSION_session_id(int sslSessionNativePointer);
578
579     public static native long SSL_SESSION_get_time(int sslSessionNativePointer);
580
581     public static native String SSL_SESSION_get_version(int sslSessionNativePointer);
582
583     public static native String SSL_SESSION_cipher(int sslSessionNativePointer);
584
585     public static native String SSL_SESSION_compress_meth(int sslCtxNativePointer,
586                                                           int sslSessionNativePointer);
587
588     public static native void SSL_SESSION_free(int sslSessionNativePointer);
589
590     public static native byte[] i2d_SSL_SESSION(int sslSessionNativePointer);
591
592     public static native int d2i_SSL_SESSION(byte[] data);
593
594     /**
595      * A collection of callbacks from the native OpenSSL code that are
596      * related to the SSL handshake initiated by SSL_do_handshake.
597      */
598     public interface SSLHandshakeCallbacks {
599         /**
600          * Verify that we trust the certificate chain is trusted.
601          *
602          * @param asn1DerEncodedCertificateChain A chain of ASN.1 DER encoded certficates
603          * @param authMethod auth algorithm name
604          *
605          * @throws CertificateException if the certificate is untrusted
606          */
607         public void verifyCertificateChain(byte[][] asn1DerEncodedCertificateChain, String authMethod)
608             throws CertificateException;
609
610         /**
611          * Called on an SSL client when the server requests (or
612          * requires a certificate). The client can respond by using
613          * SSL_use_certificate and SSL_use_PrivateKey to set a
614          * certificate if has an appropriate one available, similar to
615          * how the server provides its certificate.
616          *
617          * @param keyTypes key types supported by the server,
618          * convertible to strings with #keyType
619          * @param asn1DerEncodedX500Principals CAs known to the server
620          */
621         public void clientCertificateRequested(byte[] keyTypes,
622                                                byte[][] asn1DerEncodedX500Principals)
623             throws CertificateEncodingException, SSLException;
624
625         /**
626          * Called when SSL handshake is completed. Note that this can
627          * be after SSL_do_handshake returns when handshake cutthrough
628          * is enabled.
629          */
630         public void handshakeCompleted();
631     }
632 }