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 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 0xCC13: // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_OLD
132 				return TLSCiphersuite(0xCC13, "RSA", "ECDH", "ChaCha20Poly1305", 32, 0, 0, "AEAD", 0, "SHA-256");
133 			case 0xCCA8: // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
134 				return TLSCiphersuite(0xCCA8, "RSA", "ECDH", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256");
135 			case 0xCC14: // ECDHE_ECDSA_WITH_CHACHA20_POLY1305_OLD
136 				return TLSCiphersuite(0xCC14, "ECDSA", "ECDH", "ChaCha20Poly1305", 32, 0, 0, "AEAD", 0, "SHA-256");
137 			case 0xCCA9: // ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 
138 				return TLSCiphersuite(0xCCA9, "ECDSA", "ECDH", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256");
139 			case 0xCC15: // DHE_RSA_WITH_CHACHA20_POLY1305_OLD
140 				return TLSCiphersuite(0xCC15, "RSA", "DH", "ChaCha20Poly1305", 32, 0, 0, "AEAD", 0, "SHA-256");
141 			case 0xCCAA: // DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
142 				return TLSCiphersuite(0xCCAA, "RSA", "DH", "ChaCha20Poly1305", 32, 12, 0, "AEAD", 0, "SHA-256");
143             case 0x009A: // DHE_RSA_WITH_SEED_CBC_SHA
144                 return TLSCiphersuite(0x009A, "RSA", "DH", "SEED", 16, 16, 0, "SHA-1", 20);
145             case 0x001B: // DH_anon_WITH_3DES_EDE_CBC_SHA
146                 return TLSCiphersuite(0x001B, "", "DH", "3DES", 24, 8, 0, "SHA-1", 20);
147             case 0x0034: // DH_anon_WITH_AES_128_CBC_SHA
148                 return TLSCiphersuite(0x0034, "", "DH", "AES-128", 16, 16, 0, "SHA-1", 20);
149             case 0x006C: // DH_anon_WITH_AES_128_CBC_SHA256
150                 return TLSCiphersuite(0x006C, "", "DH", "AES-128", 16, 16, 0, "SHA-256", 32);
151             case 0x00A6: // DH_anon_WITH_AES_128_GCM_SHA256
152                 return TLSCiphersuite(0x00A6, "", "DH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
153             case 0x003A: // DH_anon_WITH_AES_256_CBC_SHA
154                 return TLSCiphersuite(0x003A, "", "DH", "AES-256", 32, 16, 0, "SHA-1", 20);
155             case 0x006D: // DH_anon_WITH_AES_256_CBC_SHA256
156                 return TLSCiphersuite(0x006D, "", "DH", "AES-256", 32, 16, 0, "SHA-256", 32);
157             case 0x00A7: // DH_anon_WITH_AES_256_GCM_SHA384
158                 return TLSCiphersuite(0x00A7, "", "DH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
159             case 0x0046: // DH_anon_WITH_CAMELLIA_128_CBC_SHA
160                 return TLSCiphersuite(0x0046, "", "DH", "Camellia-128", 16, 16, 0, "SHA-1", 20);
161             case 0x00BF: // DH_anon_WITH_CAMELLIA_128_CBC_SHA256
162                 return TLSCiphersuite(0x00BF, "", "DH", "Camellia-128", 16, 16, 0, "SHA-256", 32);
163             case 0xC084: // DH_anon_WITH_CAMELLIA_128_GCM_SHA256
164                 return TLSCiphersuite(0xC084, "", "DH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
165             case 0x0089: // DH_anon_WITH_CAMELLIA_256_CBC_SHA
166                 return TLSCiphersuite(0x0089, "", "DH", "Camellia-256", 32, 16, 0, "SHA-1", 20);
167             case 0x00C5: // DH_anon_WITH_CAMELLIA_256_CBC_SHA256
168                 return TLSCiphersuite(0x00C5, "", "DH", "Camellia-256", 32, 16, 0, "SHA-256", 32);
169             case 0xC085: // DH_anon_WITH_CAMELLIA_256_GCM_SHA384
170                 return TLSCiphersuite(0xC085, "", "DH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
171             case 0x0018: // DH_anon_WITH_RC4_128_MD5
172                 return TLSCiphersuite(0x0018, "", "DH", "RC4", 16, 0, 0, "MD5", 16);
173             case 0x009B: // DH_anon_WITH_SEED_CBC_SHA
174                 return TLSCiphersuite(0x009B, "", "DH", "SEED", 16, 16, 0, "SHA-1", 20);
175             case 0xC008: // ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
176                 return TLSCiphersuite(0xC008, "ECDSA", "ECDH", "3DES", 24, 8, 0, "SHA-1", 20);
177             case 0xC009: // ECDHE_ECDSA_WITH_AES_128_CBC_SHA
178                 return TLSCiphersuite(0xC009, "ECDSA", "ECDH", "AES-128", 16, 16, 0, "SHA-1", 20);
179             case 0xC023: // ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
180                 return TLSCiphersuite(0xC023, "ECDSA", "ECDH", "AES-128", 16, 16, 0, "SHA-256", 32);
181             case 0xC0AC: // ECDHE_ECDSA_WITH_AES_128_CCM
182                 return TLSCiphersuite(0xC0AC, "ECDSA", "ECDH", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256");
183             case 0xC0AE: // ECDHE_ECDSA_WITH_AES_128_CCM_8
184                 return TLSCiphersuite(0xC0AE, "ECDSA", "ECDH", "AES-128/CCM-8", 16, 4, 8, "AEAD", 0, "SHA-256");
185             case 0xC02B: // ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
186                 return TLSCiphersuite(0xC02B, "ECDSA", "ECDH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
187             case 0xC00A: // ECDHE_ECDSA_WITH_AES_256_CBC_SHA
188                 return TLSCiphersuite(0xC00A, "ECDSA", "ECDH", "AES-256", 32, 16, 0, "SHA-1", 20);
189             case 0xC024: // ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
190                 return TLSCiphersuite(0xC024, "ECDSA", "ECDH", "AES-256", 32, 16, 0, "SHA-384", 48);
191             case 0xC0AD: // ECDHE_ECDSA_WITH_AES_256_CCM
192                 return TLSCiphersuite(0xC0AD, "ECDSA", "ECDH", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256");
193             case 0xC0AF: // ECDHE_ECDSA_WITH_AES_256_CCM_8
194                 return TLSCiphersuite(0xC0AF, "ECDSA", "ECDH", "AES-256/CCM-8", 32, 4, 8, "AEAD", 0, "SHA-256");
195             case 0xC02C: // ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
196                 return TLSCiphersuite(0xC02C, "ECDSA", "ECDH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
197             case 0xC072: // ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
198                 return TLSCiphersuite(0xC072, "ECDSA", "ECDH", "Camellia-128", 16, 16, 0, "SHA-256", 32);
199             case 0xC086: // ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
200                 return TLSCiphersuite(0xC086, "ECDSA", "ECDH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
201             case 0xC073: // ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
202                 return TLSCiphersuite(0xC073, "ECDSA", "ECDH", "Camellia-256", 32, 16, 0, "SHA-384", 48);
203             case 0xC087: // ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
204                 return TLSCiphersuite(0xC087, "ECDSA", "ECDH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
205             case 0xC007: // ECDHE_ECDSA_WITH_RC4_128_SHA
206                 return TLSCiphersuite(0xC007, "ECDSA", "ECDH", "RC4", 16, 0, 0, "SHA-1", 20);
207             case 0xC034: // ECDHE_PSK_WITH_3DES_EDE_CBC_SHA
208                 return TLSCiphersuite(0xC034, "", "ECDHE_PSK", "3DES", 24, 8, 0, "SHA-1", 20);
209             case 0xC035: // ECDHE_PSK_WITH_AES_128_CBC_SHA
210                 return TLSCiphersuite(0xC035, "", "ECDHE_PSK", "AES-128", 16, 16, 0, "SHA-1", 20);
211             case 0xC037: // ECDHE_PSK_WITH_AES_128_CBC_SHA256
212                 return TLSCiphersuite(0xC037, "", "ECDHE_PSK", "AES-128", 16, 16, 0, "SHA-256", 32);
213             case 0xC036: // ECDHE_PSK_WITH_AES_256_CBC_SHA
214                 return TLSCiphersuite(0xC036, "", "ECDHE_PSK", "AES-256", 32, 16, 0, "SHA-1", 20);
215             case 0xC038: // ECDHE_PSK_WITH_AES_256_CBC_SHA384
216                 return TLSCiphersuite(0xC038, "", "ECDHE_PSK", "AES-256", 32, 16, 0, "SHA-384", 48);
217             case 0xC09A: // ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256
218                 return TLSCiphersuite(0xC09A, "", "ECDHE_PSK", "Camellia-128", 16, 16, 0, "SHA-256", 32);
219             case 0xC09B: // ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384
220                 return TLSCiphersuite(0xC09B, "", "ECDHE_PSK", "Camellia-256", 32, 16, 0, "SHA-384", 48);
221             case 0xC033: // ECDHE_PSK_WITH_RC4_128_SHA
222                 return TLSCiphersuite(0xC033, "", "ECDHE_PSK", "RC4", 16, 0, 0, "SHA-1", 20);
223             case 0xC012: // ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
224                 return TLSCiphersuite(0xC012, "RSA", "ECDH", "3DES", 24, 8, 0, "SHA-1", 20);
225             case 0xC013: // ECDHE_RSA_WITH_AES_128_CBC_SHA
226                 return TLSCiphersuite(0xC013, "RSA", "ECDH", "AES-128", 16, 16, 0, "SHA-1", 20);
227             case 0xC027: // ECDHE_RSA_WITH_AES_128_CBC_SHA256
228                 return TLSCiphersuite(0xC027, "RSA", "ECDH", "AES-128", 16, 16, 0, "SHA-256", 32);
229             case 0xC02F: // ECDHE_RSA_WITH_AES_128_GCM_SHA256
230                 return TLSCiphersuite(0xC02F, "RSA", "ECDH", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
231             case 0xC014: // ECDHE_RSA_WITH_AES_256_CBC_SHA
232                 return TLSCiphersuite(0xC014, "RSA", "ECDH", "AES-256", 32, 16, 0, "SHA-1", 20);
233             case 0xC028: // ECDHE_RSA_WITH_AES_256_CBC_SHA384
234                 return TLSCiphersuite(0xC028, "RSA", "ECDH", "AES-256", 32, 16, 0, "SHA-384", 48);
235             case 0xC030: // ECDHE_RSA_WITH_AES_256_GCM_SHA384
236                 return TLSCiphersuite(0xC030, "RSA", "ECDH", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
237             case 0xC076: // ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
238                 return TLSCiphersuite(0xC076, "RSA", "ECDH", "Camellia-128", 16, 16, 0, "SHA-256", 32);
239             case 0xC08A: // ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
240                 return TLSCiphersuite(0xC08A, "RSA", "ECDH", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
241             case 0xC077: // ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
242                 return TLSCiphersuite(0xC077, "RSA", "ECDH", "Camellia-256", 32, 16, 0, "SHA-384", 48);
243             case 0xC08B: // ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
244                 return TLSCiphersuite(0xC08B, "RSA", "ECDH", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
245             case 0xC011: // ECDHE_RSA_WITH_RC4_128_SHA
246                 return TLSCiphersuite(0xC011, "RSA", "ECDH", "RC4", 16, 0, 0, "SHA-1", 20);
247             case 0xC017: // ECDH_anon_WITH_3DES_EDE_CBC_SHA
248                 return TLSCiphersuite(0xC017, "", "ECDH", "3DES", 24, 8, 0, "SHA-1", 20);
249             case 0xC018: // ECDH_anon_WITH_AES_128_CBC_SHA
250                 return TLSCiphersuite(0xC018, "", "ECDH", "AES-128", 16, 16, 0, "SHA-1", 20);
251             case 0xC019: // ECDH_anon_WITH_AES_256_CBC_SHA
252                 return TLSCiphersuite(0xC019, "", "ECDH", "AES-256", 32, 16, 0, "SHA-1", 20);
253             case 0xC016: // ECDH_anon_WITH_RC4_128_SHA
254                 return TLSCiphersuite(0xC016, "", "ECDH", "RC4", 16, 0, 0, "SHA-1", 20);
255             case 0xC0AA: // PSK_DHE_WITH_AES_128_CCM_8
256                 return TLSCiphersuite(0xC0AA, "", "DHE_PSK", "AES-128/CCM-8", 16, 4, 8, "AEAD", 0, "SHA-256");
257             case 0xC0AB: // PSK_DHE_WITH_AES_256_CCM_8
258                 return TLSCiphersuite(0xC0AB, "", "DHE_PSK", "AES-256/CCM-8", 32, 4, 8, "AEAD", 0, "SHA-256");
259             case 0x008B: // PSK_WITH_3DES_EDE_CBC_SHA
260                 return TLSCiphersuite(0x008B, "", "PSK", "3DES", 24, 8, 0, "SHA-1", 20);
261             case 0x008C: // PSK_WITH_AES_128_CBC_SHA
262                 return TLSCiphersuite(0x008C, "", "PSK", "AES-128", 16, 16, 0, "SHA-1", 20);
263             case 0x00AE: // PSK_WITH_AES_128_CBC_SHA256
264                 return TLSCiphersuite(0x00AE, "", "PSK", "AES-128", 16, 16, 0, "SHA-256", 32);
265             case 0xC0A4: // PSK_WITH_AES_128_CCM
266                 return TLSCiphersuite(0xC0A4, "", "PSK", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256");
267             case 0xC0A8: // PSK_WITH_AES_128_CCM_8
268                 return TLSCiphersuite(0xC0A8, "", "PSK", "AES-128/CCM-8", 16, 4, 8, "AEAD", 0, "SHA-256");
269             case 0x00A8: // PSK_WITH_AES_128_GCM_SHA256
270                 return TLSCiphersuite(0x00A8, "", "PSK", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
271             case 0x008D: // PSK_WITH_AES_256_CBC_SHA
272                 return TLSCiphersuite(0x008D, "", "PSK", "AES-256", 32, 16, 0, "SHA-1", 20);
273             case 0x00AF: // PSK_WITH_AES_256_CBC_SHA384
274                 return TLSCiphersuite(0x00AF, "", "PSK", "AES-256", 32, 16, 0, "SHA-384", 48);
275             case 0xC0A5: // PSK_WITH_AES_256_CCM
276                 return TLSCiphersuite(0xC0A5, "", "PSK", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256");
277             case 0xC0A9: // PSK_WITH_AES_256_CCM_8
278                 return TLSCiphersuite(0xC0A9, "", "PSK", "AES-256/CCM-8", 32, 4, 8, "AEAD", 0, "SHA-256");
279             case 0x00A9: // PSK_WITH_AES_256_GCM_SHA384
280                 return TLSCiphersuite(0x00A9, "", "PSK", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
281             case 0xC094: // PSK_WITH_CAMELLIA_128_CBC_SHA256
282                 return TLSCiphersuite(0xC094, "", "PSK", "Camellia-128", 16, 16, 0, "SHA-256", 32);
283             case 0xC08E: // PSK_WITH_CAMELLIA_128_GCM_SHA256
284                 return TLSCiphersuite(0xC08E, "", "PSK", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
285             case 0xC095: // PSK_WITH_CAMELLIA_256_CBC_SHA384
286                 return TLSCiphersuite(0xC095, "", "PSK", "Camellia-256", 32, 16, 0, "SHA-384", 48);
287             case 0xC08F: // PSK_WITH_CAMELLIA_256_GCM_SHA384
288                 return TLSCiphersuite(0xC08F, "", "PSK", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
289             case 0x008A: // PSK_WITH_RC4_128_SHA
290                 return TLSCiphersuite(0x008A, "", "PSK", "RC4", 16, 0, 0, "SHA-1", 20);
291             case 0x000A: // RSA_WITH_3DES_EDE_CBC_SHA
292                 return TLSCiphersuite(0x000A, "RSA", "RSA", "3DES", 24, 8, 0, "SHA-1", 20);
293             case 0x002F: // RSA_WITH_AES_128_CBC_SHA
294                 return TLSCiphersuite(0x002F, "RSA", "RSA", "AES-128", 16, 16, 0, "SHA-1", 20);
295             case 0x003C: // RSA_WITH_AES_128_CBC_SHA256
296                 return TLSCiphersuite(0x003C, "RSA", "RSA", "AES-128", 16, 16, 0, "SHA-256", 32);
297             case 0xC09C: // RSA_WITH_AES_128_CCM
298                 return TLSCiphersuite(0xC09C, "RSA", "RSA", "AES-128/CCM", 16, 4, 8, "AEAD", 0, "SHA-256");
299             case 0xC0A0: // RSA_WITH_AES_128_CCM_8
300                 return TLSCiphersuite(0xC0A0, "RSA", "RSA", "AES-128/CCM-8", 16, 4, 8, "AEAD", 0, "SHA-256");
301             case 0x009C: // RSA_WITH_AES_128_GCM_SHA256
302                 return TLSCiphersuite(0x009C, "RSA", "RSA", "AES-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
303             case 0x0035: // RSA_WITH_AES_256_CBC_SHA
304                 return TLSCiphersuite(0x0035, "RSA", "RSA", "AES-256", 32, 16, 0, "SHA-1", 20);
305             case 0x003D: // RSA_WITH_AES_256_CBC_SHA256
306                 return TLSCiphersuite(0x003D, "RSA", "RSA", "AES-256", 32, 16, 0, "SHA-256", 32);
307             case 0xC09D: // RSA_WITH_AES_256_CCM
308                 return TLSCiphersuite(0xC09D, "RSA", "RSA", "AES-256/CCM", 32, 4, 8, "AEAD", 0, "SHA-256");
309             case 0xC0A1: // RSA_WITH_AES_256_CCM_8
310                 return TLSCiphersuite(0xC0A1, "RSA", "RSA", "AES-256/CCM-8", 32, 4, 8, "AEAD", 0, "SHA-256");
311             case 0x009D: // RSA_WITH_AES_256_GCM_SHA384
312                 return TLSCiphersuite(0x009D, "RSA", "RSA", "AES-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
313             case 0x0041: // RSA_WITH_CAMELLIA_128_CBC_SHA
314                 return TLSCiphersuite(0x0041, "RSA", "RSA", "Camellia-128", 16, 16, 0, "SHA-1", 20);
315             case 0x00BA: // RSA_WITH_CAMELLIA_128_CBC_SHA256
316                 return TLSCiphersuite(0x00BA, "RSA", "RSA", "Camellia-128", 16, 16, 0, "SHA-256", 32);
317             case 0xC07A: // RSA_WITH_CAMELLIA_128_GCM_SHA256
318                 return TLSCiphersuite(0xC07A, "RSA", "RSA", "Camellia-128/GCM", 16, 4, 8, "AEAD", 0, "SHA-256");
319             case 0x0084: // RSA_WITH_CAMELLIA_256_CBC_SHA
320                 return TLSCiphersuite(0x0084, "RSA", "RSA", "Camellia-256", 32, 16, 0, "SHA-1", 20);
321             case 0x00C0: // RSA_WITH_CAMELLIA_256_CBC_SHA256
322                 return TLSCiphersuite(0x00C0, "RSA", "RSA", "Camellia-256", 32, 16, 0, "SHA-256", 32);
323             case 0xC07B: // RSA_WITH_CAMELLIA_256_GCM_SHA384
324                 return TLSCiphersuite(0xC07B, "RSA", "RSA", "Camellia-256/GCM", 32, 4, 8, "AEAD", 0, "SHA-384");
325             case 0x0004: // RSA_WITH_RC4_128_MD5
326                 return TLSCiphersuite(0x0004, "RSA", "RSA", "RC4", 16, 0, 0, "MD5", 16);
327             case 0x0005: // RSA_WITH_RC4_128_SHA
328                 return TLSCiphersuite(0x0005, "RSA", "RSA", "RC4", 16, 0, 0, "SHA-1", 20);
329             case 0x0096: // RSA_WITH_SEED_CBC_SHA
330                 return TLSCiphersuite(0x0096, "RSA", "RSA", "SEED", 16, 16, 0, "SHA-1", 20);
331             case 0xC01C: // SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA
332                 return TLSCiphersuite(0xC01C, "DSA", "SRP_SHA", "3DES", 24, 8, 0, "SHA-1", 20);
333             case 0xC01F: // SRP_SHA_DSS_WITH_AES_128_CBC_SHA
334                 return TLSCiphersuite(0xC01F, "DSA", "SRP_SHA", "AES-128", 16, 16, 0, "SHA-1", 20);
335             case 0xC022: // SRP_SHA_DSS_WITH_AES_256_CBC_SHA
336                 return TLSCiphersuite(0xC022, "DSA", "SRP_SHA", "AES-256", 32, 16, 0, "SHA-1", 20);
337             case 0xC01B: // SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA
338                 return TLSCiphersuite(0xC01B, "RSA", "SRP_SHA", "3DES", 24, 8, 0, "SHA-1", 20);
339             case 0xC01E: // SRP_SHA_RSA_WITH_AES_128_CBC_SHA
340                 return TLSCiphersuite(0xC01E, "RSA", "SRP_SHA", "AES-128", 16, 16, 0, "SHA-1", 20);
341             case 0xC021: // SRP_SHA_RSA_WITH_AES_256_CBC_SHA
342                 return TLSCiphersuite(0xC021, "RSA", "SRP_SHA", "AES-256", 32, 16, 0, "SHA-1", 20);
343             case 0xC01A: // SRP_SHA_WITH_3DES_EDE_CBC_SHA
344                 return TLSCiphersuite(0xC01A, "", "SRP_SHA", "3DES", 24, 8, 0, "SHA-1", 20);
345             case 0xC01D: // SRP_SHA_WITH_AES_128_CBC_SHA
346                 return TLSCiphersuite(0xC01D, "", "SRP_SHA", "AES-128", 16, 16, 0, "SHA-1", 20);
347             case 0xC020: // SRP_SHA_WITH_AES_256_CBC_SHA
348                 return TLSCiphersuite(0xC020, "", "SRP_SHA", "AES-256", 32, 16, 0, "SHA-1", 20);
349 
350             default:
351                 return TLSCiphersuite.init; // some unknown ciphersuite
352         }
353     }
354 
355     /**
356     * Lookup a ciphersuite by name
357     * Params:
358     *  name = the name (eg TLS_RSA_WITH_RC4_128_SHA)
359     * Returns: ciphersuite object
360     */
361     static TLSCiphersuite byName(in string name)
362     {
363 		auto all_ciphersuites = allKnownCiphersuites();
364 		foreach (const ref TLSCiphersuite suite; all_ciphersuites)
365         {
366             if (suite.toString() == name)
367                 return suite;
368         }
369         
370         return TLSCiphersuite.init; // some unknown ciphersuite
371     }
372 
373     /**
374     * Generate a static list of all known ciphersuites and return it.
375     *
376     * Returns: list of all known ciphersuites
377     */
378     static const(TLSCiphersuite[]) allKnownCiphersuites()
379     {
380         static Vector!TLSCiphersuite all_ciphersuites;
381         static bool initialized;
382         if (!initialized) {
383             initialized = true;
384             all_ciphersuites = gatherKnownCiphersuites();
385         }
386         return cast(const)all_ciphersuites[];
387     }
388 
389     /**
390     * Formats the ciphersuite back to an RFC-style ciphersuite string
391     * Returns: RFC ciphersuite string identifier
392     */
393     string toString() const
394     {
395         if (m_cipher_keylen == 0)
396             throw new Exception("toString - no value set");
397         Appender!string output;
398         
399         output ~= "TLS_";
400         
401         if (kexAlgo() != "RSA")
402         {
403             if (kexAlgo() == "DH")
404                 output ~= "DHE";
405             else if (kexAlgo() == "ECDH")
406                 output ~= "ECDHE";
407             else
408                 output ~= kexAlgo();
409             
410             output ~= '_';
411         }
412         
413         if (sigAlgo() == "DSA")
414             output ~= "DSS_";
415         else if (sigAlgo() != "")
416             output ~= sigAlgo() ~ '_';
417         
418         output ~= "WITH_";
419         
420         if (cipherAlgo() == "RC4")
421         {
422             output ~= "RC4_128_";
423         }
424 		else if(cipherAlgo() == "ChaCha20Poly1305")
425 		{
426 			output ~= "CHACHA20_POLY1305_";
427 		}
428         else
429         {
430             if (cipherAlgo() == "3DES")
431                 output ~= "3DES_EDE";
432             else if (cipherAlgo().find("Camellia") == -1)
433                 output ~= "CAMELLIA_" ~ to!string(8*cipherKeylen());
434             else
435                 output ~= replaceChars(cipherAlgo(), ['-', '/'], '_');
436             
437             if (cipherAlgo().find("/") != -1)
438                 output ~= "_"; // some explicit mode already included
439             else
440                 output ~= "_CBC_";
441         }
442         
443         if (macAlgo() == "SHA-1")
444             output ~= "SHA";
445         else if (macAlgo() == "AEAD")
446             output ~= eraseChars(prfAlgo(), ['-']);
447         else
448             output ~= eraseChars(macAlgo(), ['-']);
449         
450         return output.data;
451     }
452 
453     /**
454     * Returns: ciphersuite number
455     */
456     ushort ciphersuiteCode() const { return m_ciphersuite_code; }
457 
458     /**
459     * Returns: true if this is a PSK ciphersuite
460     */
461     bool pskCiphersuite() const
462     {
463         return (kexAlgo() == "PSK" ||
464                 kexAlgo() == "DHE_PSK" ||
465                 kexAlgo() == "ECDHE_PSK");
466     }
467 
468     /**
469     * Returns: true if this is an ECC ciphersuite
470     */
471     bool eccCiphersuite() const
472     {
473         return (sigAlgo() == "ECDSA" || kexAlgo() == "ECDH" || kexAlgo() == "ECDHE_PSK");
474     }
475 
476     /**
477     * Returns: key exchange algorithm used by this ciphersuite
478     */
479     ref const(string) kexAlgo() const { return m_kex_algo; }
480 
481     /**
482     * Returns: signature algorithm used by this ciphersuite
483     */
484     ref const(string) sigAlgo() const { return m_sig_algo; }
485 
486     /**
487     * Returns: symmetric cipher algorithm used by this ciphersuite
488     */
489     ref const(string) cipherAlgo() const { return m_cipher_algo; }
490 
491     /**
492     * Returns: message authentication algorithm used by this ciphersuite
493     */
494     ref const(string) macAlgo() const { return m_mac_algo; }
495 
496     ref const(string) prfAlgo() const
497     {
498         return (m_prf_algo != "") ? m_prf_algo : m_mac_algo;
499     }
500 
501     /**
502     * Returns: cipher key length used by this ciphersuite
503     */
504     size_t cipherKeylen() const { return m_cipher_keylen; }
505 
506     size_t nonceBytesFromHandshake() const { return m_nonce_bytes_from_handshake; }
507 
508     size_t nonceBytesFromRecord() const { return m_nonce_bytes_from_record; }
509 
510     size_t macKeylen() const { return m_mac_keylen; }
511 
512     /**
513     * Returns: true if this is a valid/known ciphersuite
514     */    
515     bool valid() const
516     {
517         if (!m_cipher_keylen) // uninitialized object
518             return false;
519         
520         AlgorithmFactory af = globalState().algorithmFactory();
521         
522         if (!af.prototypeHashFunction(prfAlgo()))
523             return false;
524         
525         if (macAlgo() == "AEAD")
526         {
527 			if (cipherAlgo() == "ChaCha20Poly1305")
528 			{
529 				static if (!BOTAN_HAS_AEAD_CHACHA20_POLY1305) {
530 					return false;
531 				}
532 			} 
533 			else {
534 				static string last_cipher_algo;
535 				static Vector!string last_cipher_and_mode;
536 				Vector!string cipher_and_mode;
537 				if (last_cipher_algo == cipherAlgo())
538 					cipher_and_mode = last_cipher_and_mode.dup;
539 				else {
540 					cipher_and_mode = splitter(cipherAlgo(), '/');
541 					last_cipher_and_mode = cipher_and_mode.dup;
542 					last_cipher_algo = cipherAlgo();
543 				}
544 	            assert(cipher_and_mode.length == 2, "Expected format for AEAD algo");
545 	            if (!af.prototypeBlockCipher(cipher_and_mode[0]))
546 	                return false;
547 	            
548 	            const auto mode = cipher_and_mode[1];
549 	            
550 	            static if (!BOTAN_HAS_AEAD_CCM) {
551 	                if (mode == "CCM" || mode == "CCM-8")
552 	                    return false;
553 	            }
554 	            
555 	            static if (!BOTAN_HAS_AEAD_GCM) {
556 	                if (mode == "GCM")
557 	                    return false;
558 	            }
559 	            
560 	            static if (!BOTAN_HAS_AEAD_OCB) {
561 	                if (mode == "OCB")
562 	                    return false;
563 	            }
564 			}
565         }
566         else
567         {
568             if (!af.prototypeBlockCipher(cipherAlgo()) &&
569                 !af.prototypeStreamCipher(cipherAlgo()))
570                 return false;
571             
572             if (!af.prototypeHashFunction(macAlgo()))
573                 return false;
574         }
575         
576         if (kexAlgo() == "SRP_SHA")
577         {
578             static if (!BOTAN_HAS_SRP6) {
579                 return false;
580             }
581         }
582         else if (kexAlgo() == "ECDH" || kexAlgo() == "ECDHE_PSK")
583         {
584             static if (!BOTAN_HAS_ECDH) {
585                 return false;
586             }
587         }
588         else if (kexAlgo() == "DH" || kexAlgo() == "DHE_PSK")
589         {
590             static if (!BOTAN_HAS_DIFFIE_HELLMAN) {
591                 return false;
592             }
593         }
594         
595         if (sigAlgo() == "DSA")
596         {
597             static if (!BOTAN_HAS_DSA) {
598                 return false;
599             }
600         }
601         else if (sigAlgo() == "ECDSA")
602         {
603             static if (!BOTAN_HAS_ECDSA) {
604                 return false;
605             }
606         }
607         else if (sigAlgo() == "RSA")
608         {
609             static if (!BOTAN_HAS_RSA) {
610                 return false;
611             }
612         }
613         
614         return true;
615     }
616 private:
617     this(ushort ciphersuite_code,
618          string sig_algo,
619          string kex_algo,
620          string cipher_algo,
621          size_t cipher_keylen,
622          size_t nonce_bytes_from_handshake,
623          size_t nonce_bytes_from_record,
624          string mac_algo,
625          size_t mac_keylen,
626          string prf_algo = "")
627     {
628         m_ciphersuite_code = ciphersuite_code;
629         m_sig_algo = sig_algo;
630         m_kex_algo = kex_algo;
631         m_prf_algo = prf_algo;
632         m_cipher_algo = cipher_algo;
633         m_cipher_keylen = cipher_keylen;
634         m_nonce_bytes_from_handshake = nonce_bytes_from_handshake;
635         m_nonce_bytes_from_record = nonce_bytes_from_record;
636         m_mac_algo = mac_algo;
637         m_mac_keylen = mac_keylen;
638     }
639 
640     /*
641     * This way all work happens at the constuctor call, and we can
642     * rely on that happening only once in D
643     */
644     static Vector!TLSCiphersuite gatherKnownCiphersuites()
645     {
646         Vector!TLSCiphersuite ciphersuites;
647         
648         for (size_t i = 0; i <= 0xFFFF; ++i)
649         {
650             TLSCiphersuite suite = byId(cast(ushort)i);
651             
652             if (suite.valid())
653                 ciphersuites.pushBack(suite);
654         }
655         
656         return ciphersuites;
657     }
658 
659     ushort m_ciphersuite_code;
660 
661     string m_sig_algo;
662     string m_kex_algo;
663     string m_prf_algo;
664     string m_cipher_algo;
665 
666     size_t m_cipher_keylen;
667     size_t m_cipher_ivlen;
668     size_t m_nonce_bytes_from_handshake;
669     size_t m_nonce_bytes_from_record;
670     string m_mac_algo;
671     size_t m_mac_keylen;
672 }
673 
674 ptrdiff_t find(string str, string str2) {
675     import std.algorithm : countUntil;
676     return str.countUntil(str2);
677 }