CipherSuite.java 55.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

Kenny Root's avatar
Kenny Root committed
18
package org.conscrypt;
19 20 21 22 23 24

import java.security.GeneralSecurityException;
import java.util.Hashtable;
import javax.crypto.Cipher;

/**
25
 * Represents Cipher Suite as defined in TLS 1.0 spec.,
26 27 28
 * A.5. The CipherSuite;
 * C. CipherSuite definitions.
 * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec.</a>
29
 *
30 31 32 33 34
 */
public class CipherSuite {

    /**
     * true if this cipher suite is supported
35
     */
36 37 38 39 40 41 42
    boolean supported = true;

    /**
     * cipher suite key exchange
     */
    final int keyExchange;

43
    /**
44
     * algorithm used for authentication ("RSA", "DSA", "DH", null for anonymous)
45 46 47
     */
    final String authType;

48 49 50 51
    /**
     * cipher
     */
    final String cipherName;
52

53 54 55 56 57 58
    /**
     * Cipher information
     */
    final int keyMaterial;
    final int expandedKeyMaterial;
    final int effectiveKeyBytes;
59
    final int ivSize;
60
    final private int blockSize;
61

62 63 64 65 66
    // cipher suite code
    private final byte[] cipherSuiteCode;

    // cipher suite name
    private final String name;
67

68 69 70 71 72
    // true if cipher suite is exportable
    private final boolean isExportable;

    // Hash algorithm
    final private String hashName;
73

74 75
    // MAC algorithm
    final private String hmacName;
76

77 78 79
    // Hash size
    final private int hashSize;

80 81 82 83 84 85
    /**
     * Whether this cipher needs BEAST mitigation or not. This enabled for CBC
     * mode ciphers.
     */
    final private boolean needInitialRecordSplit;

86 87 88
    /**
     * key exchange values
     */
89 90 91 92 93 94
    static final int KEY_EXCHANGE_RSA = 1;
    static final int KEY_EXCHANGE_RSA_EXPORT = 2;
    static final int KEY_EXCHANGE_DHE_DSS = 3;
    static final int KEY_EXCHANGE_DHE_DSS_EXPORT = 4;
    static final int KEY_EXCHANGE_DHE_RSA = 5;
    static final int KEY_EXCHANGE_DHE_RSA_EXPORT = 6;
95 96 97 98
    // BEGIN android-removed
    // static final int KEY_EXCHANGE_DH_DSS = 7;
    // static final int KEY_EXCHANGE_DH_RSA = 8;
    // END android-removed
99 100
    static final int KEY_EXCHANGE_DH_anon = 9;
    static final int KEY_EXCHANGE_DH_anon_EXPORT = 10;
101 102 103 104 105 106 107 108 109
    // BEGIN android-removed
    // static final int KEY_EXCHANGE_DH_DSS_EXPORT = 11;
    // static final int KEY_EXCHANGE_DH_RSA_EXPORT = 12;
    // END android-removed
    static final int KEY_EXCHANGE_ECDH_ECDSA = 13;
    static final int KEY_EXCHANGE_ECDHE_ECDSA = 14;
    static final int KEY_EXCHANGE_ECDH_RSA = 15;
    static final int KEY_EXCHANGE_ECDHE_RSA = 16;
    static final int KEY_EXCHANGE_ECDH_anon = 17;
110 111 112 113

    /**
     * TLS cipher suite codes
     */
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
    static final byte[] CODE_SSL_NULL_WITH_NULL_NULL = { 0x00, 0x00 };
    static final byte[] CODE_SSL_RSA_WITH_NULL_MD5 = { 0x00, 0x01 };
    static final byte[] CODE_SSL_RSA_WITH_NULL_SHA = { 0x00, 0x02 };
    static final byte[] CODE_SSL_RSA_EXPORT_WITH_RC4_40_MD5 = { 0x00, 0x03 };
    static final byte[] CODE_SSL_RSA_WITH_RC4_128_MD5 = { 0x00, 0x04 };
    static final byte[] CODE_SSL_RSA_WITH_RC4_128_SHA = { 0x00, 0x05 };
    static final byte[] CODE_SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = { 0x00, 0x06 };
    // BEGIN android-removed
    // static final byte[] CODE_TLS_RSA_WITH_IDEA_CBC_SHA = { 0x00, 0x07 };
    // END android-removed
    static final byte[] CODE_SSL_RSA_EXPORT_WITH_DES40_CBC_SHA = { 0x00, 0x08 };
    static final byte[] CODE_SSL_RSA_WITH_DES_CBC_SHA = { 0x00, 0x09 };
    static final byte[] CODE_SSL_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00, 0x0A };
    // BEGIN android-removed
    // static final byte[] CODE_SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = { 0x00, 0x0B };
    // static final byte[] CODE_SSL_DH_DSS_WITH_DES_CBC_SHA = { 0x00, 0x0C };
    // static final byte[] CODE_SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA = { 0x00, 0x0D };
    // static final byte[] CODE_SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = { 0x00, 0x0E };
    // static final byte[] CODE_SSL_DH_RSA_WITH_DES_CBC_SHA = { 0x00, 0x0F };
    // static final byte[] CODE_SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00, 0x10 };
    // END android-removed
    static final byte[] CODE_SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = { 0x00, 0x11 };
    static final byte[] CODE_SSL_DHE_DSS_WITH_DES_CBC_SHA = { 0x00, 0x12 };
    static final byte[] CODE_SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA = { 0x00, 0x13 };
    static final byte[] CODE_SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = { 0x00, 0x14 };
    static final byte[] CODE_SSL_DHE_RSA_WITH_DES_CBC_SHA = { 0x00, 0x15 };
    static final byte[] CODE_SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00, 0x16 };
    static final byte[] CODE_SSL_DH_anon_EXPORT_WITH_RC4_40_MD5 = { 0x00, 0x17 };
    static final byte[] CODE_SSL_DH_anon_WITH_RC4_128_MD5 = { 0x00, 0x18 };
    static final byte[] CODE_SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA = { 0x00, 0x19 };
    static final byte[] CODE_SSL_DH_anon_WITH_DES_CBC_SHA = { 0x00, 0x1A };
    static final byte[] CODE_SSL_DH_anon_WITH_3DES_EDE_CBC_SHA = { 0x00, 0x1B };

    // AES Cipher Suites from RFC 3268 - http://www.ietf.org/rfc/rfc3268.txt
    static final byte[] CODE_TLS_RSA_WITH_AES_128_CBC_SHA = { 0x00, 0x2F };
    //static final byte[] CODE_TLS_DH_DSS_WITH_AES_128_CBC_SHA = { 0x00, 0x30 };
    //static final byte[] CODE_TLS_DH_RSA_WITH_AES_128_CBC_SHA = { 0x00, 0x31 };
    static final byte[] CODE_TLS_DHE_DSS_WITH_AES_128_CBC_SHA = { 0x00, 0x32 };
    static final byte[] CODE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA = { 0x00, 0x33 };
    static final byte[] CODE_TLS_DH_anon_WITH_AES_128_CBC_SHA = { 0x00, 0x34 };
    static final byte[] CODE_TLS_RSA_WITH_AES_256_CBC_SHA = { 0x00, 0x35 };
    //static final byte[] CODE_TLS_DH_DSS_WITH_AES_256_CBC_SHA = { 0x00, 0x36 };
    //static final byte[] CODE_TLS_DH_RSA_WITH_AES_256_CBC_SHA = { 0x00, 0x37 };
    static final byte[] CODE_TLS_DHE_DSS_WITH_AES_256_CBC_SHA = { 0x00, 0x38 };
    static final byte[] CODE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA = { 0x00, 0x39 };
    static final byte[] CODE_TLS_DH_anon_WITH_AES_256_CBC_SHA = { 0x00, 0x3A };

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
    // EC Cipher Suites from RFC 4492 - http://www.ietf.org/rfc/rfc4492.txt
    static final byte[] CODE_TLS_ECDH_ECDSA_WITH_NULL_SHA = { (byte) 0xc0, 0x01};
    static final byte[] CODE_TLS_ECDH_ECDSA_WITH_RC4_128_SHA = { (byte) 0xc0, 0x02};
    static final byte[] CODE_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = { (byte) 0xc0, 0x03};
    static final byte[] CODE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = { (byte) 0xc0, 0x04};
    static final byte[] CODE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = { (byte) 0xc0, 0x05};
    static final byte[] CODE_TLS_ECDHE_ECDSA_WITH_NULL_SHA = { (byte) 0xc0, 0x06};
    static final byte[] CODE_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = { (byte) 0xc0, 0x07};
    static final byte[] CODE_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = { (byte) 0xc0, 0x08};
    static final byte[] CODE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = { (byte) 0xc0, 0x09};
    static final byte[] CODE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = { (byte) 0xc0, 0x0A};
    static final byte[] CODE_TLS_ECDH_RSA_WITH_NULL_SHA = { (byte) 0xc0, 0x0B};
    static final byte[] CODE_TLS_ECDH_RSA_WITH_RC4_128_SHA = { (byte) 0xc0, 0x0C};
    static final byte[] CODE_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = { (byte) 0xc0, 0x0D};
    static final byte[] CODE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = { (byte) 0xc0, 0x0E};
    static final byte[] CODE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = { (byte) 0xc0, 0x0F};
    static final byte[] CODE_TLS_ECDHE_RSA_WITH_NULL_SHA = { (byte) 0xc0, 0x10};
    static final byte[] CODE_TLS_ECDHE_RSA_WITH_RC4_128_SHA = { (byte) 0xc0, 0x11};
    static final byte[] CODE_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = { (byte) 0xc0, 0x12};
    static final byte[] CODE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = { (byte) 0xc0, 0x13};
    static final byte[] CODE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = { (byte) 0xc0, 0x14};
    static final byte[] CODE_TLS_ECDH_anon_WITH_NULL_SHA = { (byte) 0xc0, 0x15};
    static final byte[] CODE_TLS_ECDH_anon_WITH_RC4_128_SHA = { (byte) 0xc0, 0x16};
    static final byte[] CODE_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = { (byte) 0xc0, 0x17};
    static final byte[] CODE_TLS_ECDH_anon_WITH_AES_128_CBC_SHA = { (byte) 0xc0, 0x18};
    static final byte[] CODE_TLS_ECDH_anon_WITH_AES_256_CBC_SHA = { (byte) 0xc0, 0x19};

