1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/ssl/ssl_cipher_suite_names.h"
6
7#include <stdlib.h>
8
9#include "base/logging.h"
10#include "base/strings/string_number_conversions.h"
11#include "base/strings/string_util.h"
12#include "net/ssl/ssl_connection_status_flags.h"
13
14// Rather than storing the names of all the ciphersuites we eliminate the
15// redundancy and break each cipher suite into a key exchange method, cipher
16// and mac. For all the ciphersuites in the IANA registry, we extract each of
17// those components from the name, number them and pack the result into a
18// 16-bit number thus:
19//   (MSB to LSB)
20//   <3 bits> unused
21//   <5 bits> key exchange
22//   <5 bits> cipher
23//   <3 bits> mac
24
25// The following tables were generated by ssl_cipher_suite_names_generate.go,
26// found in the same directory as this file.
27
28struct CipherSuite {
29  uint16 cipher_suite, encoded;
30};
31
32static const struct CipherSuite kCipherSuites[] = {
33  {0x0, 0x0},  // TLS_NULL_WITH_NULL_NULL
34  {0x1, 0x101},  // TLS_RSA_WITH_NULL_MD5
35  {0x2, 0x102},  // TLS_RSA_WITH_NULL_SHA
36  {0x3, 0x209},  // TLS_RSA_EXPORT_WITH_RC4_40_MD5
37  {0x4, 0x111},  // TLS_RSA_WITH_RC4_128_MD5
38  {0x5, 0x112},  // TLS_RSA_WITH_RC4_128_SHA
39  {0x6, 0x219},  // TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
40  {0x7, 0x122},  // TLS_RSA_WITH_IDEA_CBC_SHA
41  {0x8, 0x22a},  // TLS_RSA_EXPORT_WITH_DES40_CBC_SHA
42  {0x9, 0x132},  // TLS_RSA_WITH_DES_CBC_SHA
43  {0xa, 0x13a},  // TLS_RSA_WITH_3DES_EDE_CBC_SHA
44  {0xb, 0x32a},  // TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA
45  {0xc, 0x432},  // TLS_DH_DSS_WITH_DES_CBC_SHA
46  {0xd, 0x43a},  // TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA
47  {0xe, 0x52a},  // TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA
48  {0xf, 0x632},  // TLS_DH_RSA_WITH_DES_CBC_SHA
49  {0x10, 0x63a},  // TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA
50  {0x11, 0x72a},  // TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
51  {0x12, 0x832},  // TLS_DHE_DSS_WITH_DES_CBC_SHA
52  {0x13, 0x83a},  // TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
53  {0x14, 0x92a},  // TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
54  {0x15, 0xa32},  // TLS_DHE_RSA_WITH_DES_CBC_SHA
55  {0x16, 0xa3a},  // TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
56  {0x17, 0xb09},  // TLS_DH_anon_EXPORT_WITH_RC4_40_MD5
57  {0x18, 0xc11},  // TLS_DH_anon_WITH_RC4_128_MD5
58  {0x19, 0xb2a},  // TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA
59  {0x1a, 0xc32},  // TLS_DH_anon_WITH_DES_CBC_SHA
60  {0x1b, 0xc3a},  // TLS_DH_anon_WITH_3DES_EDE_CBC_SHA
61  {0x2f, 0x142},  // TLS_RSA_WITH_AES_128_CBC_SHA
62  {0x30, 0x442},  // TLS_DH_DSS_WITH_AES_128_CBC_SHA
63  {0x31, 0x642},  // TLS_DH_RSA_WITH_AES_128_CBC_SHA
64  {0x32, 0x842},  // TLS_DHE_DSS_WITH_AES_128_CBC_SHA
65  {0x33, 0xa42},  // TLS_DHE_RSA_WITH_AES_128_CBC_SHA
66  {0x34, 0xc42},  // TLS_DH_anon_WITH_AES_128_CBC_SHA
67  {0x35, 0x14a},  // TLS_RSA_WITH_AES_256_CBC_SHA
68  {0x36, 0x44a},  // TLS_DH_DSS_WITH_AES_256_CBC_SHA
69  {0x37, 0x64a},  // TLS_DH_RSA_WITH_AES_256_CBC_SHA
70  {0x38, 0x84a},  // TLS_DHE_DSS_WITH_AES_256_CBC_SHA
71  {0x39, 0xa4a},  // TLS_DHE_RSA_WITH_AES_256_CBC_SHA
72  {0x3a, 0xc4a},  // TLS_DH_anon_WITH_AES_256_CBC_SHA
73  {0x3b, 0x103},  // TLS_RSA_WITH_NULL_SHA256
74  {0x3c, 0x143},  // TLS_RSA_WITH_AES_128_CBC_SHA256
75  {0x3d, 0x14b},  // TLS_RSA_WITH_AES_256_CBC_SHA256
76  {0x3e, 0x443},  // TLS_DH_DSS_WITH_AES_128_CBC_SHA256
77  {0x3f, 0x643},  // TLS_DH_RSA_WITH_AES_128_CBC_SHA256
78  {0x40, 0x843},  // TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
79  {0x41, 0x152},  // TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
80  {0x42, 0x452},  // TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA
81  {0x43, 0x652},  // TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA
82  {0x44, 0x852},  // TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA
83  {0x45, 0xa52},  // TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
84  {0x46, 0xc52},  // TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA
85  {0x67, 0xa43},  // TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
86  {0x68, 0x44b},  // TLS_DH_DSS_WITH_AES_256_CBC_SHA256
87  {0x69, 0x64b},  // TLS_DH_RSA_WITH_AES_256_CBC_SHA256
88  {0x6a, 0x84b},  // TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
89  {0x6b, 0xa4b},  // TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
90  {0x6c, 0xc43},  // TLS_DH_anon_WITH_AES_128_CBC_SHA256
91  {0x6d, 0xc4b},  // TLS_DH_anon_WITH_AES_256_CBC_SHA256
92  {0x84, 0x15a},  // TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
93  {0x85, 0x45a},  // TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA
94  {0x86, 0x65a},  // TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA
95  {0x87, 0x85a},  // TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA
96  {0x88, 0xa5a},  // TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
97  {0x89, 0xc5a},  // TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA
98  {0x96, 0x162},  // TLS_RSA_WITH_SEED_CBC_SHA
99  {0x97, 0x462},  // TLS_DH_DSS_WITH_SEED_CBC_SHA
100  {0x98, 0x662},  // TLS_DH_RSA_WITH_SEED_CBC_SHA
101  {0x99, 0x862},  // TLS_DHE_DSS_WITH_SEED_CBC_SHA
102  {0x9a, 0xa62},  // TLS_DHE_RSA_WITH_SEED_CBC_SHA
103  {0x9b, 0xc62},  // TLS_DH_anon_WITH_SEED_CBC_SHA
104  {0x9c, 0x16f},  // TLS_RSA_WITH_AES_128_GCM_SHA256
105  {0x9d, 0x177},  // TLS_RSA_WITH_AES_256_GCM_SHA384
106  {0x9e, 0xa6f},  // TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
107  {0x9f, 0xa77},  // TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
108  {0xa0, 0x66f},  // TLS_DH_RSA_WITH_AES_128_GCM_SHA256
109  {0xa1, 0x677},  // TLS_DH_RSA_WITH_AES_256_GCM_SHA384
110  {0xa2, 0x86f},  // TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
111  {0xa3, 0x877},  // TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
112  {0xa4, 0x46f},  // TLS_DH_DSS_WITH_AES_128_GCM_SHA256
113  {0xa5, 0x477},  // TLS_DH_DSS_WITH_AES_256_GCM_SHA384
114  {0xa6, 0xc6f},  // TLS_DH_anon_WITH_AES_128_GCM_SHA256
115  {0xa7, 0xc77},  // TLS_DH_anon_WITH_AES_256_GCM_SHA384
116  {0xba, 0x153},  // TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256
117  {0xbb, 0x453},  // TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256
118  {0xbc, 0x653},  // TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256
119  {0xbd, 0x853},  // TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256
120  {0xbe, 0xa53},  // TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
121  {0xbf, 0xc53},  // TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256
122  {0xc0, 0x15b},  // TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256
123  {0xc1, 0x45b},  // TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256
124  {0xc2, 0x65b},  // TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256
125  {0xc3, 0x85b},  // TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256
126  {0xc4, 0xa5b},  // TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256
127  {0xc5, 0xc5b},  // TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256
128  {0xc001, 0xd02},  // TLS_ECDH_ECDSA_WITH_NULL_SHA
129  {0xc002, 0xd12},  // TLS_ECDH_ECDSA_WITH_RC4_128_SHA
130  {0xc003, 0xd3a},  // TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
131  {0xc004, 0xd42},  // TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
132  {0xc005, 0xd4a},  // TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
133  {0xc006, 0xe02},  // TLS_ECDHE_ECDSA_WITH_NULL_SHA
134  {0xc007, 0xe12},  // TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
135  {0xc008, 0xe3a},  // TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
136  {0xc009, 0xe42},  // TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
137  {0xc00a, 0xe4a},  // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
138  {0xc00b, 0xf02},  // TLS_ECDH_RSA_WITH_NULL_SHA
139  {0xc00c, 0xf12},  // TLS_ECDH_RSA_WITH_RC4_128_SHA
140  {0xc00d, 0xf3a},  // TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
141  {0xc00e, 0xf42},  // TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
142  {0xc00f, 0xf4a},  // TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
143  {0xc010, 0x1002},  // TLS_ECDHE_RSA_WITH_NULL_SHA
144  {0xc011, 0x1012},  // TLS_ECDHE_RSA_WITH_RC4_128_SHA
145  {0xc012, 0x103a},  // TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
146  {0xc013, 0x1042},  // TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
147  {0xc014, 0x104a},  // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
148  {0xc015, 0x1102},  // TLS_ECDH_anon_WITH_NULL_SHA
149  {0xc016, 0x1112},  // TLS_ECDH_anon_WITH_RC4_128_SHA
150  {0xc017, 0x113a},  // TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA
151  {0xc018, 0x1142},  // TLS_ECDH_anon_WITH_AES_128_CBC_SHA
152  {0xc019, 0x114a},  // TLS_ECDH_anon_WITH_AES_256_CBC_SHA
153  {0xc023, 0xe43},  // TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
154  {0xc024, 0xe4c},  // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
155  {0xc025, 0xd43},  // TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
156  {0xc026, 0xd4c},  // TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
157  {0xc027, 0x1043},  // TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
158  {0xc028, 0x104c},  // TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
159  {0xc029, 0xf43},  // TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
160  {0xc02a, 0xf4c},  // TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
161  {0xc02b, 0xe6f},  // TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
162  {0xc02c, 0xe77},  // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
163  {0xc02d, 0xd6f},  // TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
164  {0xc02e, 0xd77},  // TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
165  {0xc02f, 0x106f},  // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
166  {0xc030, 0x1077},  // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
167  {0xc031, 0xf6f},  // TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
168  {0xc032, 0xf77},  // TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
169  {0xc072, 0xe53},  // TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
170  {0xc073, 0xe5c},  // TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
171  {0xc074, 0xd53},  // TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256
172  {0xc075, 0xd5c},  // TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384
173  {0xc076, 0x1053},  // TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256
174  {0xc077, 0x105c},  // TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384
175  {0xc078, 0xf53},  // TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256
176  {0xc079, 0xf5c},  // TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384
177  {0xc07a, 0x17f},  // TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256
178  {0xc07b, 0x187},  // TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384
179  {0xc07c, 0xa7f},  // TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
180  {0xc07d, 0xa87},  // TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
181  {0xc07e, 0x67f},  // TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256
182  {0xc07f, 0x687},  // TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384
183  {0xc080, 0x87f},  // TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256
184  {0xc081, 0x887},  // TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384
185  {0xc082, 0x47f},  // TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256
186  {0xc083, 0x487},  // TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384
187  {0xc084, 0xc7f},  // TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256
188  {0xc085, 0xc87},  // TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384
189  {0xc086, 0xe7f},  // TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
190  {0xc087, 0xe87},  // TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
191  {0xc088, 0xd7f},  // TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256
192  {0xc089, 0xd87},  // TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384
193  {0xc08a, 0x107f},  // TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256
194  {0xc08b, 0x1087},  // TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384
195  {0xc08c, 0xf7f},  // TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256
196  {0xc08d, 0xf87},  // TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384
197  {0xcc13, 0x108f},  // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
198  {0xcc14, 0x0e8f},  // TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
199};
200
201static const struct {
202  char name[15];
203} kKeyExchangeNames[18] = {
204  {"NULL"},  // 0
205  {"RSA"},  // 1
206  {"RSA_EXPORT"},  // 2
207  {"DH_DSS_EXPORT"},  // 3
208  {"DH_DSS"},  // 4
209  {"DH_RSA_EXPORT"},  // 5
210  {"DH_RSA"},  // 6
211  {"DHE_DSS_EXPORT"},  // 7
212  {"DHE_DSS"},  // 8
213  {"DHE_RSA_EXPORT"},  // 9
214  {"DHE_RSA"},  // 10
215  {"DH_anon_EXPORT"},  // 11
216  {"DH_anon"},  // 12
217  {"ECDH_ECDSA"},  // 13
218  {"ECDHE_ECDSA"},  // 14
219  {"ECDH_RSA"},  // 15
220  {"ECDHE_RSA"},  // 16
221  {"ECDH_anon"},  // 17
222};
223
224static const struct {
225  char name[18];
226} kCipherNames[18] = {
227  {"NULL"},  // 0
228  {"RC4_40"},  // 1
229  {"RC4_128"},  // 2
230  {"RC2_CBC_40"},  // 3
231  {"IDEA_CBC"},  // 4
232  {"DES40_CBC"},  // 5
233  {"DES_CBC"},  // 6
234  {"3DES_EDE_CBC"},  // 7
235  {"AES_128_CBC"},  // 8
236  {"AES_256_CBC"},  // 9
237  {"CAMELLIA_128_CBC"},  // 10
238  {"CAMELLIA_256_CBC"},  // 11
239  {"SEED_CBC"},  // 12
240  {"AES_128_GCM"},  // 13
241  {"AES_256_GCM"},  // 14
242  {"CAMELLIA_128_GCM"},  // 15
243  {"CAMELLIA_256_GCM"},  // 16
244  {"CHACHA20_POLY1305"},  // 17
245};
246
247static const struct {
248  char name[7];
249} kMacNames[5] = {
250  {"NULL"},  // 0
251  {"MD5"},  // 1
252  {"SHA1"},  // 2
253  {"SHA256"},  // 3
254  {"SHA384"},  // 4
255  // 7 is reserved to indicate an AEAD cipher suite.
256};
257
258static const int kAEADMACValue = 7;
259
260namespace net {
261
262static int CipherSuiteCmp(const void* ia, const void* ib) {
263  const CipherSuite* a = static_cast<const CipherSuite*>(ia);
264  const CipherSuite* b = static_cast<const CipherSuite*>(ib);
265
266  if (a->cipher_suite < b->cipher_suite) {
267    return -1;
268  } else if (a->cipher_suite == b->cipher_suite) {
269    return 0;
270  } else {
271    return 1;
272  }
273}
274
275void SSLCipherSuiteToStrings(const char** key_exchange_str,
276                             const char** cipher_str,
277                             const char** mac_str,
278                             bool *is_aead,
279                             uint16 cipher_suite) {
280  *key_exchange_str = *cipher_str = *mac_str = "???";
281  *is_aead = false;
282
283  struct CipherSuite desired = {0};
284  desired.cipher_suite = cipher_suite;
285
286  void* r = bsearch(&desired, kCipherSuites,
287                    arraysize(kCipherSuites), sizeof(kCipherSuites[0]),
288                    CipherSuiteCmp);
289
290  if (!r)
291    return;
292
293  const CipherSuite* cs = static_cast<CipherSuite*>(r);
294
295  const int key_exchange = cs->encoded >> 8;
296  const int cipher = (cs->encoded >> 3) & 0x1f;
297  const int mac = cs->encoded & 0x7;
298
299  *key_exchange_str = kKeyExchangeNames[key_exchange].name;
300  *cipher_str = kCipherNames[cipher].name;
301  if (mac == kAEADMACValue) {
302    *is_aead = true;
303    *mac_str = NULL;
304  } else {
305    *mac_str = kMacNames[mac].name;
306  }
307}
308
309void SSLVersionToString(const char** name, int ssl_version) {
310  switch (ssl_version) {
311    case SSL_CONNECTION_VERSION_SSL2:
312      *name = "SSL 2.0";
313      break;
314    case SSL_CONNECTION_VERSION_SSL3:
315      *name = "SSL 3.0";
316      break;
317    case SSL_CONNECTION_VERSION_TLS1:
318      *name = "TLS 1.0";
319      break;
320    case SSL_CONNECTION_VERSION_TLS1_1:
321      *name = "TLS 1.1";
322      break;
323    case SSL_CONNECTION_VERSION_TLS1_2:
324      *name = "TLS 1.2";
325      break;
326    case SSL_CONNECTION_VERSION_QUIC:
327      *name = "QUIC";
328      break;
329    default:
330      NOTREACHED() << ssl_version;
331      *name = "???";
332      break;
333  }
334}
335
336bool ParseSSLCipherString(const std::string& cipher_string,
337                          uint16* cipher_suite) {
338  int value = 0;
339  if (cipher_string.size() == 6 &&
340      StartsWithASCII(cipher_string, "0x", false /* case insensitive */) &&
341      base::HexStringToInt(cipher_string, &value)) {
342    *cipher_suite = static_cast<uint16>(value);
343    return true;
344  }
345  return false;
346}
347
348bool IsSecureTLSCipherSuite(uint16 cipher_suite) {
349  CipherSuite desired = {0};
350  desired.cipher_suite = cipher_suite;
351
352  void* r = bsearch(&desired,
353                    kCipherSuites,
354                    arraysize(kCipherSuites),
355                    sizeof(kCipherSuites[0]),
356                    CipherSuiteCmp);
357
358  if (!r)
359    return false;
360
361  const CipherSuite* cs = static_cast<const CipherSuite*>(r);
362
363  const int key_exchange = cs->encoded >> 8;
364  const int cipher = (cs->encoded >> 3) & 0x1f;
365  const int mac = cs->encoded & 0x7;
366
367  // Only allow forward secure key exchanges.
368  switch (key_exchange) {
369    case 10:  // DHE_RSA
370    case 14:  // ECDHE_ECDSA
371    case 16:  // ECDHE_RSA
372      break;
373    default:
374      return false;
375  }
376
377  switch (cipher) {
378    case 13:  // AES_128_GCM
379    case 14:  // AES_256_GCM
380    case 17:  // CHACHA20_POLY1305
381      break;
382    default:
383      return false;
384  }
385
386  // Only AEADs allowed.
387  if (mac != kAEADMACValue)
388    return false;
389
390  return true;
391}
392
393}  // namespace net
394