1 /**
2 * TLS Cipher Suites
3 * 
4 * Copyright:
5 * (C) 2004-2011,2012 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 
12 module botan.tls.ciphersuite;
13 
14 import botan.constants;
15 static if (BOTAN_HAS_TLS):
16 
17 import botan.utils.types;
18 import botan.libstate.libstate;
19 import botan.utils.parsing;
20 import std.array : Appender;
21 import std.exception;
22 
23 /**
24 * TLSCiphersuite Information
25 */
26 struct TLSCiphersuite
27 {
28 public:
29     /**
30     * Convert an SSL/TLS ciphersuite to algorithm fields
31     * Params:
32     *  suite = the ciphersuite code number
33     * Returns: ciphersuite object
34     */
35     static TLSCiphersuite byId(ushort suite)
36     {
37         switch(suite)
38         {
39             case 0x0013: // DHE_DSS_WITH_3DES_EDE_CBC_SHA
40                 return TLSCiphersuite(0x0013, "DSA", "DH", "3DES", 24, 8, 0, "SHA-1", 20);
41             case 0x0032: // DHE_DSS_WITH_AES_128_CBC_SHA
42                 return TLSCiphersuite(0x0032, "DSA", "DH", "AES-128", 16, 16, 0, "SHA-1", 20);
43             case 0x0040: // DHE_DSS_WITH_AES_128_CBC_SHA256
44                 return TLSCiphersuite(0x0040, "DSA", "DH", "AES-128", 16, 16, 0, "SHA-256", 32);
45             case 0x00A2: // DHE_DSS_WITH_AES_128_GCM_SHA256
46                 return TLSCiphersuite(0x00A2, "DSA", "DH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
47             case 0x0038: // DHE_DSS_WITH_AES_256_CBC_SHA
48                 return TLSCiphersuite(0x0038, "DSA", "DH", "AES-256", 32, 16, 0, "SHA-1", 20);
49             case 0x006A: // DHE_DSS_WITH_AES_256_CBC_SHA256
50                 return TLSCiphersuite(0x006A, "DSA", "DH", "AES-256", 32, 16, 0, "SHA-256", 32);
51             case 0x00A3: // DHE_DSS_WITH_AES_256_GCM_SHA384
52                 return TLSCiphersuite(0x00A3, "DSA", "DH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
53             case 0x0044: // DHE_DSS_WITH_CAMELLIA_128_CBC_SHA
54                 return TLSCiphersuite(0x0044, "DSA", "DH", "Camellia-128", 16, 16, 0, "SHA-1", 20);
55             case 0x00BD: // DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256
56                 return TLSCiphersuite(0x00BD, "DSA", "DH", "Camellia-128", 16, 16, 0, "SHA-256", 32);
57             case 0xC080: // DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256
58                 return TLSCiphersuite(0xC080, "DSA", "DH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
59             case 0x0087: // DHE_DSS_WITH_CAMELLIA_256_CBC_SHA
60                 return TLSCiphersuite(0x0087, "DSA", "DH", "Camellia-256", 32, 16, 0, "SHA-1", 20);
61             case 0x00C3: // DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256
62                 return TLSCiphersuite(0x00C3, "DSA", "DH", "Camellia-256", 32, 16, 0, "SHA-256", 32);
63             case 0xC081: // DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384
64                 return TLSCiphersuite(0xC081, "DSA", "DH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
65             case 0x0066: // DHE_DSS_WITH_RC4_128_SHA
66                 return TLSCiphersuite(0x0066, "DSA", "DH", "RC4", 16, 0, 0, "SHA-1", 20);
67             case 0x0099: // DHE_DSS_WITH_SEED_CBC_SHA
68                 return TLSCiphersuite(0x0099, "DSA", "DH", "SEED", 16, 16, 0, "SHA-1", 20);
69             case 0x008F: // DHE_PSK_WITH_3DES_EDE_CBC_SHA
70                 return TLSCiphersuite(0x008F, "", "DHE_PSK", "3DES", 24, 8, 0, "SHA-1", 20);
71             case 0x0090: // DHE_PSK_WITH_AES_128_CBC_SHA
72                 return TLSCiphersuite(0x0090, "", "DHE_PSK", "AES-128", 16, 16, 0, "SHA-1", 20);
73             case 0x00B2: // DHE_PSK_WITH_AES_128_CBC_SHA256
74                 return TLSCiphersuite(0x00B2, "", "DHE_PSK", "AES-128", 16, 16, 0, "SHA-256", 32);
75             case 0xC0A6: // DHE_PSK_WITH_AES_128_CCM
76                 return TLSCiphersuite(0xC0A6, "", "DHE_PSK", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256");
77             case 0x00AA: // DHE_PSK_WITH_AES_128_GCM_SHA256
78                 return TLSCiphersuite(0x00AA, "", "DHE_PSK", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
79             case 0x0091: // DHE_PSK_WITH_AES_256_CBC_SHA
80                 return TLSCiphersuite(0x0091, "", "DHE_PSK", "AES-256", 32, 16, 0, "SHA-1", 20);
81             case 0x00B3: // DHE_PSK_WITH_AES_256_CBC_SHA384
82                 return TLSCiphersuite(0x00B3, "", "DHE_PSK", "AES-256", 32, 16, 0, "SHA-384", 48);
83             case 0xC0A7: // DHE_PSK_WITH_AES_256_CCM
84                 return TLSCiphersuite(0xC0A7, "", "DHE_PSK", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256");
85             case 0x00AB: // DHE_PSK_WITH_AES_256_GCM_SHA384
86                 return TLSCiphersuite(0x00AB, "", "DHE_PSK", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
87             case 0xC096: // DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
88                 return TLSCiphersuite(0xC096, "", "DHE_PSK", "Camellia-128", 16, 16, 0, "SHA-256", 32);
89             case 0xC090: // DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256
90                 return TLSCiphersuite(0xC090, "", "DHE_PSK", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
91             case 0xC097: // DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
92                 return TLSCiphersuite(0xC097, "", "DHE_PSK", "Camellia-256", 32, 16, 0, "SHA-384", 48);
93             case 0xC091: // DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384
94                 return TLSCiphersuite(0xC091, "", "DHE_PSK", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
95             case 0x008E: // DHE_PSK_WITH_RC4_128_SHA
96                 return TLSCiphersuite(0x008E, "", "DHE_PSK", "RC4", 16, 0, 0, "SHA-1", 20);
97             case 0x0016: // DHE_RSA_WITH_3DES_EDE_CBC_SHA
98                 return TLSCiphersuite(0x0016, "RSA", "DH", "3DES", 24, 8, 0, "SHA-1", 20);
99             case 0x0033: // DHE_RSA_WITH_AES_128_CBC_SHA
100                 return TLSCiphersuite(0x0033, "RSA", "DH", "AES-128", 16, 16, 0, "SHA-1", 20);
101             case 0x0067: // DHE_RSA_WITH_AES_128_CBC_SHA256
102                 return TLSCiphersuite(0x0067, "RSA", "DH", "AES-128", 16, 16, 0, "SHA-256", 32);
103             case 0xC09E: // DHE_RSA_WITH_AES_128_CCM
104                 return TLSCiphersuite(0xC09E, "RSA", "DH", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256");
105             case 0xC0A2: // DHE_RSA_WITH_AES_128_CCM_8
106                 return TLSCiphersuite(0xC0A2, "RSA", "DH", "AES-128/CCM-8", 16, 4, 8, "AEAD", 0, "SHA-256");
107             case 0x009E: // DHE_RSA_WITH_AES_128_GCM_SHA256
108                 return TLSCiphersuite(0x009E, "RSA", "DH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
109             case 0x0039: // DHE_RSA_WITH_AES_256_CBC_SHA
110                 return TLSCiphersuite(0x0039, "RSA", "DH", "AES-256", 32, 16, 0, "SHA-1", 20);
111             case 0x006B: // DHE_RSA_WITH_AES_256_CBC_SHA256
112                 return TLSCiphersuite(0x006B, "RSA", "DH", "AES-256", 32, 16, 0, "SHA-256", 32);
113             case 0xC09F: // DHE_RSA_WITH_AES_256_CCM
114                 return TLSCiphersuite(0xC09F, "RSA", "DH", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256");
115             case 0xC0A3: // DHE_RSA_WITH_AES_256_CCM_8
116                 return TLSCiphersuite(0xC0A3, "RSA", "DH", "AES-256/CCM-8", 32, 4, 8, "AEAD", 0, "SHA-256");
117             case 0x009F: // DHE_RSA_WITH_AES_256_GCM_SHA384
118                 return TLSCiphersuite(0x009F, "RSA", "DH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
119             case 0x0045: // DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
120                 return TLSCiphersuite(0x0045, "RSA", "DH", "Camellia-128", 16, 16, 0, "SHA-1", 20);
121             case 0x00BE: // DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
122                 return TLSCiphersuite(0x00BE, "RSA", "DH", "Camellia-128", 16, 16, 0, "SHA-256", 32);
123             case 0xC07C: // DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
124                 return TLSCiphersuite(0xC07C, "RSA", "DH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
125             case 0x0088: // DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
126                 return TLSCiphersuite(0x0088, "RSA", "DH", "Camellia-256", 32, 16, 0, "SHA-1", 20);
127             case 0x00C4: // DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
128                 return TLSCiphersuite(0x00C4, "RSA", "DH", "Camellia-256", 32, 16, 0, "SHA-256", 32);
129             case 0xC07D: // DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
130                 return TLSCiphersuite(0xC07D, "RSA", "DH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
131 			case 0xCC15: // DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
132 				return TLSCiphersuite(0xCC15, "RSA", "DH", "ChaCha20Poly1305", 32, 0, 0, "AEAD", 0, "SHA-256");
133             case 0x009A: // DHE_RSA_WITH_SEED_CBC_SHA
134                 return TLSCiphersuite(0x009A, "RSA", "DH", "SEED", 16, 16, 0, "SHA-1", 20);
135             case 0x001B: // DH_anon_WITH_3DES_EDE_CBC_SHA
136                 return TLSCiphersuite(0x001B, "", "DH", "3DES", 24, 8, 0, "SHA-1", 20);
137             case 0x0034: // DH_anon_WITH_AES_128_CBC_SHA
138                 return TLSCiphersuite(0x0034, "", "DH", "AES-128", 16, 16, 0, "SHA-1", 20);
139             case 0x006C: // DH_anon_WITH_AES_128_CBC_SHA256
140                 return TLSCiphersuite(0x006C, "", "DH", "AES-128", 16, 16, 0, "SHA-256", 32);
141             case 0x00A6: // DH_anon_WITH_AES_128_GCM_SHA256
142                 return TLSCiphersuite(0x00A6, "", "DH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
143             case 0x003A: // DH_anon_WITH_AES_256_CBC_SHA
144                 return TLSCiphersuite(0x003A, "", "DH", "AES-256", 32, 16, 0, "SHA-1", 20);
145             case 0x006D: // DH_anon_WITH_AES_256_CBC_SHA256
146                 return TLSCiphersuite(0x006D, "", "DH", "AES-256", 32, 16, 0, "SHA-256", 32);
147             case 0x00A7: // DH_anon_WITH_AES_256_GCM_SHA384
148                 return TLSCiphersuite(0x00A7, "", "DH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
149             case 0x0046: // DH_anon_WITH_CAMELLIA_128_CBC_SHA
150                 return TLSCiphersuite(0x0046, "", "DH", "Camellia-128", 16, 16, 0, "SHA-1", 20);
151             case 0x00BF: // DH_anon_WITH_CAMELLIA_128_CBC_SHA256
152                 return TLSCiphersuite(0x00BF, "", "DH", "Camellia-128", 16, 16, 0, "SHA-256", 32);
153             case 0xC084: // DH_anon_WITH_CAMELLIA_128_GCM_SHA256
154                 return TLSCiphersuite(0xC084, "", "DH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
155             case 0x0089: // DH_anon_WITH_CAMELLIA_256_CBC_SHA
156                 return TLSCiphersuite(0x0089, "", "DH", "Camellia-256", 32, 16, 0, "SHA-1", 20);
157             case 0x00C5: // DH_anon_WITH_CAMELLIA_256_CBC_SHA256
158                 return TLSCiphersuite(0x00C5, "", "DH", "Camellia-256", 32, 16, 0, "SHA-256", 32);
159             case 0xC085: // DH_anon_WITH_CAMELLIA_256_GCM_SHA384
160                 return TLSCiphersuite(0xC085, "", "DH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
161             case 0x0018: // DH_anon_WITH_RC4_128_MD5
162                 return TLSCiphersuite(0x0018, "", "DH", "RC4", 16, 0, 0, "MD5", 16);
163             case 0x009B: // DH_anon_WITH_SEED_CBC_SHA
164                 return TLSCiphersuite(0x009B, "", "DH", "SEED", 16, 16, 0, "SHA-1", 20);
165             case 0xC008: // ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
166                 return TLSCiphersuite(0xC008, "ECDSA", "ECDH", "3DES", 24, 8, 0, "SHA-1", 20);
167             case 0xC009: // ECDHE_ECDSA_WITH_AES_128_CBC_SHA
168                 return TLSCiphersuite(0xC009, "ECDSA", "ECDH", "AES-128", 16, 16, 0, "SHA-1", 20);
169             case 0xC023: // ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
170                 return TLSCiphersuite(0xC023, "ECDSA", "ECDH", "AES-128", 16, 16, 0, "SHA-256", 32);
171             case 0xC0AC: // ECDHE_ECDSA_WITH_AES_128_CCM
172                 return TLSCiphersuite(0xC0AC, "ECDSA", "ECDH", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256");
173             case 0xC0AE: // ECDHE_ECDSA_WITH_AES_128_CCM_8
174                 return TLSCiphersuite(0xC0AE, "ECDSA", "ECDH", "AES-128/CCM-8", 16, 4, 8, "AEAD", 0, "SHA-256");
175             case 0xC02B: // ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
176                 return TLSCiphersuite(0xC02B, "ECDSA", "ECDH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
177             case 0xC00A: // ECDHE_ECDSA_WITH_AES_256_CBC_SHA
178                 return TLSCiphersuite(0xC00A, "ECDSA", "ECDH", "AES-256", 32, 16, 0, "SHA-1", 20);
179             case 0xC024: // ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
180                 return TLSCiphersuite(0xC024, "ECDSA", "ECDH", "AES-256", 32, 16, 0, "SHA-384", 48);
181             case 0xC0AD: // ECDHE_ECDSA_WITH_AES_256_CCM
182                 return TLSCiphersuite(0xC0AD, "ECDSA", "ECDH", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256");
183             case 0xC0AF: // ECDHE_ECDSA_WITH_AES_256_CCM_8
184                 return TLSCiphersuite(0xC0AF, "ECDSA", "ECDH", "AES-256/CCM-8", 32, 4, 8, "AEAD", 0, "SHA-256");
185             case 0xC02C: // ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
186                 return TLSCiphersuite(0xC02C, "ECDSA", "ECDH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
187             case 0xC072: // ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
188                 return TLSCiphersuite(0xC072, "ECDSA", "ECDH", "Camellia-128", 16, 16, 0, "SHA-256", 32);
189             case 0xC086: // ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
190                 return TLSCiphersuite(0xC086, "ECDSA", "ECDH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
191             case 0xC073: // ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
192                 return TLSCiphersuite(0xC073, "ECDSA", "ECDH", "Camellia-256", 32, 16, 0, "SHA-384", 48);
193             case 0xC087: // ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
194                 return TLSCiphersuite(0xC087, "ECDSA", "ECDH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
195 			case 0xCC14: // ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
196 				return TLSCiphersuite(0xCC14, "ECDSA", "ECDH", "ChaCha20Poly1305", 32, 0, 0, "AEAD", 0, "SHA-256");
197             case 0xC007: // ECDHE_ECDSA_WITH_RC4_128_SHA
198                 return TLSCiphersuite(0xC007, "ECDSA", "ECDH", "RC4", 16, 0, 0, "SHA-1", 20);
199             case 0xC034: // ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
200                 return TLSCiphersuite(0xC034, "", "ECDHE_PSK", "3DES", 24, 8, 0, "SHA-1", 20);
201             case 0xC035: // ECDHE_PSK_WITH_AES_128_CBC_SHA
202                 return TLSCiphersuite(0xC035, "", "ECDHE_PSK", "AES-128", 16, 16, 0, "SHA-1", 20);
203             case 0xC037: // ECDHE_PSK_WITH_AES_128_CBC_SHA256
204                 return TLSCiphersuite(0xC037, "", "ECDHE_PSK", "AES-128", 16, 16, 0, "SHA-256", 32);
205             case 0xC036: // ECDHE_PSK_WITH_AES_256_CBC_SHA
206                 return TLSCiphersuite(0xC036, "", "ECDHE_PSK", "AES-256", 32, 16, 0, "SHA-1", 20);
207             case 0xC038: // ECDHE_PSK_WITH_AES_256_CBC_SHA384
208                 return TLSCiphersuite(0xC038, "", "ECDHE_PSK", "AES-256", 32, 16, 0, "SHA-384", 48);
209             case 0xC09A: // ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
210                 return TLSCiphersuite(0xC09A, "", "ECDHE_PSK", "Camellia-128", 16, 16, 0, "SHA-256", 32);
211             case 0xC09B: // ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
212                 return TLSCiphersuite(0xC09B, "", "ECDHE_PSK", "Camellia-256", 32, 16, 0, "SHA-384", 48);
213             case 0xC033: // ECDHE_PSK_WITH_RC4_128_SHA
214                 return TLSCiphersuite(0xC033, "", "ECDHE_PSK", "RC4", 16, 0, 0, "SHA-1", 20);
215             case 0xC012: // ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
216                 return TLSCiphersuite(0xC012, "RSA", "ECDH", "3DES", 24, 8, 0, "SHA-1", 20);
217             case 0xC013: // ECDHE_RSA_WITH_AES_128_CBC_SHA
218                 return TLSCiphersuite(0xC013, "RSA", "ECDH", "AES-128", 16, 16, 0, "SHA-1", 20);
219             case 0xC027: // ECDHE_RSA_WITH_AES_128_CBC_SHA256
220                 return TLSCiphersuite(0xC027, "RSA", "ECDH", "AES-128", 16, 16, 0, "SHA-256", 32);
221             case 0xC02F: // ECDHE_RSA_WITH_AES_128_GCM_SHA256
222                 return TLSCiphersuite(0xC02F, "RSA", "ECDH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
223             case 0xC014: // ECDHE_RSA_WITH_AES_256_CBC_SHA
224                 return TLSCiphersuite(0xC014, "RSA", "ECDH", "AES-256", 32, 16, 0, "SHA-1", 20);
225             case 0xC028: // ECDHE_RSA_WITH_AES_256_CBC_SHA384
226                 return TLSCiphersuite(0xC028, "RSA", "ECDH", "AES-256", 32, 16, 0, "SHA-384", 48);
227             case 0xC030: // ECDHE_RSA_WITH_AES_256_GCM_SHA384
228                 return TLSCiphersuite(0xC030, "RSA", "ECDH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
229             case 0xC076: // ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
230                 return TLSCiphersuite(0xC076, "RSA", "ECDH", "Camellia-128", 16, 16, 0, "SHA-256", 32);
231             case 0xC08A: // ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
232                 return TLSCiphersuite(0xC08A, "RSA", "ECDH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
233             case 0xC077: // ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
234                 return TLSCiphersuite(0xC077, "RSA", "ECDH", "Camellia-256", 32, 16, 0, "SHA-384", 48);
235             case 0xC08B: // ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
236                 return TLSCiphersuite(0xC08B, "RSA", "ECDH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
237 			case 0xCC13: // ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
238 				return TLSCiphersuite(0xCC13, "RSA", "ECDH", "ChaCha20Poly1305", 32, 0, 0, "AEAD", 0, "SHA-256");
239             case 0xC011: // ECDHE_RSA_WITH_RC4_128_SHA
240                 return TLSCiphersuite(0xC011, "RSA", "ECDH", "RC4", 16, 0, 0, "SHA-1", 20);
241             case 0xC017: // ECDH_anon_WITH_3DES_EDE_CBC_SHA
242                 return TLSCiphersuite(0xC017, "", "ECDH", "3DES", 24, 8, 0, "SHA-1", 20);
243             case 0xC018: // ECDH_anon_WITH_AES_128_CBC_SHA
244                 return TLSCiphersuite(0xC018, "", "ECDH", "AES-128", 16, 16, 0, "SHA-1", 20);
245             case 0xC019: // ECDH_anon_WITH_AES_256_CBC_SHA
246                 return TLSCiphersuite(0xC019, "", "ECDH", "AES-256", 32, 16, 0, "SHA-1", 20);
247             case 0xC016: // ECDH_anon_WITH_RC4_128_SHA
248                 return TLSCiphersuite(0xC016, "", "ECDH", "RC4", 16, 0, 0, "SHA-1", 20);
249             case 0xC0AA: // PSK_DHE_WITH_AES_128_CCM_8
250                 return TLSCiphersuite(0xC0AA, "", "DHE_PSK", "AES-128/CCM-8", 16, 4, 8, "AEAD", 0, "SHA-256");
251             case 0xC0AB: // PSK_DHE_WITH_AES_256_CCM_8
252                 return TLSCiphersuite(0xC0AB, "", "DHE_PSK", "AES-256/CCM-8", 32, 4, 8, "AEAD", 0, "SHA-256");
253             case 0x008B: // PSK_WITH_3DES_EDE_CBC_SHA
254                 return TLSCiphersuite(0x008B, "", "PSK", "3DES", 24, 8, 0, "SHA-1", 20);
255             case 0x008C: // PSK_WITH_AES_128_CBC_SHA
256                 return TLSCiphersuite(0x008C, "", "PSK", "AES-128", 16, 16, 0, "SHA-1", 20);
257             case 0x00AE: // PSK_WITH_AES_128_CBC_SHA256
258                 return TLSCiphersuite(0x00AE, "", "PSK", "AES-128", 16, 16, 0, "SHA-256", 32);
259             case 0xC0A4: // PSK_WITH_AES_128_CCM
260                 return TLSCiphersuite(0xC0A4, "", "PSK", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256");
261             case 0xC0A8: // PSK_WITH_AES_128_CCM_8
262                 return TLSCiphersuite(0xC0A8, "", "PSK", "AES-128/CCM-8", 16, 4, 8, "AEAD", 0, "SHA-256");
263             case 0x00A8: // PSK_WITH_AES_128_GCM_SHA256
264                 return TLSCiphersuite(0x00A8, "", "PSK", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
265             case 0x008D: // PSK_WITH_AES_256_CBC_SHA
266                 return TLSCiphersuite(0x008D, "", "PSK", "AES-256", 32, 16, 0, "SHA-1", 20);
267             case 0x00AF: // PSK_WITH_AES_256_CBC_SHA384
268                 return TLSCiphersuite(0x00AF, "", "PSK", "AES-256", 32, 16, 0, "SHA-384", 48);
269             case 0xC0A5: // PSK_WITH_AES_256_CCM
270                 return TLSCiphersuite(0xC0A5, "", "PSK", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256");
271             case 0xC0A9: // PSK_WITH_AES_256_CCM_8
272                 return TLSCiphersuite(0xC0A9, "", "PSK", "AES-256/CCM-8", 32, 4, 8, "AEAD", 0, "SHA-256");
273             case 0x00A9: // PSK_WITH_AES_256_GCM_SHA384
274                 return TLSCiphersuite(0x00A9, "", "PSK", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
275             case 0xC094: // PSK_WITH_CAMELLIA_128_CBC_SHA256
276                 return TLSCiphersuite(0xC094, "", "PSK", "Camellia-128", 16, 16, 0, "SHA-256", 32);
277             case 0xC08E: // PSK_WITH_CAMELLIA_128_GCM_SHA256
278                 return TLSCiphersuite(0xC08E, "", "PSK", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
279             case 0xC095: // PSK_WITH_CAMELLIA_256_CBC_SHA384
280                 return TLSCiphersuite(0xC095, "", "PSK", "Camellia-256", 32, 16, 0, "SHA-384", 48);
281             case 0xC08F: // PSK_WITH_CAMELLIA_256_GCM_SHA384
282                 return TLSCiphersuite(0xC08F, "", "PSK", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
283             case 0x008A: // PSK_WITH_RC4_128_SHA
284                 return TLSCiphersuite(0x008A, "", "PSK", "RC4", 16, 0, 0, "SHA-1", 20);
285             case 0x000A: // RSA_WITH_3DES_EDE_CBC_SHA
286                 return TLSCiphersuite(0x000A, "RSA", "RSA", "3DES", 24, 8, 0, "SHA-1", 20);
287             case 0x002F: // RSA_WITH_AES_128_CBC_SHA
288                 return TLSCiphersuite(0x002F, "RSA", "RSA", "AES-128", 16, 16, 0, "SHA-1", 20);
289             case 0x003C: // RSA_WITH_AES_128_CBC_SHA256
290                 return TLSCiphersuite(0x003C, "RSA", "RSA", "AES-128", 16, 16, 0, "SHA-256", 32);
291             case 0xC09C: // RSA_WITH_AES_128_CCM
292                 return TLSCiphersuite(0xC09C, "RSA", "RSA", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256");
293             case 0xC0A0: // RSA_WITH_AES_128_CCM_8
294                 return TLSCiphersuite(0xC0A0, "RSA", "RSA", "AES-128/CCM-8", 16, 4, 8, "AEAD", 0, "SHA-256");
295             case 0x009C: // RSA_WITH_AES_128_GCM_SHA256
296                 return TLSCiphersuite(0x009C, "RSA", "RSA", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
297             case 0x0035: // RSA_WITH_AES_256_CBC_SHA
298                 return TLSCiphersuite(0x0035, "RSA", "RSA", "AES-256", 32, 16, 0, "SHA-1", 20);
299             case 0x003D: // RSA_WITH_AES_256_CBC_SHA256
300                 return TLSCiphersuite(0x003D, "RSA", "RSA", "AES-256", 32, 16, 0, "SHA-256", 32);
301             case 0xC09D: // RSA_WITH_AES_256_CCM
302                 return TLSCiphersuite(0xC09D, "RSA", "RSA", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256");
303             case 0xC0A1: // RSA_WITH_AES_256_CCM_8
304                 return TLSCiphersuite(0xC0A1, "RSA", "RSA", "AES-256/CCM-8", 32, 4, 8, "AEAD", 0, "SHA-256");
305             case 0x009D: // RSA_WITH_AES_256_GCM_SHA384
306                 return TLSCiphersuite(0x009D, "RSA", "RSA", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
307             case 0x0041: // RSA_WITH_CAMELLIA_128_CBC_SHA
308                 return TLSCiphersuite(0x0041, "RSA", "RSA", "Camellia-128", 16, 16, 0, "SHA-1", 20);
309             case 0x00BA: // RSA_WITH_CAMELLIA_128_CBC_SHA256
310                 return TLSCiphersuite(0x00BA, "RSA", "RSA", "Camellia-128", 16, 16, 0, "SHA-256", 32);
311             case 0xC07A: // RSA_WITH_CAMELLIA_128_GCM_SHA256
312                 return TLSCiphersuite(0xC07A, "RSA", "RSA", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
313             case 0x0084: // RSA_WITH_CAMELLIA_256_CBC_SHA
314                 return TLSCiphersuite(0x0084, "RSA", "RSA", "Camellia-256", 32, 16, 0, "SHA-1", 20);
315             case 0x00C0: // RSA_WITH_CAMELLIA_256_CBC_SHA256
316                 return TLSCiphersuite(0x00C0, "RSA", "RSA", "Camellia-256", 32, 16, 0, "SHA-256", 32);
317             case 0xC07B: // RSA_WITH_CAMELLIA_256_GCM_SHA384
318                 return TLSCiphersuite(0xC07B, "RSA", "RSA", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
319             case 0x0004: // RSA_WITH_RC4_128_MD5
320                 return TLSCiphersuite(0x0004, "RSA", "RSA", "RC4", 16, 0, 0, "MD5", 16);
321             case 0x0005: // RSA_WITH_RC4_128_SHA
322                 return TLSCiphersuite(0x0005, "RSA", "RSA", "RC4", 16, 0, 0, "SHA-1", 20);
323             case 0x0096: // RSA_WITH_SEED_CBC_SHA
324                 return TLSCiphersuite(0x0096, "RSA", "RSA", "SEED", 16, 16, 0, "SHA-1", 20);
325             case 0xC01C: // SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA
326                 return TLSCiphersuite(0xC01C, "DSA", "SRP_SHA", "3DES", 24, 8, 0, "SHA-1", 20);
327             case 0xC01F: // SRP_SHA_DSS_WITH_AES_128_CBC_SHA
328                 return TLSCiphersuite(0xC01F, "DSA", "SRP_SHA", "AES-128", 16, 16, 0, "SHA-1", 20);
329             case 0xC022: // SRP_SHA_DSS_WITH_AES_256_CBC_SHA
330                 return TLSCiphersuite(0xC022, "DSA", "SRP_SHA", "AES-256", 32, 16, 0, "SHA-1", 20);
331             case 0xC01B: // SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA
332                 return TLSCiphersuite(0xC01B, "RSA", "SRP_SHA", "3DES", 24, 8, 0, "SHA-1", 20);
333             case 0xC01E: // SRP_SHA_RSA_WITH_AES_128_CBC_SHA
334                 return TLSCiphersuite(0xC01E, "RSA", "SRP_SHA", "AES-128", 16, 16, 0, "SHA-1", 20);
335             case 0xC021: // SRP_SHA_RSA_WITH_AES_256_CBC_SHA
336                 return TLSCiphersuite(0xC021, "RSA", "SRP_SHA", "AES-256", 32, 16, 0, "SHA-1", 20);
337             case 0xC01A: // SRP_SHA_WITH_3DES_EDE_CBC_SHA
338                 return TLSCiphersuite(0xC01A, "", "SRP_SHA", "3DES", 24, 8, 0, "SHA-1", 20);
339             case 0xC01D: // SRP_SHA_WITH_AES_128_CBC_SHA
340                 return TLSCiphersuite(0xC01D, "", "SRP_SHA", "AES-128", 16, 16, 0, "SHA-1", 20);
341             case 0xC020: // SRP_SHA_WITH_AES_256_CBC_SHA
342                 return TLSCiphersuite(0xC020, "", "SRP_SHA", "AES-256", 32, 16, 0, "SHA-1", 20);
343 
344             default:
345                 return TLSCiphersuite.init; // some unknown ciphersuite
346         }
347     }
348 
349     /**
350     * Lookup a ciphersuite by name
351     * Params:
352     *  name = the name (eg TLS_RSA_WITH_RC4_128_SHA)
353     * Returns: ciphersuite object
354     */
355     static TLSCiphersuite byName(in string name)
356     {
357 		auto all_ciphersuites = allKnownCiphersuites();
358 		foreach (const ref TLSCiphersuite suite; all_ciphersuites)
359         {
360             if (suite.toString() == name)
361                 return suite;
362         }
363         
364         return TLSCiphersuite.init; // some unknown ciphersuite
365     }
366 
367     /**
368     * Generate a static list of all known ciphersuites and return it.
369     *
370     * Returns: list of all known ciphersuites
371     */
372     static const(TLSCiphersuite[]) allKnownCiphersuites()
373     {
374         static Vector!TLSCiphersuite all_ciphersuites;
375         static bool initialized;
376         if (!initialized) {
377             initialized = true;
378             all_ciphersuites = gatherKnownCiphersuites();
379         }
380         return cast(const)all_ciphersuites[];
381     }
382 
383     /**
384     * Formats the ciphersuite back to an RFC-style ciphersuite string
385     * Returns: RFC ciphersuite string identifier
386     */
387     string toString() const
388     {
389         if (m_cipher_keylen == 0)
390             throw new Exception("toString - no value set");
391         Appender!string output;
392         
393         output ~= "TLS_";
394         
395         if (kexAlgo() != "RSA")
396         {
397             if (kexAlgo() == "DH")
398                 output ~= "DHE";
399             else if (kexAlgo() == "ECDH")
400                 output ~= "ECDHE";
401             else
402                 output ~= kexAlgo();
403             
404             output ~= '_';
405         }
406         
407         if (sigAlgo() == "DSA")
408             output ~= "DSS_";
409         else if (sigAlgo() != "")
410             output ~= sigAlgo() ~ '_';
411         
412         output ~= "WITH_";
413         
414         if (cipherAlgo() == "RC4")
415         {
416             output ~= "RC4_128_";
417         }
418 		else if(cipherAlgo() == "ChaCha20Poly1305")
419 		{
420 			output ~= "CHACHA20_POLY1305_";
421 		}
422         else
423         {
424             if (cipherAlgo() == "3DES")
425                 output ~= "3DES_EDE";
426             else if (cipherAlgo().find("Camellia") == -1)
427                 output ~= "CAMELLIA_" ~ to!string(8*cipherKeylen());
428             else
429                 output ~= replaceChars(cipherAlgo(), ['-', '/'], '_');
430             
431             if (cipherAlgo().find("/") != -1)
432                 output ~= "_"; // some explicit mode already included
433             else
434                 output ~= "_CBC_";
435         }
436         
437         if (macAlgo() == "SHA-1")
438             output ~= "SHA";
439         else if (macAlgo() == "AEAD")
440             output ~= eraseChars(prfAlgo(), ['-']);
441         else
442             output ~= eraseChars(macAlgo(), ['-']);
443         
444         return output.data;
445     }
446 
447     /**
448     * Returns: ciphersuite number
449     */
450     ushort ciphersuiteCode() const { return m_ciphersuite_code; }
451 
452     /**
453     * Returns: true if this is a PSK ciphersuite
454     */
455     bool pskCiphersuite() const
456     {
457         return (kexAlgo() == "PSK" ||
458                 kexAlgo() == "DHE_PSK" ||
459                 kexAlgo() == "ECDHE_PSK");
460     }
461 
462     /**
463     * Returns: true if this is an ECC ciphersuite
464     */
465     bool eccCiphersuite() const
466     {
467         return (sigAlgo() == "ECDSA" || kexAlgo() == "ECDH" || kexAlgo() == "ECDHE_PSK");
468     }
469 
470     /**
471     * Returns: key exchange algorithm used by this ciphersuite
472     */
473     ref const(string) kexAlgo() const { return m_kex_algo; }
474 
475     /**
476     * Returns: signature algorithm used by this ciphersuite
477     */
478     ref const(string) sigAlgo() const { return m_sig_algo; }
479 
480     /**
481     * Returns: symmetric cipher algorithm used by this ciphersuite
482     */
483     ref const(string) cipherAlgo() const { return m_cipher_algo; }
484 
485     /**
486     * Returns: message authentication algorithm used by this ciphersuite
487     */
488     ref const(string) macAlgo() const { return m_mac_algo; }
489 
490     ref const(string) prfAlgo() const
491     {
492         return (m_prf_algo != "") ? m_prf_algo : m_mac_algo;
493     }
494 
495     /**
496     * Returns: cipher key length used by this ciphersuite
497     */
498     size_t cipherKeylen() const { return m_cipher_keylen; }
499 
500     size_t nonceBytesFromHandshake() const { return m_nonce_bytes_from_handshake; }
501 
502     size_t nonceBytesFromRecord() const { return m_nonce_bytes_from_record; }
503 
504     size_t macKeylen() const { return m_mac_keylen; }
505 
506     /**
507     * Returns: true if this is a valid/known ciphersuite
508     */    
509     bool valid() const
510     {
511         if (!m_cipher_keylen) // uninitialized object
512             return false;
513         
514         AlgorithmFactory af = globalState().algorithmFactory();
515         
516         if (!af.prototypeHashFunction(prfAlgo()))
517             return false;
518         
519         if (macAlgo() == "AEAD")
520         {
521 			if (cipherAlgo() == "ChaCha20Poly1305")
522 			{
523 				static if (!BOTAN_HAS_AEAD_CHACHA20_POLY1305) {
524 					return false;
525 				}
526 			} 
527 			else {
528 	            auto cipher_and_mode = splitter(cipherAlgo(), '/');
529 	            assert(cipher_and_mode.length == 2, "Expected format for AEAD algo");
530 	            if (!af.prototypeBlockCipher(cipher_and_mode[0]))
531 	                return false;
532 	            
533 	            const auto mode = cipher_and_mode[1];
534 	            
535 	            static if (!BOTAN_HAS_AEAD_CCM) {
536 	                if (mode == "CCM" || mode == "CCM-8")
537 	                    return false;
538 	            }
539 	            
540 	            static if (!BOTAN_HAS_AEAD_GCM) {
541 	                if (mode == "GCM")
542 	                    return false;
543 	            }
544 	            
545 	            static if (!BOTAN_HAS_AEAD_OCB) {
546 	                if (mode == "OCB")
547 	                    return false;
548 	            }
549 			}
550         }
551         else
552         {
553             if (!af.prototypeBlockCipher(cipherAlgo()) &&
554                 !af.prototypeStreamCipher(cipherAlgo()))
555                 return false;
556             
557             if (!af.prototypeHashFunction(macAlgo()))
558                 return false;
559         }
560         
561         if (kexAlgo() == "SRP_SHA")
562         {
563             static if (!BOTAN_HAS_SRP6) {
564                 return false;
565             }
566         }
567         else if (kexAlgo() == "ECDH" || kexAlgo() == "ECDHE_PSK")
568         {
569             static if (!BOTAN_HAS_ECDH) {
570                 return false;
571             }
572         }
573         else if (kexAlgo() == "DH" || kexAlgo() == "DHE_PSK")
574         {
575             static if (!BOTAN_HAS_DIFFIE_HELLMAN) {
576                 return false;
577             }
578         }
579         
580         if (sigAlgo() == "DSA")
581         {
582             static if (!BOTAN_HAS_DSA) {
583                 return false;
584             }
585         }
586         else if (sigAlgo() == "ECDSA")
587         {
588             static if (!BOTAN_HAS_ECDSA) {
589                 return false;
590             }
591         }
592         else if (sigAlgo() == "RSA")
593         {
594             static if (!BOTAN_HAS_RSA) {
595                 return false;
596             }
597         }
598         
599         return true;
600     }
601 private:
602     this(ushort ciphersuite_code,
603          string sig_algo,
604          string kex_algo,
605          string cipher_algo,
606          size_t cipher_keylen,
607          size_t nonce_bytes_from_handshake,
608          size_t nonce_bytes_from_record,
609          string mac_algo,
610          size_t mac_keylen,
611          string prf_algo = "")
612     {
613         m_ciphersuite_code = ciphersuite_code;
614         m_sig_algo = sig_algo;
615         m_kex_algo = kex_algo;
616         m_prf_algo = prf_algo;
617         m_cipher_algo = cipher_algo;
618         m_cipher_keylen = cipher_keylen;
619         m_nonce_bytes_from_handshake = nonce_bytes_from_handshake;
620         m_nonce_bytes_from_record = nonce_bytes_from_record;
621         m_mac_algo = mac_algo;
622         m_mac_keylen = mac_keylen;
623     }
624 
625     /*
626     * This way all work happens at the constuctor call, and we can
627     * rely on that happening only once in D
628     */
629     static Vector!TLSCiphersuite gatherKnownCiphersuites()
630     {
631         Vector!TLSCiphersuite ciphersuites;
632         
633         for (size_t i = 0; i <= 0xFFFF; ++i)
634         {
635             TLSCiphersuite suite = byId(cast(ushort)i);
636             
637             if (suite.valid())
638                 ciphersuites.pushBack(suite);
639         }
640         
641         return ciphersuites;
642     }
643 
644     ushort m_ciphersuite_code;
645 
646     string m_sig_algo;
647     string m_kex_algo;
648     string m_prf_algo;
649     string m_cipher_algo;
650 
651     size_t m_cipher_keylen;
652     size_t m_cipher_ivlen;
653     size_t m_nonce_bytes_from_handshake;
654     size_t m_nonce_bytes_from_record;
655     string m_mac_algo;
656     size_t m_mac_keylen;
657 }
658 
659 ptrdiff_t find(string str, string str2) {
660     import std.algorithm : countUntil;
661     return str.countUntil(str2);
662 }