Home | History | Annotate | Download | only in jsse
      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 }
    633