188
    static final CipherSuite SSL_NULL_WITH_NULL_NULL = new CipherSuite(
189
            "SSL_NULL_WITH_NULL_NULL", true, 0, null, null, null,
190
            CODE_SSL_NULL_WITH_NULL_NULL);
191

192
    static final CipherSuite SSL_RSA_WITH_NULL_MD5 = new CipherSuite(
193
            "SSL_RSA_WITH_NULL_MD5", true, KEY_EXCHANGE_RSA, "RSA", null, "MD5",
194
            CODE_SSL_RSA_WITH_NULL_MD5);
195

196
    static final CipherSuite SSL_RSA_WITH_NULL_SHA = new CipherSuite(
197
            "SSL_RSA_WITH_NULL_SHA", true, KEY_EXCHANGE_RSA, "RSA", null, "SHA",
198
            CODE_SSL_RSA_WITH_NULL_SHA);
199

200
    static final CipherSuite SSL_RSA_EXPORT_WITH_RC4_40_MD5 = new CipherSuite(
201
            "SSL_RSA_EXPORT_WITH_RC4_40_MD5", true, KEY_EXCHANGE_RSA_EXPORT,
202
            "RSA", "RC4_40", "MD5", CODE_SSL_RSA_EXPORT_WITH_RC4_40_MD5);
203

204
    static final CipherSuite SSL_RSA_WITH_RC4_128_MD5 = new CipherSuite(
205
            "SSL_RSA_WITH_RC4_128_MD5", false, KEY_EXCHANGE_RSA, "RSA", "RC4_128",
206
            "MD5", CODE_SSL_RSA_WITH_RC4_128_MD5);
207

208
    static final CipherSuite SSL_RSA_WITH_RC4_128_SHA = new CipherSuite(
209
            "SSL_RSA_WITH_RC4_128_SHA", false, KEY_EXCHANGE_RSA, "RSA", "RC4_128",
210
            "SHA", CODE_SSL_RSA_WITH_RC4_128_SHA);
211

212
    static final CipherSuite SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = new CipherSuite(
213
            "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5", true, KEY_EXCHANGE_RSA_EXPORT,
214
            "RSA", "RC2_CBC_40", "MD5", CODE_SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5);
215

216 217 218 219 220
    // BEGIN android-removed
    // static final CipherSuite TLS_RSA_WITH_IDEA_CBC_SHA = new CipherSuite(
    //         "TLS_RSA_WITH_IDEA_CBC_SHA", false, KEY_EXCHANGE_RSA, "RSA", "IDEA_CBC",
    //         "SHA", CODE_TLS_RSA_WITH_IDEA_CBC_SHA);
    // END android-removed
221

222
    static final CipherSuite SSL_RSA_EXPORT_WITH_DES40_CBC_SHA = new CipherSuite(
223
            "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA", true, KEY_EXCHANGE_RSA_EXPORT,
224
            "RSA", "DES40_CBC", "SHA", CODE_SSL_RSA_EXPORT_WITH_DES40_CBC_SHA);
225

226
    static final CipherSuite SSL_RSA_WITH_DES_CBC_SHA = new CipherSuite(
227
            "SSL_RSA_WITH_DES_CBC_SHA", false, KEY_EXCHANGE_RSA, "RSA", "DES_CBC",
228
            "SHA", CODE_SSL_RSA_WITH_DES_CBC_SHA);
229

230
    static final CipherSuite SSL_RSA_WITH_3DES_EDE_CBC_SHA = new CipherSuite(
231
            "SSL_RSA_WITH_3DES_EDE_CBC_SHA", false, KEY_EXCHANGE_RSA,
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
            "RSA", "3DES_EDE_CBC", "SHA", CODE_SSL_RSA_WITH_3DES_EDE_CBC_SHA);

    // BEGIN android-removed
    // static final CipherSuite SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = new CipherSuite(
    //         "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", true,
    //         KEY_EXCHANGE_DH_DSS_EXPORT, "DH", "DES40_CBC", "SHA",
    //         CODE_SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA);
    //
    // static final CipherSuite SSL_DH_DSS_WITH_DES_CBC_SHA = new CipherSuite(
    //         "SSL_DH_DSS_WITH_DES_CBC_SHA", false, KEY_EXCHANGE_DH_DSS,
    //         "DH", "DES_CBC", "SHA", CODE_SSL_DH_DSS_WITH_DES_CBC_SHA);
    //
    // static final CipherSuite SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA = new CipherSuite(
    //         "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA", false, KEY_EXCHANGE_DH_DSS,
    //         "DH", "3DES_EDE_CBC", "SHA", CODE_SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA);
    //
    // static final CipherSuite SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = new CipherSuite(
    //         "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", true,
    //         KEY_EXCHANGE_DH_RSA_EXPORT, "DH", "DES40_CBC", "SHA",
    //         CODE_SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA);
    //
    // static final CipherSuite SSL_DH_RSA_WITH_DES_CBC_SHA = new CipherSuite(
    //         "SSL_DH_RSA_WITH_DES_CBC_SHA", false, KEY_EXCHANGE_DH_RSA,
    //         "DH", "DES_CBC", "SHA", CODE_SSL_DH_RSA_WITH_DES_CBC_SHA);
    //
    // static final CipherSuite SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA = new CipherSuite(
    //         "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA", false, KEY_EXCHANGE_DH_RSA,
    //         "DH", "3DES_EDE_CBC", "SHA", CODE_SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA);
    // END android-removed

    static final CipherSuite SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = new CipherSuite(
263
            "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", true,
264
            KEY_EXCHANGE_DHE_DSS_EXPORT, "DSA", "DES40_CBC", "SHA",
265
            CODE_SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA);
