CipherSuite.java revision 6b811c5daec1b28e6f63b57f98a032236f2c3cf7
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.xnet.provider.jsse;
19
20import java.security.GeneralSecurityException;
21import java.util.Hashtable;
22
23import javax.crypto.Cipher;
24
25/**
26 * Represents Cipher Suite as defined in TLS 1.0 spec.,
27 * A.5. The CipherSuite;
28 * C. CipherSuite definitions.
29 * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec.</a>
30 *
31 */
32public class CipherSuite {
33
34    /**
35     * true if this cipher suite is supported
36     */
37    boolean supported = true;
38
39    /**
40     * cipher suite key exchange
41     */
42    final int keyExchange;
43
44    /**
45     * cipher
46     */
47    final String cipherName;
48
49    /**
50     * Cipher information
51     */
52    final int keyMaterial;
53    final int expandedKeyMaterial;
54    final int effectiveKeyBytes;
55    final int IVSize;
56    final private int blockSize;
57
58    // cipher suite code
59    private final byte[] cipherSuiteCode;
60
61    // cipher suite name
62    private final String name;
63
64    // true if cipher suite is exportable
65    private final boolean isExportable;
66
67    // Hash algorithm
68    final private String hashName;
69
70    // MAC algorithm
71    final private String hmacName;
72
73    // Hash size
74    final private int hashSize;
75
76    /**
77     * key exchange values
78     */
79    static int KeyExchange_RSA = 1;
80    static int KeyExchange_RSA_EXPORT = 2;
81    static int KeyExchange_DHE_DSS = 3;
82    static int KeyExchange_DHE_DSS_EXPORT = 4;
83    static int KeyExchange_DHE_RSA = 5;
84    static int KeyExchange_DHE_RSA_EXPORT = 6;
85    static int KeyExchange_DH_DSS = 7;
86    static int KeyExchange_DH_RSA = 8;
87    static int KeyExchange_DH_anon = 9;
88    static int KeyExchange_DH_anon_EXPORT = 10;
89    static int KeyExchange_DH_DSS_EXPORT = 11;
90    static int KeyExchange_DH_RSA_EXPORT = 12;
91
92    /**
93     * TLS cipher suite codes
94     */
95    static byte[] code_TLS_NULL_WITH_NULL_NULL = { 0x00, 0x00 };
96    static byte[] code_TLS_RSA_WITH_NULL_MD5 = { 0x00, 0x01 };
97    static byte[] code_TLS_RSA_WITH_NULL_SHA = { 0x00, 0x02 };
98    static byte[] code_TLS_RSA_EXPORT_WITH_RC4_40_MD5 = { 0x00, 0x03 };
99    static byte[] code_TLS_RSA_WITH_RC4_128_MD5 = { 0x00, 0x04 };
100    static byte[] code_TLS_RSA_WITH_RC4_128_SHA = { 0x00, 0x05 };
101    static byte[] code_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = { 0x00, 0x06 };
102    static byte[] code_TLS_RSA_WITH_IDEA_CBC_SHA = { 0x00, 0x07 };
103    static byte[] code_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = { 0x00, 0x08 };
104    static byte[] code_TLS_RSA_WITH_DES_CBC_SHA = { 0x00, 0x09 };
105    static byte[] code_TLS_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00, 0x0A };
106    static byte[] code_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = { 0x00, 0x0B };
107    static byte[] code_TLS_DH_DSS_WITH_DES_CBC_SHA = { 0x00, 0x0C };
108    static byte[] code_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = { 0x00, 0x0D };
109    static byte[] code_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = { 0x00, 0x0E };
110    static byte[] code_TLS_DH_RSA_WITH_DES_CBC_SHA = { 0x00, 0x0F };
111    static byte[] code_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00, 0x10 };
112    static byte[] code_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = { 0x00, 0x11 };
113    static byte[] code_TLS_DHE_DSS_WITH_DES_CBC_SHA = { 0x00, 0x12 };
114    static byte[] code_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = { 0x00, 0x13 };
115    static byte[] code_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = { 0x00, 0x14 };
116    static byte[] code_TLS_DHE_RSA_WITH_DES_CBC_SHA = { 0x00, 0x15 };
117    static byte[] code_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = { 0x00, 0x16 };
118    static byte[] code_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = { 0x00, 0x17 };
119    static byte[] code_TLS_DH_anon_WITH_RC4_128_MD5 = { 0x00, 0x18 };
120    static byte[] code_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = { 0x00, 0x19 };
121    static byte[] code_TLS_DH_anon_WITH_DES_CBC_SHA = { 0x00, 0x1A };
122    static byte[] code_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = { 0x00, 0x1B };
123
124    static CipherSuite TLS_NULL_WITH_NULL_NULL = new CipherSuite(
125            "TLS_NULL_WITH_NULL_NULL", true, 0, null, null,
126            code_TLS_NULL_WITH_NULL_NULL);
127
128    static CipherSuite TLS_RSA_WITH_NULL_MD5 = new CipherSuite(
129            "TLS_RSA_WITH_NULL_MD5", true, KeyExchange_RSA, null, "MD5",
130            code_TLS_RSA_WITH_NULL_MD5);
131
132    static CipherSuite TLS_RSA_WITH_NULL_SHA = new CipherSuite(
133            "TLS_RSA_WITH_NULL_SHA", true, KeyExchange_RSA, null, "SHA",
134            code_TLS_RSA_WITH_NULL_SHA);
135
136    static CipherSuite TLS_RSA_EXPORT_WITH_RC4_40_MD5 = new CipherSuite(
137            "TLS_RSA_EXPORT_WITH_RC4_40_MD5", true, KeyExchange_RSA_EXPORT,
138            "RC4_40", "MD5", code_TLS_RSA_EXPORT_WITH_RC4_40_MD5);
139
140    static CipherSuite TLS_RSA_WITH_RC4_128_MD5 = new CipherSuite(
141            "TLS_RSA_WITH_RC4_128_MD5", false, KeyExchange_RSA, "RC4_128",
142            "MD5", code_TLS_RSA_WITH_RC4_128_MD5);
143
144    static CipherSuite TLS_RSA_WITH_RC4_128_SHA = new CipherSuite(
145            "TLS_RSA_WITH_RC4_128_SHA", false, KeyExchange_RSA, "RC4_128",
146            "SHA", code_TLS_RSA_WITH_RC4_128_SHA);
147
148    static CipherSuite TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = new CipherSuite(
149            "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5", true, KeyExchange_RSA_EXPORT,
150            "RC2_CBC_40", "MD5", code_TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5);
151
152    static CipherSuite TLS_RSA_WITH_IDEA_CBC_SHA = new CipherSuite(
153            "TLS_RSA_WITH_IDEA_CBC_SHA", false, KeyExchange_RSA, "IDEA_CBC",
154            "SHA", code_TLS_RSA_WITH_IDEA_CBC_SHA);
155
156    static CipherSuite TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = new CipherSuite(
157            "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA", true, KeyExchange_RSA_EXPORT,
158            "DES40_CBC", "SHA", code_TLS_RSA_EXPORT_WITH_DES40_CBC_SHA);
159
160    static CipherSuite TLS_RSA_WITH_DES_CBC_SHA = new CipherSuite(
161            "TLS_RSA_WITH_DES_CBC_SHA", false, KeyExchange_RSA, "DES_CBC",
162            "SHA", code_TLS_RSA_WITH_DES_CBC_SHA);
163
164    static CipherSuite TLS_RSA_WITH_3DES_EDE_CBC_SHA = new CipherSuite(
165            "TLS_RSA_WITH_3DES_EDE_CBC_SHA", false, KeyExchange_RSA,
166            "3DES_EDE_CBC", "SHA", code_TLS_RSA_WITH_3DES_EDE_CBC_SHA);
167
168    static CipherSuite TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = new CipherSuite(
169            "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA", true,
170            KeyExchange_DH_DSS_EXPORT, "DES40_CBC", "SHA",
171            code_TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA);
172
173    static CipherSuite TLS_DH_DSS_WITH_DES_CBC_SHA = new CipherSuite(
174            "TLS_DH_DSS_WITH_DES_CBC_SHA", false, KeyExchange_DH_DSS,
175            "DES_CBC", "SHA", code_TLS_DH_DSS_WITH_DES_CBC_SHA);
176
177    static CipherSuite TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = new CipherSuite(
178            "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA", false, KeyExchange_DH_DSS,
179            "3DES_EDE_CBC", "SHA", code_TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA);
180
181    static CipherSuite TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = new CipherSuite(
182            "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA", true,
183            KeyExchange_DH_RSA_EXPORT, "DES40_CBC", "SHA",
184            code_TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA);
185
186    static CipherSuite TLS_DH_RSA_WITH_DES_CBC_SHA = new CipherSuite(
187            "TLS_DH_RSA_WITH_DES_CBC_SHA", false, KeyExchange_DH_RSA,
188            "DES_CBC", "SHA", code_TLS_DH_RSA_WITH_DES_CBC_SHA);
189
190    static CipherSuite TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = new CipherSuite(
191            "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA", false, KeyExchange_DH_RSA,
192            "3DES_EDE_CBC", "SHA", code_TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA);
193
194    static CipherSuite TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = new CipherSuite(
195            "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA", true,
196            KeyExchange_DHE_DSS_EXPORT, "DES40_CBC", "SHA",
197            code_TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA);
198
199    static CipherSuite TLS_DHE_DSS_WITH_DES_CBC_SHA = new CipherSuite(
200            "TLS_DHE_DSS_WITH_DES_CBC_SHA", false, KeyExchange_DHE_DSS,
201            "DES_CBC", "SHA", code_TLS_DHE_DSS_WITH_DES_CBC_SHA);
202
203    static CipherSuite TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = new CipherSuite(
204            "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", false, KeyExchange_DHE_DSS,
205            "3DES_EDE_CBC", "SHA", code_TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA);
206
207    static CipherSuite TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = new CipherSuite(
208            "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", true,
209            KeyExchange_DHE_RSA_EXPORT, "DES40_CBC", "SHA",
210            code_TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA);
211
212    static CipherSuite TLS_DHE_RSA_WITH_DES_CBC_SHA = new CipherSuite(
213            "TLS_DHE_RSA_WITH_DES_CBC_SHA", false, KeyExchange_DHE_RSA,
214            "DES_CBC", "SHA", code_TLS_DHE_RSA_WITH_DES_CBC_SHA);
215
216    static CipherSuite TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = new CipherSuite(
217            "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA", false, KeyExchange_DHE_RSA,
218            "3DES_EDE_CBC", "SHA", code_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA);
219
220    static CipherSuite TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = new CipherSuite(
221            "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5", true,
222            KeyExchange_DH_anon_EXPORT, "RC4_40", "MD5",
223            code_TLS_DH_anon_EXPORT_WITH_RC4_40_MD5);
224
225    static CipherSuite TLS_DH_anon_WITH_RC4_128_MD5 = new CipherSuite(
226            "TLS_DH_anon_WITH_RC4_128_MD5", false, KeyExchange_DH_anon,
227            "RC4_128", "MD5", code_TLS_DH_anon_WITH_RC4_128_MD5);
228
229    static CipherSuite TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = new CipherSuite(
230            "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA", true,
231            KeyExchange_DH_anon_EXPORT, "DES40_CBC", "SHA",
232            code_TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA);
233
234    static CipherSuite TLS_DH_anon_WITH_DES_CBC_SHA = new CipherSuite(
235            "TLS_DH_anon_WITH_DES_CBC_SHA", false, KeyExchange_DH_anon,
236            "DES_CBC", "SHA", code_TLS_DH_anon_WITH_DES_CBC_SHA);
237
238    static CipherSuite TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = new CipherSuite(
239            "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA", false, KeyExchange_DH_anon,
240            "3DES_EDE_CBC", "SHA", code_TLS_DH_anon_WITH_3DES_EDE_CBC_SHA);
241
242    // array for quick access to cipher suite by code
243    private static CipherSuite[] cuitesByCode = {
244            TLS_NULL_WITH_NULL_NULL,
245            TLS_RSA_WITH_NULL_MD5,
246            TLS_RSA_WITH_NULL_SHA,
247            TLS_RSA_EXPORT_WITH_RC4_40_MD5,
248            TLS_RSA_WITH_RC4_128_MD5,
249            TLS_RSA_WITH_RC4_128_SHA,
250            TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
251            TLS_RSA_WITH_IDEA_CBC_SHA,
252            TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,
253            TLS_RSA_WITH_DES_CBC_SHA,
254            TLS_RSA_WITH_3DES_EDE_CBC_SHA,
255            TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
256            TLS_DH_DSS_WITH_DES_CBC_SHA,
257            TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA,
258            TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
259            TLS_DH_RSA_WITH_DES_CBC_SHA,
260            TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA,
261            TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
262            TLS_DHE_DSS_WITH_DES_CBC_SHA,
263            TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
264            TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
265            TLS_DHE_RSA_WITH_DES_CBC_SHA,
266            TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
267            TLS_DH_anon_EXPORT_WITH_RC4_40_MD5,
268            TLS_DH_anon_WITH_RC4_128_MD5,
269            TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
270            TLS_DH_anon_WITH_DES_CBC_SHA,
271            TLS_DH_anon_WITH_3DES_EDE_CBC_SHA
272            };
273
274    // hash for quick access to cipher suite by name
275    private static Hashtable<String, CipherSuite> cuitesByName;
276
277    /**
278     * array of supported cipher suites.
279     * Set of supported suites is defined at the moment provider's start
280     */
281//  TODO Dynamically supported suites: new providers may be dynamically
282//  added/removed and the set of supported suites may be changed
283    static CipherSuite[] supportedCipherSuites;
284
285    /**
286     * array of supported cipher suites names
287     */
288    static String[] supportedCipherSuiteNames;
289
290    /**
291     * default cipher suites
292     */
293    static CipherSuite[] defaultCipherSuites;
294
295    static {
296        int count = 0;
297        cuitesByName = new Hashtable<String, CipherSuite>();
298        for (int i = 0; i < cuitesByCode.length; i++) {
299            cuitesByName.put(cuitesByCode[i].getName(), cuitesByCode[i]);
300            if (cuitesByCode[i].supported) {
301                count++;
302            }
303        }
304        supportedCipherSuites = new CipherSuite[count];
305        supportedCipherSuiteNames = new String[count];
306        count = 0;
307        for (int i = 0; i < cuitesByCode.length; i++) {
308            if (cuitesByCode[i].supported) {
309                supportedCipherSuites[count] = cuitesByCode[i];
310                supportedCipherSuiteNames[count] = supportedCipherSuites[count].getName();
311                count++;
312            }
313        }
314
315        CipherSuite[] defaultPretendent = {
316                TLS_RSA_WITH_RC4_128_MD5,
317                TLS_RSA_WITH_RC4_128_SHA,
318                // TLS_RSA_WITH_AES_128_CBC_SHA,
319                // TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
320                // LS_DHE_DSS_WITH_AES_128_CBC_SHA,
321                TLS_RSA_WITH_3DES_EDE_CBC_SHA,
322                TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
323                TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, TLS_RSA_WITH_DES_CBC_SHA,
324                TLS_DHE_RSA_WITH_DES_CBC_SHA, TLS_DHE_DSS_WITH_DES_CBC_SHA,
325                TLS_RSA_EXPORT_WITH_RC4_40_MD5,
326                TLS_RSA_EXPORT_WITH_DES40_CBC_SHA,
327                TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
328                TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
329                };
330        count = 0;
331        for (int i = 0; i < defaultPretendent.length; i++) {
332            if (defaultPretendent[i].supported) {
333                count++;
334            }
335        }
336        defaultCipherSuites = new CipherSuite[count];
337        count = 0;
338        for (int i = 0; i < defaultPretendent.length; i++) {
339            if (defaultPretendent[i].supported) {
340                defaultCipherSuites[count++] = defaultPretendent[i];
341            }
342        }
343    }
344
345    /**
346     * Returns CipherSuite by name
347     * @param name
348     * @return
349     */
350    public static CipherSuite getByName(String name) {
351        return cuitesByName.get(name);
352    }
353
354    /**
355     * Returns CipherSuite based on TLS CipherSuite code
356     * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., A.5. The CipherSuite</a>
357     * @param b1
358     * @param b2
359     * @return
360     */
361    public static CipherSuite getByCode(byte b1, byte b2) {
362        if (b1 != 0 || (b2 & 0xFF) > cuitesByCode.length) {
363            // Unknown
364            return new CipherSuite("UNKNOUN_" + b1 + "_" + b2, false, 0, "",
365                    "", new byte[] { b1, b2 });
366        }
367        return cuitesByCode[b2];
368    }
369
370    /**
371     * Returns CipherSuite based on V2CipherSpec code
372     * as described in TLS 1.0 spec., E. Backward Compatibility With SSL
373     *
374     * @param b1
375     * @param b2
376     * @param b3
377     * @return CipherSuite
378     */
379    public static CipherSuite getByCode(byte b1, byte b2, byte b3) {
380        if (b1 == 0 && b2 == 0) {
381            if ((b3 & 0xFF) <= cuitesByCode.length) {
382                return cuitesByCode[b3];
383            }
384        }
385        // as TLSv1 equivalent of V2CipherSpec should be included in
386        // V2ClientHello, ignore V2CipherSpec
387        return new CipherSuite("UNKNOUN_" + b1 + "_" + b2 + "_" + b3, false, 0,
388                "", "", new byte[] { b1, b2, b3 });
389    }
390
391    /**
392     * Creates CipherSuite
393     * @param name
394     * @param isExportable
395     * @param keyExchange
396     * @param cipherName
397     * @param hash
398     * @param code
399     */
400    public CipherSuite(String name, boolean isExportable, int keyExchange,
401            String cipherName, String hash, byte[] code) {
402        this.name = name;
403        this.keyExchange = keyExchange;
404        this.isExportable = isExportable;
405        if (cipherName == null) {
406            this.cipherName = null;
407            keyMaterial = 0;
408            expandedKeyMaterial = 0;
409            effectiveKeyBytes = 0;
410            IVSize = 0;
411            blockSize = 0;
412        } else if ("IDEA_CBC".equals(cipherName)) {
413            this.cipherName = "IDEA/CBC/NoPadding";
414            keyMaterial = 16;
415            expandedKeyMaterial = 16;
416            effectiveKeyBytes = 16;
417            IVSize = 8;
418            blockSize = 8;
419        } else if ("RC2_CBC_40".equals(cipherName)) {
420            this.cipherName = "RC2/CBC/NoPadding";
421            keyMaterial = 5;
422            expandedKeyMaterial = 16;
423            effectiveKeyBytes = 5;
424            IVSize = 8;
425            blockSize = 8;
426        } else if ("RC4_40".equals(cipherName)) {
427            this.cipherName = "RC4";
428            keyMaterial = 5;
429            expandedKeyMaterial = 16;
430            effectiveKeyBytes = 5;
431            IVSize = 0;
432            blockSize = 0;
433        } else if ("RC4_128".equals(cipherName)) {
434            this.cipherName = "RC4";
435            keyMaterial = 16;
436            expandedKeyMaterial = 16;
437            effectiveKeyBytes = 16;
438            IVSize = 0;
439            blockSize = 0;
440        } else if ("DES40_CBC".equals(cipherName)) {
441            this.cipherName = "DES/CBC/NoPadding";
442            keyMaterial = 5;
443            expandedKeyMaterial = 8;
444            effectiveKeyBytes = 5;
445            IVSize = 8;
446            blockSize = 8;
447        } else if ("DES_CBC".equals(cipherName)) {
448            this.cipherName = "DES/CBC/NoPadding";
449            keyMaterial = 8;
450            expandedKeyMaterial = 8;
451            effectiveKeyBytes = 7;
452            IVSize = 8;
453            blockSize = 8;
454        } else if ("3DES_EDE_CBC".equals(cipherName)) {
455            this.cipherName = "DESede/CBC/NoPadding";
456            keyMaterial = 24;
457            expandedKeyMaterial = 24;
458            effectiveKeyBytes = 24;
459            IVSize = 8;
460            blockSize = 8;
461        } else {
462            this.cipherName = cipherName;
463            keyMaterial = 0;
464            expandedKeyMaterial = 0;
465            effectiveKeyBytes = 0;
466            IVSize = 0;
467            blockSize = 0;
468        }
469
470        if ("MD5".equals(hash)) {
471            this.hmacName = "HmacMD5";
472            this.hashName = "MD5";
473            hashSize = 16;
474        } else if ("SHA".equals(hash)) {
475            this.hmacName = "HmacSHA1";
476            this.hashName = "SHA-1";
477            hashSize = 20;
478        } else {
479            this.hmacName = null;
480            this.hashName = null;
481            hashSize = 0;
482        }
483
484        cipherSuiteCode = code;
485
486        if (this.cipherName != null) {
487            try {
488                Cipher.getInstance(this.cipherName);
489            } catch (GeneralSecurityException e) {
490                supported = false;
491            }
492        }
493
494    }
495
496    /**
497     * Returns true if cipher suite is anonymous
498     * @return
499     */
500    public boolean isAnonymous() {
501        if (keyExchange == KeyExchange_DH_anon
502                || keyExchange == KeyExchange_DH_anon_EXPORT) {
503            return true;
504        }
505        return false;
506    }
507
508    /**
509     * Returns array of supported CipherSuites
510     * @return
511     */
512    public static CipherSuite[] getSupported() {
513        return supportedCipherSuites;
514    }
515
516    /**
517     * Returns array of supported cipher suites names
518     * @return
519     */
520    public static String[] getSupportedCipherSuiteNames() {
521        return supportedCipherSuiteNames.clone();
522    }
523
524    /**
525     * Returns cipher suite name
526     * @return
527     */
528    public String getName() {
529        return name;
530    }
531
532    /**
533     * Returns cipher suite code as byte array
534     * @return
535     */
536    public byte[] toBytes() {
537        return cipherSuiteCode;
538    }
539
540    /**
541     * Returns cipher suite description
542     */
543    @Override
544    public String toString() {
545        return name + ": " + cipherSuiteCode[0] + " " + cipherSuiteCode[1];
546    }
547
548    /**
549     * Compares this cipher suite to the specified object.
550     */
551    @Override
552    public boolean equals(Object obj) {
553        if (obj instanceof CipherSuite
554                && this.cipherSuiteCode[0] == ((CipherSuite) obj).cipherSuiteCode[0]
555                && this.cipherSuiteCode[1] == ((CipherSuite) obj).cipherSuiteCode[1]) {
556            return true;
557        }
558        return false;
559    }
560
561    /**
562     * Returns cipher algorithm name
563     * @return
564     */
565    public String getBulkEncryptionAlgorithm() {
566        return cipherName;
567    }
568
569    /**
570     * Returns cipher block size
571     * @return
572     */
573    public int getBlockSize() {
574        return blockSize;
575    }
576
577    /**
578     * Returns MAC algorithm name
579     * @return
580     */
581    public String getHmacName() {
582        return hmacName;
583    }
584
585    /**
586     * Returns hash algorithm name
587     * @return
588     */
589    public String getHashName() {
590        return hashName;
591    }
592
593    /**
594     * Returns hash size
595     * @return
596     */
597    public int getMACLength() {
598        return hashSize;
599    }
600
601    /**
602     * Indicates whether this cipher suite is exportable
603     * @return
604     */
605    public boolean isExportable() {
606        return isExportable;
607    }
608
609}
610
611