266

267
    static final CipherSuite SSL_DHE_DSS_WITH_DES_CBC_SHA = new CipherSuite(
268
            "SSL_DHE_DSS_WITH_DES_CBC_SHA", false, KEY_EXCHANGE_DHE_DSS,
269
            "DSA", "DES_CBC", "SHA", CODE_SSL_DHE_DSS_WITH_DES_CBC_SHA);
270

271
    static final CipherSuite SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA = new CipherSuite(
272
            "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA", false, KEY_EXCHANGE_DHE_DSS,
273
            "DSA", "3DES_EDE_CBC", "SHA", CODE_SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA);
274

275
    static final CipherSuite SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = new CipherSuite(
276
            "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", true,
277
            KEY_EXCHANGE_DHE_RSA_EXPORT, "RSA", "DES40_CBC", "SHA",
278
            CODE_SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA);
279

280
    static final CipherSuite SSL_DHE_RSA_WITH_DES_CBC_SHA = new CipherSuite(
281
            "SSL_DHE_RSA_WITH_DES_CBC_SHA", false, KEY_EXCHANGE_DHE_RSA,
282
            "RSA", "DES_CBC", "SHA", CODE_SSL_DHE_RSA_WITH_DES_CBC_SHA);
283

284
    static final CipherSuite SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA = new CipherSuite(
285
            "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA", false, KEY_EXCHANGE_DHE_RSA,
286
            "RSA", "3DES_EDE_CBC", "SHA", CODE_SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA);
287

288
    static final CipherSuite SSL_DH_anon_EXPORT_WITH_RC4_40_MD5 = new CipherSuite(
289
            "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5", true,
290
            KEY_EXCHANGE_DH_anon_EXPORT, "DH", "RC4_40", "MD5",
291
            CODE_SSL_DH_anon_EXPORT_WITH_RC4_40_MD5);
292

293
    static final CipherSuite SSL_DH_anon_WITH_RC4_128_MD5 = new CipherSuite(
294
            "SSL_DH_anon_WITH_RC4_128_MD5", false, KEY_EXCHANGE_DH_anon,
295
            "DH", "RC4_128", "MD5", CODE_SSL_DH_anon_WITH_RC4_128_MD5);
296

297
    static final CipherSuite SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA = new CipherSuite(
298
            "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA", true,
299
            KEY_EXCHANGE_DH_anon_EXPORT, "DH", "DES40_CBC", "SHA",
300
            CODE_SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA);
301

302
    static final CipherSuite SSL_DH_anon_WITH_DES_CBC_SHA = new CipherSuite(
303
            "SSL_DH_anon_WITH_DES_CBC_SHA", false, KEY_EXCHANGE_DH_anon,
304
            "DH", "DES_CBC", "SHA", CODE_SSL_DH_anon_WITH_DES_CBC_SHA);
305

306
    static final CipherSuite SSL_DH_anon_WITH_3DES_EDE_CBC_SHA = new CipherSuite(
307
            "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA", false, KEY_EXCHANGE_DH_anon,
308 309 310 311 312 313 314
            "DH", "3DES_EDE_CBC", "SHA", CODE_SSL_DH_anon_WITH_3DES_EDE_CBC_SHA);

    static final CipherSuite TLS_RSA_WITH_AES_128_CBC_SHA
            = new CipherSuite("TLS_RSA_WITH_AES_128_CBC_SHA",
                              false,
                              KEY_EXCHANGE_RSA,
                              "RSA",
315
                              "AES_128_CBC",
316 317 318 319 320 321 322
                              "SHA",
                              CODE_TLS_RSA_WITH_AES_128_CBC_SHA);
    static final CipherSuite TLS_DHE_DSS_WITH_AES_128_CBC_SHA
            = new CipherSuite("TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
                              false,
                              KEY_EXCHANGE_DHE_DSS,
                              "DSA",
323
                              "AES_128_CBC",
324 325 326 327 328 329 330
                              "SHA",
                              CODE_TLS_DHE_DSS_WITH_AES_128_CBC_SHA);
    static final CipherSuite TLS_DHE_RSA_WITH_AES_128_CBC_SHA
            = new CipherSuite("TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
                              false,
                              KEY_EXCHANGE_DHE_RSA,
                              "RSA",
331
                              "AES_128_CBC",
332 333 334 335 336 337 338
                              "SHA",
                              CODE_TLS_DHE_RSA_WITH_AES_128_CBC_SHA);
    static final CipherSuite TLS_DH_anon_WITH_AES_128_CBC_SHA
            = new CipherSuite("TLS_DH_anon_WITH_AES_128_CBC_SHA",
                              false,
                              KEY_EXCHANGE_DH_anon,
                              "DH",
339
                              "AES_128_CBC",
340 341 342 343 344 345 346
                              "SHA",
                              CODE_TLS_DH_anon_WITH_AES_128_CBC_SHA);
    static final CipherSuite TLS_RSA_WITH_AES_256_CBC_SHA
            = new CipherSuite("TLS_RSA_WITH_AES_256_CBC_SHA",
                              false,
                              KEY_EXCHANGE_RSA,
                              "RSA",
347
                              "AES_256_CBC",
348 349 350 351 352 353 354
                              "SHA",
                              CODE_TLS_RSA_WITH_AES_256_CBC_SHA);
    static final CipherSuite TLS_DHE_DSS_WITH_AES_256_CBC_SHA
            = new CipherSuite("TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
                              false,
                              KEY_EXCHANGE_DHE_DSS,
                              "DSA",
355
                              "AES_256_CBC",
356 357 358 359 360 361 362
                              "SHA",
                              CODE_TLS_DHE_DSS_WITH_AES_256_CBC_SHA);
    static final CipherSuite TLS_DHE_RSA_WITH_AES_256_CBC_SHA
            = new CipherSuite("TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
                              false,
                              KEY_EXCHANGE_DHE_RSA,
                              "RSA",
363
                              "AES_256_CBC",
364 365 366 367 368 369 370
                              "SHA",
                              CODE_TLS_DHE_RSA_WITH_AES_256_CBC_SHA);
    static final CipherSuite TLS_DH_anon_WITH_AES_256_CBC_SHA
            = new CipherSuite("TLS_DH_anon_WITH_AES_256_CBC_SHA",
                              false,
                              KEY_EXCHANGE_DH_anon,
                              "DH",
371
                              "AES_256_CBC",
372 373
                              "SHA",
                              CODE_TLS_DH_anon_WITH_AES_256_CBC_SHA);
374

375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577
    static final CipherSuite TLS_ECDH_ECDSA_WITH_NULL_SHA
            = new CipherSuite("TLS_ECDH_ECDSA_WITH_NULL_SHA",
                              false,
                              KEY_EXCHANGE_ECDH_ECDSA,
                              "EC",
                              null,
                              "SHA",
                              CODE_TLS_ECDH_ECDSA_WITH_NULL_SHA);
    static final CipherSuite TLS_ECDH_ECDSA_WITH_RC4_128_SHA
            = new CipherSuite("TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
                              false,
                              KEY_EXCHANGE_ECDH_ECDSA,
                              "EC",
                              "RC4_128",
                              "SHA",
                              CODE_TLS_ECDH_ECDSA_WITH_RC4_128_SHA);
    static final CipherSuite TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
            = new CipherSuite("TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
                              false,
                              KEY_EXCHANGE_ECDH_ECDSA,
                              "EC",
                              "3DES_EDE_CBC",
                              "SHA",
                              CODE_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA);
    static final CipherSuite TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
            = new CipherSuite("TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
                              false,
                              KEY_EXCHANGE_ECDH_ECDSA,
                              "EC",
                              "AES_128_CBC",
                              "SHA",
                              CODE_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA);
    static final CipherSuite TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
            = new CipherSuite("TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
                              false,
                              KEY_EXCHANGE_ECDH_ECDSA,
                              "EC",
                              "AES_256_CBC",
                              "SHA",
                              CODE_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA);
    static final CipherSuite TLS_ECDHE_ECDSA_WITH_NULL_SHA
            = new CipherSuite("TLS_ECDHE_ECDSA_WITH_NULL_SHA",
                              false,
                              KEY_EXCHANGE_ECDHE_ECDSA,
                              "EC",
                              null,
                              "SHA",
                              CODE_TLS_ECDHE_ECDSA_WITH_NULL_SHA);
    static final CipherSuite TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
            = new CipherSuite("TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
                              false,
                              KEY_EXCHANGE_ECDHE_ECDSA,
                              "EC",
                              "RC4_128",
                              "SHA",
                              CODE_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA);
    static final CipherSuite TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
            = new CipherSuite("TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
                              false,
                              KEY_EXCHANGE_ECDHE_ECDSA,
                              "EC",
                              "3DES_EDE_CBC",
                              "SHA",
                              CODE_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA);
    static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
            = new CipherSuite("TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
                              false,
                              KEY_EXCHANGE_ECDHE_ECDSA,
                              "EC",
                              "AES_128_CBC",
                              "SHA",
                              CODE_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA);
    static final CipherSuite TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
            = new CipherSuite("TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
                              false,
                              KEY_EXCHANGE_ECDHE_ECDSA,
                              "EC",
                              "AES_256_CBC",
                              "SHA",
                              CODE_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA);
    static final CipherSuite TLS_ECDH_RSA_WITH_NULL_SHA
            = new CipherSuite("TLS_ECDH_RSA_WITH_NULL_SHA",
                              false,
                              KEY_EXCHANGE_ECDH_RSA,
                              "EC",
                              null,
                              "SHA",
                              CODE_TLS_ECDH_RSA_WITH_NULL_SHA);
    static final CipherSuite TLS_ECDH_RSA_WITH_RC4_128_SHA
            = new CipherSuite("TLS_ECDH_RSA_WITH_RC4_128_SHA",
                              false,
                              KEY_EXCHANGE_ECDH_RSA,
                              "EC",
                              "RC4_128",
                              "SHA",
                              CODE_TLS_ECDH_RSA_WITH_RC4_128_SHA);
    static final CipherSuite TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
            = new CipherSuite("TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
                              false,
                              KEY_EXCHANGE_ECDH_RSA,
                              "EC",
                              "3DES_EDE_CBC",
                              "SHA",
                              CODE_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA);
    static final CipherSuite TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
            = new CipherSuite("TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
                              false,
                              KEY_EXCHANGE_ECDH_RSA,
                              "EC",
                              "AES_128_CBC",
                              "SHA",
                              CODE_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA);
    static final CipherSuite TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
            = new CipherSuite("TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
                              false,
                              KEY_EXCHANGE_ECDH_RSA,
                              "EC",
                              "AES_256_CBC",
                              "SHA",
                              CODE_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA);
    static final CipherSuite TLS_ECDHE_RSA_WITH_NULL_SHA
            = new CipherSuite("TLS_ECDHE_RSA_WITH_NULL_SHA",
                              false,
                              KEY_EXCHANGE_ECDHE_RSA,
                              "EC",
                              null,
                              "SHA",
                              CODE_TLS_ECDHE_RSA_WITH_NULL_SHA);
    static final CipherSuite TLS_ECDHE_RSA_WITH_RC4_128_SHA
            = new CipherSuite("TLS_ECDHE_RSA_WITH_RC4_128_SHA",
                              false,
                              KEY_EXCHANGE_ECDHE_RSA,
                              "EC",
                              "RC4_128",
                              "SHA",
                              CODE_TLS_ECDHE_RSA_WITH_RC4_128_SHA);
    static final CipherSuite TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
            = new CipherSuite("TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
                              false,
                              KEY_EXCHANGE_ECDHE_RSA,
                              "EC",
                              "3DES_EDE_CBC",
                              "SHA",
                              CODE_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA);
    static final CipherSuite TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
            = new CipherSuite("TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
                              false,
                              KEY_EXCHANGE_ECDHE_RSA,
                              "EC",
                              "AES_128_CBC",
                              "SHA",
                              CODE_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
    static final CipherSuite TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
            = new CipherSuite("TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
                              false,
                              KEY_EXCHANGE_ECDHE_RSA,
                              "EC",
                              "AES_256_CBC",
                              "SHA",
                              CODE_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA);
    static final CipherSuite TLS_ECDH_anon_WITH_NULL_SHA
            = new CipherSuite("TLS_ECDH_anon_WITH_NULL_SHA",
                              false,
                              KEY_EXCHANGE_ECDH_anon,
                              "EC",
                              null,
                              "SHA",
                              CODE_TLS_ECDH_anon_WITH_NULL_SHA);
    static final CipherSuite TLS_ECDH_anon_WITH_RC4_128_SHA
            = new CipherSuite("TLS_ECDH_anon_WITH_RC4_128_SHA",
                              false,
                              KEY_EXCHANGE_ECDH_anon,
                              "EC",
                              "RC4_128",
                              "SHA",
                              CODE_TLS_ECDH_anon_WITH_RC4_128_SHA);
    static final CipherSuite TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA
            = new CipherSuite("TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
                              false,
                              KEY_EXCHANGE_ECDH_anon,
                              "EC",
                              "3DES_EDE_CBC",
                              "SHA",
                              CODE_TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA);
    static final CipherSuite TLS_ECDH_anon_WITH_AES_128_CBC_SHA
            = new CipherSuite("TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
                              false,
                              KEY_EXCHANGE_ECDH_anon,
                              "EC",
                              "AES_128_CBC",
                              "SHA",
                              CODE_TLS_ECDH_anon_WITH_AES_128_CBC_SHA);
    static final CipherSuite TLS_ECDH_anon_WITH_AES_256_CBC_SHA
            = new CipherSuite("TLS_ECDH_anon_WITH_AES_256_CBC_SHA",
                              false,
                              KEY_EXCHANGE_ECDH_anon,
                              "EC",
                              "AES_256_CBC",
                              "SHA",
                              CODE_TLS_ECDH_anon_WITH_AES_256_CBC_SHA);

    // arrays for quick access to cipher suite by code
    private static final CipherSuite[] SUITES_BY_CODE_0x00 = {
578
        // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml
579 580 581 582 583 584
        SSL_NULL_WITH_NULL_NULL,                          // { 0x00, 0x00 };
        SSL_RSA_WITH_NULL_MD5,                            // { 0x00, 0x01 };
        SSL_RSA_WITH_NULL_SHA,                            // { 0x00, 0x02 };
        SSL_RSA_EXPORT_WITH_RC4_40_MD5,                   // { 0x00, 0x03 };
        SSL_RSA_WITH_RC4_128_MD5,                         // { 0x00, 0x04 };
        SSL_RSA_WITH_RC4_128_SHA,                         // { 0x00, 0x05 };
585
        // BEGIN android-changed
586 587
        null, // SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,      // { 0x00, 0x06 };
        null, // TLS_RSA_WITH_IDEA_CBC_SHA,               // { 0x00, 0x07 };
588
        // END android-changed
589 590 591
        SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,                // { 0x00, 0x08 };
        SSL_RSA_WITH_DES_CBC_SHA,                         // { 0x00, 0x09 };
        SSL_RSA_WITH_3DES_EDE_CBC_SHA,                    // { 0x00, 0x0a };
592
        // BEGIN android-changed
593 594 595 596 597 598
        null, // SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA     // { 0x00, 0x0b };
        null, // SSL_DH_DSS_WITH_DES_CBC_SHA,             // { 0x00, 0x0c };
        null, // SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,        // { 0x00, 0x0d };
        null, // SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,    // { 0x00, 0x0e };
        null, // SSL_DH_RSA_WITH_DES_CBC_SHA,             // { 0x00, 0x0f };
        null, // SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,        // { 0x00, 0x10 };
599
        // END android-changed
600 601 602 603 604 605 606 607 608 609 610
        SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,            // { 0x00, 0x11 };
        SSL_DHE_DSS_WITH_DES_CBC_SHA,                     // { 0x00, 0x12 };
        SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,                // { 0x00, 0x13 };
        SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,            // { 0x00, 0x14 };
        SSL_DHE_RSA_WITH_DES_CBC_SHA,                     // { 0x00, 0x15 };
        SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,                // { 0x00, 0x16 };
        SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,               // { 0x00, 0x17 };
        SSL_DH_anon_WITH_RC4_128_MD5,                     // { 0x00, 0x18 };
        SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,            // { 0x00, 0x19 };
        SSL_DH_anon_WITH_DES_CBC_SHA,                     // { 0x00, 0x1A };
        SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,                // { 0x00, 0x1B };
611
        // BEGIN android-added
612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642
        null, // SSL_FORTEZZA_KEA_WITH_NULL_SHA           // { 0x00, 0x1C };
        null, // SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA   // { 0x00, 0x1D };
        null, // TLS_KRB5_WITH_DES_CBC_SHA                // { 0x00, 0x1E };
        null, // TLS_KRB5_WITH_3DES_EDE_CBC_SHA           // { 0x00, 0x1F };
        null, // TLS_KRB5_WITH_RC4_128_SHA                // { 0x00, 0x20 };
        null, // TLS_KRB5_WITH_IDEA_CBC_SHA               // { 0x00, 0x21 };
        null, // TLS_KRB5_WITH_DES_CBC_MD5                // { 0x00, 0x22 };
        null, // TLS_KRB5_WITH_3DES_EDE_CBC_MD5           // { 0x00, 0x23 };
        null, // TLS_KRB5_WITH_RC4_128_MD5                // { 0x00, 0x24 };
        null, // TLS_KRB5_WITH_IDEA_CBC_MD5               // { 0x00, 0x25 };
        null, // TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA      // { 0x00, 0x26 };
        null, // TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA      // { 0x00, 0x27 };
        null, // TLS_KRB5_EXPORT_WITH_RC4_40_SHA          // { 0x00, 0x28 };
        null, // TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5      // { 0x00, 0x29 };
        null, // TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5      // { 0x00, 0x2A };
        null, // TLS_KRB5_EXPORT_WITH_RC4_40_MD5          // { 0x00, 0x2B };
        null, // TLS_PSK_WITH_NULL_SHA                    // { 0x00, 0x2C };
        null, // TLS_DHE_PSK_WITH_NULL_SHA                // { 0x00, 0x2D };
        null, // TLS_RSA_PSK_WITH_NULL_SHA                // { 0x00, 0x2E };
        TLS_RSA_WITH_AES_128_CBC_SHA,                     // { 0x00, 0x2F };
        null, // TLS_DH_DSS_WITH_AES_128_CBC_SHA          // { 0x00, 0x30 };
        null, // TLS_DH_RSA_WITH_AES_128_CBC_SHA          // { 0x00, 0x31 };
        TLS_DHE_DSS_WITH_AES_128_CBC_SHA,                 // { 0x00, 0x32 };
        TLS_DHE_RSA_WITH_AES_128_CBC_SHA,                 // { 0x00, 0x33 };
        TLS_DH_anon_WITH_AES_128_CBC_SHA,                 // { 0x00, 0x34 };
        TLS_RSA_WITH_AES_256_CBC_SHA,                     // { 0x00, 0x35 };
        null, // TLS_DH_DSS_WITH_AES_256_CBC_SHA,         // { 0x00, 0x36 };
        null, // TLS_DH_RSA_WITH_AES_256_CBC_SHA,         // { 0x00, 0x37 };
        TLS_DHE_DSS_WITH_AES_256_CBC_SHA,                 // { 0x00, 0x38 };
        TLS_DHE_RSA_WITH_AES_256_CBC_SHA,                 // { 0x00, 0x39 };
        TLS_DH_anon_WITH_AES_256_CBC_SHA,                 // { 0x00, 0x3A };
643 644
        // END android-added
    };
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706
    private static final CipherSuite[] SUITES_BY_CODE_0xc0 = {
        null,                                             // { 0xc0, 0x00};
        TLS_ECDH_ECDSA_WITH_NULL_SHA,                     // { 0xc0, 0x01};
        TLS_ECDH_ECDSA_WITH_RC4_128_SHA,                  // { 0xc0, 0x02};
        TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,             // { 0xc0, 0x03};
        TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,              // { 0xc0, 0x04};
        TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,              // { 0xc0, 0x05};
        TLS_ECDHE_ECDSA_WITH_NULL_SHA,                    // { 0xc0, 0x06};
        TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,                 // { 0xc0, 0x07};
        TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,            // { 0xc0, 0x08};
        TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,             // { 0xc0, 0x09};
        TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,             // { 0xc0, 0x0A};
        TLS_ECDH_RSA_WITH_NULL_SHA,                       // { 0xc0, 0x0B};
        TLS_ECDH_RSA_WITH_RC4_128_SHA,                    // { 0xc0, 0x0C};
        TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,               // { 0xc0, 0x0D};
        TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,                // { 0xc0, 0x0E};
        TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,                // { 0xc0, 0x0F};
        TLS_ECDHE_RSA_WITH_NULL_SHA,                      // { 0xc0, 0x10};
        TLS_ECDHE_RSA_WITH_RC4_128_SHA,                   // { 0xc0, 0x11};
        TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,              // { 0xc0, 0x12};
        TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,               // { 0xc0, 0x13};
        TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,               // { 0xc0, 0x14};
        TLS_ECDH_anon_WITH_NULL_SHA,                      // { 0xc0, 0x15};
        TLS_ECDH_anon_WITH_RC4_128_SHA,                   // { 0xc0, 0x16};
        TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA,              // { 0xc0, 0x17};
        TLS_ECDH_anon_WITH_AES_128_CBC_SHA,               // { 0xc0, 0x18};
        TLS_ECDH_anon_WITH_AES_256_CBC_SHA,               // { 0xc0, 0x19};
        // TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA,             // { 0xc0, 0x1A};
        // TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA,         // { 0xc0, 0x1B};
        // TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA,         // { 0xc0, 0x1C};
        // TLS_SRP_SHA_WITH_AES_128_CBC_SHA,              // { 0xc0, 0x1D};
        // TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA,          // { 0xc0, 0x1E};
        // TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA,          // { 0xc0, 0x1F};
        // TLS_SRP_SHA_WITH_AES_256_CBC_SHA,              // { 0xc0, 0x20};
        // TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA,          // { 0xc0, 0x21};
        // TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA,          // { 0xc0, 0x22};
        // TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,       // { 0xc0, 0x23};
        // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,       // { 0xc0, 0x24};
        // TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,        // { 0xc0, 0x25};
        // TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,        // { 0xc0, 0x26};
        // TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,         // { 0xc0, 0x27};
        // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,         // { 0xc0, 0x28};
        // TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,          // { 0xc0, 0x29};
        // TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,          // { 0xc0, 0x2A};
        // TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,       // { 0xc0, 0x2B};
        // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,       // { 0xc0, 0x2C};
        // TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,        // { 0xc0, 0x2D};
        // TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,        // { 0xc0, 0x2E};
        // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,         // { 0xc0, 0x2F};
        // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,         // { 0xc0, 0x30};
        // TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,          // { 0xc0, 0x31};
        // TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,          // { 0xc0, 0x32};
        // TLS_ECDHE_PSK_WITH_RC4_128_SHA,                // { 0xc0, 0x33};
        // TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA,           // { 0xc0, 0x34};
        // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,            // { 0xc0, 0x35};
        // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,            // { 0xc0, 0x36};
        // TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,         // { 0xc0, 0x37};
        // TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,         // { 0xc0, 0x38};
        // TLS_ECDHE_PSK_WITH_NULL_SHA,                   // { 0xc0, 0x39};
        // TLS_ECDHE_PSK_WITH_NULL_SHA256,                // { 0xc0, 0x3A};
        // TLS_ECDHE_PSK_WITH_NULL_SHA384,                // { 0xc0, 0x3B};
    };
707

708
    // hash for quick access to cipher suite by name
709
    private static final Hashtable<String, CipherSuite> SUITES_BY_NAME;
710 711

    /**
712
     * array of supported cipher suites.
713
     * Set of supported suites is defined at the moment provider's start
714
     */
715 716
    //  TODO Dynamically supported suites: new providers may be dynamically
    //  added/removed and the set of supported suites may be changed
717
    static final CipherSuite[] SUPPORTED_CIPHER_SUITES;
718 719

    /**
720
     * array of supported cipher suites names
721
     */
722
    static final String[] SUPPORTED_CIPHER_SUITE_NAMES;
723 724

    /**
725
     * default cipher suites
726
     */
727
    static final CipherSuite[] DEFAULT_CIPHER_SUITES;
728

729
    static {
730
        SUITES_BY_NAME = new Hashtable<String, CipherSuite>();
731 732 733
        int count_0x00 = registerCipherSuitesByCode(SUITES_BY_CODE_0x00);
        int count_0xc0 = registerCipherSuitesByCode(SUITES_BY_CODE_0xc0);
        int count = count_0x00 + count_0xc0;
734 735
        SUPPORTED_CIPHER_SUITES = new CipherSuite[count];
        SUPPORTED_CIPHER_SUITE_NAMES = new String[count];
736 737
        registerSupportedCipherSuites(0, SUITES_BY_CODE_0x00);
        registerSupportedCipherSuites(count_0x00, SUITES_BY_CODE_0xc0);
738

739 740 741 742 743 744
        // The default list of cipher suites is a trade-off between what we'd like to use and what
        // servers currently support. We strive to be secure enough by default. We thus avoid
        // unacceptably weak suites (e.g., those with bulk cipher secret key shorter than 80 bits),
        // while maintaining the capability to connect to the majority of servers.
        //
        // Cipher suites are listed in preference order (favorite choice first) of the client.
745 746 747 748 749 750 751 752 753 754 755
        // However, servers are not required to honor the order. The key rules governing the
        // preference order are:
        // * Prefer Forward Secrecy (i.e., cipher suites that use ECDHE and DHE for key agreement).
        // * Prefer AES to RC4 whose foundations are a bit shaky. See
        //   http://www.isg.rhul.ac.uk/tls/. BEAST and Lucky13 mitigations are enabled.
        // * Prefer AES_128+ and RC4_128 to 3DES_EDE. The effective bulk encryption key length of
        //   3DES_EDE is reduced from 168 to only 112 bits by meet-in-the-middle attack.
        // * Prefer 128-bit bulk encryption to 256-bit one, because 128-bit is safe enough while
        //   consuming less CPU/time/energy.
        // * Prefer HMAC-SHA to HMAC-MD5. Although HMAC-MD5 is not yet broken, the foundations are
        //   much more shaky that those of HMAC-SHA. See http://tools.ietf.org/html/rfc6151.
756 757 758
        //
        // NOTE: Removing cipher suites from this list needs to be done with caution, because this
        // may prevent apps from connecting to servers they were previously able to connect to.
759
        CipherSuite[] defaultCipherSuites = {
760
                TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
761
                TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
762
                TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
763
                TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
764 765
                TLS_RSA_WITH_AES_128_CBC_SHA,
                TLS_RSA_WITH_AES_256_CBC_SHA,
766
                SSL_RSA_WITH_RC4_128_SHA,
767
                SSL_RSA_WITH_RC4_128_MD5,
768
                SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
769 770
                SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
                SSL_RSA_WITH_3DES_EDE_CBC_SHA,
771 772
                };
        count = 0;
773 774
        for (int i = 0; i < defaultCipherSuites.length; i++) {
            if (defaultCipherSuites[i].supported) {
775 776 777
                count++;
            }
        }
778
        DEFAULT_CIPHER_SUITES = new CipherSuite[count];
779
        count = 0;
780 781 782
        for (int i = 0; i < defaultCipherSuites.length; i++) {
            if (defaultCipherSuites[i].supported) {
                DEFAULT_CIPHER_SUITES[count++] = defaultCipherSuites[i];
783 784 785
            }
        }
    }
786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817
    private static int registerCipherSuitesByCode(CipherSuite[] cipherSuites) {
        int count = 0;
        for (int i = 0; i < cipherSuites.length; i++) {
            if (cipherSuites[i] == SSL_NULL_WITH_NULL_NULL) {
                continue;
            }
            if (cipherSuites[i] == null) {
                continue;
            }
            SUITES_BY_NAME.put(cipherSuites[i].getName(), cipherSuites[i]);
            if (cipherSuites[i].supported) {
                count++;
            }
        }
        return count;
    }
    private static void registerSupportedCipherSuites(int offset, CipherSuite[] cipherSuites) {
        int count = offset;
        for (int i = 0; i < cipherSuites.length; i++) {
            if (cipherSuites[i] == SSL_NULL_WITH_NULL_NULL) {
                continue;
            }
            if (cipherSuites[i] == null) {
                continue;
            }
            if (cipherSuites[i].supported) {
                SUPPORTED_CIPHER_SUITES[count] = cipherSuites[i];
                SUPPORTED_CIPHER_SUITE_NAMES[count] = SUPPORTED_CIPHER_SUITES[count].getName();
                count++;
            }
        }
    }
818 819 820 821 822

    /**
     * Returns CipherSuite by name
     */
    public static CipherSuite getByName(String name) {
823
        return SUITES_BY_NAME.get(name);
824 825 826 827 828 829 830
    }

    /**
     * Returns CipherSuite based on TLS CipherSuite code
     * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., A.5. The CipherSuite</a>
     */
    public static CipherSuite getByCode(byte b1, byte b2) {
831 832 833 834 835
        int i1 = b1 & 0xff;
        int i2 = b2 & 0xff;
        CipherSuite cs = getCipherSuiteByCode(0, i1, i2);
        if (cs != null) {
            return cs;
836
        }
837 838
        return new CipherSuite("UNKNOWN_" + i1 + "_" + i2, false, 0, null,
                               null, null, new byte[] { b1, b2 });
839 840 841 842 843 844 845
    }

    /**
     * Returns CipherSuite based on V2CipherSpec code
     * as described in TLS 1.0 spec., E. Backward Compatibility With SSL
     */
    public static CipherSuite getByCode(byte b1, byte b2, byte b3) {
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867
        int i1 = b1 & 0xff;
        int i2 = b2 & 0xff;
        int i3 = b3 & 0xff;
        CipherSuite cs = getCipherSuiteByCode(i1, i2, i3);
        if (cs != null) {
            return cs;
        }
        return new CipherSuite("UNKNOWN_" + i1 + "_" + i2 + "_" + i3, false, 0,
                               null, null, null, new byte[] { b1, b2, b3 });
    }

    private static CipherSuite getCipherSuiteByCode(int i1, int i2, int i3) {
        CipherSuite[] cipherSuites;
        if (i1 == 0x00 && i2 == 0x00) {
            cipherSuites = SUITES_BY_CODE_0x00;
        } else if (i1 == 0x00 && i2 == 0xc0) {
            cipherSuites = SUITES_BY_CODE_0xc0;
        } else {
            return null;
        }
        if (i3 >= cipherSuites.length) {
            return null;
868
        }
869
        return cipherSuites[i3];
870 871 872 873 874
    }

    /**
     * Creates CipherSuite
     */
875
    private CipherSuite(String name, boolean isExportable, int keyExchange,
876
            String authType, String cipherName, String hash, byte[] code) {
877 878
        this.name = name;
        this.keyExchange = keyExchange;
879
        this.authType = authType;
880 881 882 883 884 885
        this.isExportable = isExportable;
        if (cipherName == null) {
            this.cipherName = null;
            keyMaterial = 0;
            expandedKeyMaterial = 0;
            effectiveKeyBytes = 0;
886
            ivSize = 0;
887
            blockSize = 0;
888
            needInitialRecordSplit = false;
889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904
        // BEGIN android-removed
        // } else if ("IDEA_CBC".equals(cipherName)) {
        //     this.cipherName = "IDEA/CBC/NoPadding";
        //     keyMaterial = 16;
        //     expandedKeyMaterial = 16;
        //     effectiveKeyBytes = 16;
        //     ivSize = 8;
        //     blockSize = 8;
        // } else if ("RC2_CBC_40".equals(cipherName)) {
        //     this.cipherName = "RC2/CBC/NoPadding";
        //     keyMaterial = 5;
        //     expandedKeyMaterial = 16;
        //     effectiveKeyBytes = 5;
        //     ivSize = 8;
        //     blockSize = 8;
        // END android-removed
905 906 907 908 909
        } else if ("RC4_40".equals(cipherName)) {
            this.cipherName = "RC4";
            keyMaterial = 5;
            expandedKeyMaterial = 16;
            effectiveKeyBytes = 5;
910
            ivSize = 0;
911
            blockSize = 0;
912
            needInitialRecordSplit = false;
913 914 915 916 917
        } else if ("RC4_128".equals(cipherName)) {
            this.cipherName = "RC4";
            keyMaterial = 16;
            expandedKeyMaterial = 16;
            effectiveKeyBytes = 16;
918
            ivSize = 0;
919
            blockSize = 0;
920
            needInitialRecordSplit = false;
921 922 923 924 925
        } else if ("DES40_CBC".equals(cipherName)) {
            this.cipherName = "DES/CBC/NoPadding";
            keyMaterial = 5;
            expandedKeyMaterial = 8;
            effectiveKeyBytes = 5;
926
            ivSize = 8;
927
            blockSize = 8;
928
            needInitialRecordSplit = true;
929 930 931 932 933
        } else if ("DES_CBC".equals(cipherName)) {
            this.cipherName = "DES/CBC/NoPadding";
            keyMaterial = 8;
            expandedKeyMaterial = 8;
            effectiveKeyBytes = 7;
934
            ivSize = 8;
935
            blockSize = 8;
936
            needInitialRecordSplit = true;
937 938 939 940 941
        } else if ("3DES_EDE_CBC".equals(cipherName)) {
            this.cipherName = "DESede/CBC/NoPadding";
            keyMaterial = 24;
            expandedKeyMaterial = 24;
            effectiveKeyBytes = 24;
942
            ivSize = 8;
943
            blockSize = 8;
944
            needInitialRecordSplit = true;
945
        } else if ("AES_128_CBC".equals(cipherName)) {
946 947 948 949 950 951
            this.cipherName = "AES/CBC/NoPadding";
            keyMaterial = 16;
            expandedKeyMaterial = 16;
            effectiveKeyBytes = 16;
            ivSize = 16;
            blockSize = 16;
952
            needInitialRecordSplit = true;
953
        } else if ("AES_256_CBC".equals(cipherName)) {
954 955 956 957 958 959
            this.cipherName = "AES/CBC/NoPadding";
            keyMaterial = 32;
            expandedKeyMaterial = 32;
            effectiveKeyBytes = 32;
            ivSize = 16;
            blockSize = 16;
960
            needInitialRecordSplit = true;
961 962 963 964 965
        } else {
            this.cipherName = cipherName;
            keyMaterial = 0;
            expandedKeyMaterial = 0;
            effectiveKeyBytes = 0;
966
            ivSize = 0;
967
            blockSize = 0;
968
            needInitialRecordSplit = false;
969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994
        }

        if ("MD5".equals(hash)) {
            this.hmacName = "HmacMD5";
            this.hashName = "MD5";
            hashSize = 16;
        } else if ("SHA".equals(hash)) {
            this.hmacName = "HmacSHA1";
            this.hashName = "SHA-1";
            hashSize = 20;
        } else {
            this.hmacName = null;
            this.hashName = null;
            hashSize = 0;
        }

        cipherSuiteCode = code;

        if (this.cipherName != null) {
            try {
                Cipher.getInstance(this.cipherName);
            } catch (GeneralSecurityException e) {
                supported = false;
            }
        }

995 996 997 998 999 1000
        // We define the Elliptic Curve cipher suites for use with
        // code shared by OpenSSL, but they are not supported by
        // SSLEngine or SSLSocket's built with SSLEngine.
        if (this.name.startsWith("TLS_EC")) {
            supported = false;
        }
1001 1002 1003 1004 1005 1006
    }

    /**
     * Returns true if cipher suite is anonymous
     */
    public boolean isAnonymous() {
1007
        if (keyExchange == KEY_EXCHANGE_DH_anon
1008 1009
                || keyExchange == KEY_EXCHANGE_DH_anon_EXPORT
                || keyExchange == KEY_EXCHANGE_ECDH_anon) {
1010 1011 1012 1013 1014 1015 1016 1017 1018
            return true;
        }
        return false;
    }

    /**
     * Returns array of supported CipherSuites
     */
    public static CipherSuite[] getSupported() {
1019
        return SUPPORTED_CIPHER_SUITES;
1020 1021 1022 1023 1024 1025
    }

    /**
     * Returns array of supported cipher suites names
     */
    public static String[] getSupportedCipherSuiteNames() {
1026
        return SUPPORTED_CIPHER_SUITE_NAMES.clone();
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
    }

    /**
     * Returns cipher suite name
     */
    public String getName() {
        return name;
    }

    /**
     * Returns cipher suite code as byte array
     */
    public byte[] toBytes() {
        return cipherSuiteCode;
    }

    /**
     * Returns cipher suite description
     */
1046
    @Override
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092
    public String toString() {
        return name + ": " + cipherSuiteCode[0] + " " + cipherSuiteCode[1];
    }

    /**
     * Returns cipher algorithm name
     */
    public String getBulkEncryptionAlgorithm() {
        return cipherName;
    }

    /**
     * Returns cipher block size
     */
    public int getBlockSize() {
        return blockSize;
    }

    /**
     * Returns MAC algorithm name
     */
    public String getHmacName() {
        return hmacName;
    }

    /**
     * Returns hash algorithm name
     */
    public String getHashName() {
        return hashName;
    }

    /**
     * Returns hash size
     */
    public int getMACLength() {
        return hashSize;
    }

    /**
     * Indicates whether this cipher suite is exportable
     */
    public boolean isExportable() {
        return isExportable;
    }

1093 1094 1095 1096 1097 1098 1099 1100
    /**
     * Indicates whether this cipher suite needs the initial record split to
     * mitigate the BEAST attack.
     */
    public boolean isInitialRecordSplit() {
        return needInitialRecordSplit;
    }

1101 1102 1103 1104 1105 1106 1107 1108
    static final String KEY_TYPE_RSA = "RSA";
    static final String KEY_TYPE_DSA = "DSA";
    static final String KEY_TYPE_DH_RSA = "DH_RSA";
    static final String KEY_TYPE_DH_DSA = "DH_DSA";
    static final String KEY_TYPE_EC = "EC";
    static final String KEY_TYPE_EC_EC = "EC_EC";
    static final String KEY_TYPE_EC_RSA = "EC_RSA";

Brian Carlstrom's avatar
Brian Carlstrom committed
1109
    /**
1110 1111 1112
     * Returns key type constant suitable for calling
     * X509KeyManager.chooseServerAlias or
     * X509ExtendedKeyManager.chooseEngineServerAlias.
Brian Carlstrom's avatar
Brian Carlstrom committed
1113
     */
1114
    public String getServerKeyType() {
Brian Carlstrom's avatar
Brian Carlstrom committed
1115 1116 1117
        switch (keyExchange) {
            case KEY_EXCHANGE_DHE_RSA:
            case KEY_EXCHANGE_DHE_RSA_EXPORT:
1118
            case KEY_EXCHANGE_ECDHE_RSA:
Brian Carlstrom's avatar
Brian Carlstrom committed
1119 1120
            case KEY_EXCHANGE_RSA:
            case KEY_EXCHANGE_RSA_EXPORT:
1121
                return KEY_TYPE_RSA;
Brian Carlstrom's avatar
Brian Carlstrom committed
1122 1123
            case KEY_EXCHANGE_DHE_DSS:
            case KEY_EXCHANGE_DHE_DSS_EXPORT:
1124 1125 1126 1127 1128 1129
                return KEY_TYPE_DSA;
            case KEY_EXCHANGE_ECDH_ECDSA:
            case KEY_EXCHANGE_ECDHE_ECDSA:
                return KEY_TYPE_EC_EC;
            case KEY_EXCHANGE_ECDH_RSA:
                return KEY_TYPE_EC_RSA;
Brian Carlstrom's avatar
Brian Carlstrom committed
1130 1131
            case KEY_EXCHANGE_DH_anon:
            case KEY_EXCHANGE_DH_anon_EXPORT:
1132
            case KEY_EXCHANGE_ECDH_anon:
Brian Carlstrom's avatar
Brian Carlstrom committed
1133 1134 1135 1136 1137
                return null;
            default:
                throw new IllegalStateException("Unknown key type for key exchange " + keyExchange);
        }
    }
1138

1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
    /**
     * Client certificate types as defined in
     * TLS 1.0 spec., 7.4.4. Certificate request.
     * EC constants from RFC 4492.
     * Names match openssl constants.
     */
    static final byte TLS_CT_RSA_SIGN = 1;
    static final byte TLS_CT_DSS_SIGN = 2;
    static final byte TLS_CT_RSA_FIXED_DH = 3;
    static final byte TLS_CT_DSS_FIXED_DH = 4;
    static final byte TLS_CT_ECDSA_SIGN = 64;
    static final byte TLS_CT_RSA_FIXED_ECDH = 65;
    static final byte TLS_CT_ECDSA_FIXED_ECDH = 66;

    /**
     * Similar to getServerKeyType, but returns value given TLS
     * ClientCertificateType byte values from a CertificateRequest
     * message for use with X509KeyManager.chooseClientAlias or
     * X509ExtendedKeyManager.chooseEngineClientAlias.
     */
    public static String getClientKeyType(byte keyType) {
        // See also http://www.ietf.org/assignments/tls-parameters/tls-parameters.xml
        switch (keyType) {
            case TLS_CT_RSA_SIGN:
                return KEY_TYPE_RSA; // RFC rsa_sign
            case TLS_CT_DSS_SIGN:
                return KEY_TYPE_DSA; // RFC dss_sign
            case TLS_CT_RSA_FIXED_DH:
                return KEY_TYPE_DH_RSA; // RFC rsa_fixed_dh
            case TLS_CT_DSS_FIXED_DH:
                return KEY_TYPE_DH_DSA; // RFC dss_fixed_dh
            case TLS_CT_ECDSA_SIGN:
                return KEY_TYPE_EC; // RFC ecdsa_sign
            case TLS_CT_RSA_FIXED_ECDH:
                return KEY_TYPE_EC_RSA; // RFC rsa_fixed_ecdh
            case TLS_CT_ECDSA_FIXED_ECDH:
                return KEY_TYPE_EC_EC; // RFC ecdsa_fixed_ecdh
            default:
                return null;
        }
    }

    private static final String AUTH_TYPE_RSA = "RSA";
    private static final String AUTH_TYPE_RSA_EXPORT = "RSA_EXPORT";
    private static final String AUTH_TYPE_DHE_DSS = "DHE_DSS";
    private static final String AUTH_TYPE_DHE_RSA = "DHE_RSA";
    private static final String AUTH_TYPE_DH_DSS = "DH_DSS";
    private static final String AUTH_TYPE_DH_RSA = "DH_RSA";
    private static final String AUTH_TYPE_ECDH_ECDSA = "ECDH_ECDSA";
    private static final String AUTH_TYPE_ECDH_RSA = "ECDH_RSA";
    private static final String AUTH_TYPE_ECDHE_ECDSA = "ECDHE_ECDSA";
    private static final String AUTH_TYPE_ECDHE_RSA = "ECDHE_RSA";

    /**
     * Returns auth type constant suitable for calling X509TrustManager.checkServerTrusted.
     */
    public String getAuthType(boolean emphemeral) {
        switch (keyExchange) {
            case KEY_EXCHANGE_RSA:
                return AUTH_TYPE_RSA;
            case KEY_EXCHANGE_RSA_EXPORT:
                return emphemeral ? AUTH_TYPE_RSA_EXPORT : AUTH_TYPE_RSA;
            case KEY_EXCHANGE_DHE_DSS:
            case KEY_EXCHANGE_DHE_DSS_EXPORT:
                return AUTH_TYPE_DHE_DSS;
            case KEY_EXCHANGE_DHE_RSA:
            case KEY_EXCHANGE_DHE_RSA_EXPORT:
                return AUTH_TYPE_DHE_RSA;
            case KEY_EXCHANGE_ECDH_ECDSA:
                return AUTH_TYPE_ECDH_ECDSA;
            case KEY_EXCHANGE_ECDHE_ECDSA:
                return AUTH_TYPE_ECDHE_ECDSA;
            case KEY_EXCHANGE_ECDH_RSA:
                return AUTH_TYPE_ECDH_RSA;
            case KEY_EXCHANGE_ECDHE_RSA:
                return AUTH_TYPE_ECDHE_RSA;
            case KEY_EXCHANGE_DH_anon:
            case KEY_EXCHANGE_DH_anon_EXPORT:
            case KEY_EXCHANGE_ECDH_anon:
                return null;
            default:
                throw new IllegalStateException("Unknown auth type for key exchange " + keyExchange);
        }
    }
}