blob: 5dd689b5cd9959aed6bb62b18414482eb1c7b61c [file] [log] [blame]
David Benjamin2e521212014-07-16 14:37:51 -04001/* Copyright (c) 2014, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15#include <stdio.h>
David Benjamin751e8892014-10-19 00:59:36 -040016#include <string.h>
David Benjamin1269ddd2015-10-18 15:18:55 -040017#include <time.h>
David Benjamin2e521212014-07-16 14:37:51 -040018
David Benjamin0f653952015-10-18 14:28:01 -040019#include <algorithm>
David Benjamin1d77e562015-03-22 17:22:08 -040020#include <string>
David Benjamin4f6acaf2015-11-21 03:00:50 -050021#include <utility>
David Benjamin1d77e562015-03-22 17:22:08 -040022#include <vector>
23
David Benjamin751e8892014-10-19 00:59:36 -040024#include <openssl/base64.h>
25#include <openssl/bio.h>
David Benjamin7a1eefd2015-10-17 23:39:22 -040026#include <openssl/crypto.h>
David Benjaminbb0a17c2014-09-20 15:35:39 -040027#include <openssl/err.h>
David Benjaminde942382016-02-11 12:02:01 -050028#include <openssl/pem.h>
David Benjamin25490f22016-07-14 00:22:54 -040029#include <openssl/sha.h>
David Benjaminbb0a17c2014-09-20 15:35:39 -040030#include <openssl/ssl.h>
David Benjaminde942382016-02-11 12:02:01 -050031#include <openssl/x509.h>
David Benjaminbb0a17c2014-09-20 15:35:39 -040032
Steven Valdez87eab492016-06-27 16:34:59 -040033#include "internal.h"
Adam Langleyd2b5af52016-07-12 08:03:59 -070034#include "test/scoped_types.h"
Sigbjorn Vik2b23d242015-06-29 15:07:26 +020035#include "../crypto/test/test_util.h"
36
David Benjamin1d77e562015-03-22 17:22:08 -040037
38struct ExpectedCipher {
39 unsigned long id;
David Benjaminbb0a17c2014-09-20 15:35:39 -040040 int in_group_flag;
David Benjamin1d77e562015-03-22 17:22:08 -040041};
David Benjaminbb0a17c2014-09-20 15:35:39 -040042
David Benjamin1d77e562015-03-22 17:22:08 -040043struct CipherTest {
44 // The rule string to apply.
David Benjaminbb0a17c2014-09-20 15:35:39 -040045 const char *rule;
David Benjaminfb974e62015-12-16 19:34:22 -050046 // The list of expected ciphers, in order.
47 std::vector<ExpectedCipher> expected;
David Benjamin1d77e562015-03-22 17:22:08 -040048};
David Benjaminbb0a17c2014-09-20 15:35:39 -040049
David Benjaminfb974e62015-12-16 19:34:22 -050050static const CipherTest kCipherTests[] = {
51 // Selecting individual ciphers should work.
52 {
53 "ECDHE-ECDSA-CHACHA20-POLY1305:"
54 "ECDHE-RSA-CHACHA20-POLY1305:"
55 "ECDHE-ECDSA-AES128-GCM-SHA256:"
56 "ECDHE-RSA-AES128-GCM-SHA256",
57 {
58 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
59 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
60 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
61 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
62 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
63 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
64 },
65 },
66 // + reorders selected ciphers to the end, keeping their relative order.
67 {
68 "ECDHE-ECDSA-CHACHA20-POLY1305:"
69 "ECDHE-RSA-CHACHA20-POLY1305:"
70 "ECDHE-ECDSA-AES128-GCM-SHA256:"
71 "ECDHE-RSA-AES128-GCM-SHA256:"
72 "+aRSA",
73 {
74 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
75 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
76 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
77 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
78 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
79 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
80 },
81 },
82 // ! banishes ciphers from future selections.
83 {
84 "!aRSA:"
85 "ECDHE-ECDSA-CHACHA20-POLY1305:"
86 "ECDHE-RSA-CHACHA20-POLY1305:"
87 "ECDHE-ECDSA-AES128-GCM-SHA256:"
88 "ECDHE-RSA-AES128-GCM-SHA256",
89 {
90 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
91 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
92 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
93 },
94 },
95 // Multiple masks can be ANDed in a single rule.
96 {
97 "kRSA+AESGCM+AES128",
98 {
99 {TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0},
100 },
101 },
102 // - removes selected ciphers, but preserves their order for future
103 // selections. Select AES_128_GCM, but order the key exchanges RSA, DHE_RSA,
104 // ECDHE_RSA.
105 {
106 "ALL:-kECDHE:-kDHE:-kRSA:-ALL:"
107 "AESGCM+AES128+aRSA",
108 {
109 {TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0},
110 {TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, 0},
111 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
112 },
113 },
114 // Unknown selectors are no-ops.
115 {
116 "ECDHE-ECDSA-CHACHA20-POLY1305:"
117 "ECDHE-RSA-CHACHA20-POLY1305:"
118 "ECDHE-ECDSA-AES128-GCM-SHA256:"
119 "ECDHE-RSA-AES128-GCM-SHA256:"
120 "BOGUS1:-BOGUS2:+BOGUS3:!BOGUS4",
121 {
122 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
123 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
124 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
125 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
126 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
127 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
128 },
129 },
130 // Square brackets specify equi-preference groups.
131 {
132 "[ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]:"
133 "[ECDHE-RSA-CHACHA20-POLY1305]:"
134 "ECDHE-RSA-AES128-GCM-SHA256",
135 {
136 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 1},
137 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 1},
138 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
139 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 1},
140 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
141 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
142 },
143 },
144 // @STRENGTH performs a stable strength-sort of the selected ciphers and
145 // only the selected ciphers.
146 {
147 // To simplify things, banish all but {ECDHE_RSA,RSA} x
148 // {CHACHA20,AES_256_CBC,AES_128_CBC,RC4} x SHA1.
149 "!kEDH:!AESGCM:!3DES:!SHA256:!MD5:!SHA384:"
150 // Order some ciphers backwards by strength.
151 "ALL:-CHACHA20:-AES256:-AES128:-RC4:-ALL:"
152 // Select ECDHE ones and sort them by strength. Ties should resolve
153 // based on the order above.
154 "kECDHE:@STRENGTH:-ALL:"
155 // Now bring back everything uses RSA. ECDHE_RSA should be first, sorted
156 // by strength. Then RSA, backwards by strength.
157 "aRSA",
158 {
159 {TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, 0},
160 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
161 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
162 {TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA, 0},
163 {TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, 0},
164 {SSL3_CK_RSA_RC4_128_SHA, 0},
165 {TLS1_CK_RSA_WITH_AES_128_SHA, 0},
166 {TLS1_CK_RSA_WITH_AES_256_SHA, 0},
167 },
168 },
169 // Exact ciphers may not be used in multi-part rules; they are treated
170 // as unknown aliases.
171 {
172 "ECDHE-ECDSA-AES128-GCM-SHA256:"
173 "ECDHE-RSA-AES128-GCM-SHA256:"
174 "!ECDHE-RSA-AES128-GCM-SHA256+RSA:"
175 "!ECDSA+ECDHE-ECDSA-AES128-GCM-SHA256",
176 {
177 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
178 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
179 },
180 },
181 // SSLv3 matches everything that existed before TLS 1.2.
182 {
183 "AES128-SHA:AES128-SHA256:!SSLv3",
184 {
185 {TLS1_CK_RSA_WITH_AES_128_SHA256, 0},
186 },
187 },
188 // TLSv1.2 matches everything added in TLS 1.2.
189 {
190 "AES128-SHA:AES128-SHA256:!TLSv1.2",
191 {
192 {TLS1_CK_RSA_WITH_AES_128_SHA, 0},
193 },
194 },
195 // The two directives have no intersection.
196 {
197 "AES128-SHA:AES128-SHA256:!TLSv1.2+SSLv3",
198 {
199 {TLS1_CK_RSA_WITH_AES_128_SHA, 0},
200 {TLS1_CK_RSA_WITH_AES_128_SHA256, 0},
201 },
202 },
203 // The shared name of the CHACHA20_POLY1305 variants behaves like a cipher
204 // name and not an alias. It may not be used in a multipart rule. (That the
205 // shared name works is covered by the standard tests.)
206 {
207 "ECDHE-ECDSA-CHACHA20-POLY1305:"
208 "ECDHE-RSA-CHACHA20-POLY1305:"
209 "!ECDHE-RSA-CHACHA20-POLY1305+RSA:"
210 "!ECDSA+ECDHE-ECDSA-CHACHA20-POLY1305",
211 {
212 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
213 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
214 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
215 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
216 },
217 },
David Benjaminbb0a17c2014-09-20 15:35:39 -0400218};
219
220static const char *kBadRules[] = {
David Benjamin1d77e562015-03-22 17:22:08 -0400221 // Invalid brackets.
David Benjaminbb0a17c2014-09-20 15:35:39 -0400222 "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256",
223 "RSA]",
224 "[[RSA]]",
David Benjamin1d77e562015-03-22 17:22:08 -0400225 // Operators inside brackets.
David Benjaminbb0a17c2014-09-20 15:35:39 -0400226 "[+RSA]",
David Benjamin1d77e562015-03-22 17:22:08 -0400227 // Unknown directive.
David Benjaminbb0a17c2014-09-20 15:35:39 -0400228 "@BOGUS",
David Benjamin1d77e562015-03-22 17:22:08 -0400229 // Empty cipher lists error at SSL_CTX_set_cipher_list.
David Benjaminbb0a17c2014-09-20 15:35:39 -0400230 "",
231 "BOGUS",
David Benjamin32fbdf22015-04-07 01:14:06 -0400232 // COMPLEMENTOFDEFAULT is empty.
233 "COMPLEMENTOFDEFAULT",
David Benjamin1d77e562015-03-22 17:22:08 -0400234 // Invalid command.
David Benjaminbb0a17c2014-09-20 15:35:39 -0400235 "?BAR",
David Benjamin1d77e562015-03-22 17:22:08 -0400236 // Special operators are not allowed if groups are used.
David Benjamin37d92462014-09-20 17:54:24 -0400237 "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:+FOO",
238 "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:!FOO",
239 "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:-FOO",
240 "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:@STRENGTH",
David Benjaminbb0a17c2014-09-20 15:35:39 -0400241};
242
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700243static const char *kMustNotIncludeNull[] = {
244 "ALL",
245 "DEFAULT",
246 "ALL:!eNULL",
247 "ALL:!NULL",
David Benjamind6e9eec2015-11-18 09:48:55 -0500248 "MEDIUM",
249 "HIGH",
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700250 "FIPS",
251 "SHA",
252 "SHA1",
253 "RSA",
254 "SSLv3",
255 "TLSv1",
256 "TLSv1.2",
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700257};
258
Matt Braithwaite053931e2016-05-25 12:06:05 -0700259static const char *kMustNotIncludeCECPQ1[] = {
260 "ALL",
261 "DEFAULT",
262 "MEDIUM",
263 "HIGH",
264 "FIPS",
265 "SHA",
266 "SHA1",
267 "SHA256",
268 "SHA384",
269 "RSA",
270 "SSLv3",
271 "TLSv1",
272 "TLSv1.2",
273 "aRSA",
274 "RSA",
275 "aECDSA",
276 "ECDSA",
277 "AES",
278 "AES128",
279 "AES256",
280 "AESGCM",
281 "CHACHA20",
282};
283
David Benjamin1d77e562015-03-22 17:22:08 -0400284static void PrintCipherPreferenceList(ssl_cipher_preference_list_st *list) {
285 bool in_group = false;
286 for (size_t i = 0; i < sk_SSL_CIPHER_num(list->ciphers); i++) {
David Benjaminbb0a17c2014-09-20 15:35:39 -0400287 const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(list->ciphers, i);
288 if (!in_group && list->in_group_flags[i]) {
289 fprintf(stderr, "\t[\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400290 in_group = true;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400291 }
292 fprintf(stderr, "\t");
293 if (in_group) {
294 fprintf(stderr, " ");
295 }
296 fprintf(stderr, "%s\n", SSL_CIPHER_get_name(cipher));
297 if (in_group && !list->in_group_flags[i]) {
298 fprintf(stderr, "\t]\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400299 in_group = false;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400300 }
301 }
302}
303
David Benjaminfb974e62015-12-16 19:34:22 -0500304static bool TestCipherRule(const CipherTest &t) {
David Benjamin1d77e562015-03-22 17:22:08 -0400305 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
306 if (!ctx) {
307 return false;
David Benjamin65226252015-02-05 16:49:47 -0500308 }
309
David Benjaminfb974e62015-12-16 19:34:22 -0500310 if (!SSL_CTX_set_cipher_list(ctx.get(), t.rule)) {
311 fprintf(stderr, "Error testing cipher rule '%s'\n", t.rule);
David Benjamin1d77e562015-03-22 17:22:08 -0400312 return false;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400313 }
314
David Benjamin1d77e562015-03-22 17:22:08 -0400315 // Compare the two lists.
David Benjaminfb974e62015-12-16 19:34:22 -0500316 if (sk_SSL_CIPHER_num(ctx->cipher_list->ciphers) != t.expected.size()) {
317 fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t.rule);
318 PrintCipherPreferenceList(ctx->cipher_list);
319 return false;
320 }
321
322 for (size_t i = 0; i < t.expected.size(); i++) {
David Benjaminbb0a17c2014-09-20 15:35:39 -0400323 const SSL_CIPHER *cipher =
324 sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i);
David Benjaminfb974e62015-12-16 19:34:22 -0500325 if (t.expected[i].id != SSL_CIPHER_get_id(cipher) ||
326 t.expected[i].in_group_flag != ctx->cipher_list->in_group_flags[i]) {
327 fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t.rule);
David Benjamin1d77e562015-03-22 17:22:08 -0400328 PrintCipherPreferenceList(ctx->cipher_list);
329 return false;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400330 }
331 }
332
David Benjamin1d77e562015-03-22 17:22:08 -0400333 return true;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400334}
335
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700336static bool TestRuleDoesNotIncludeNull(const char *rule) {
337 ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_server_method()));
338 if (!ctx) {
339 return false;
340 }
341 if (!SSL_CTX_set_cipher_list(ctx.get(), rule)) {
342 fprintf(stderr, "Error: cipher rule '%s' failed\n", rule);
343 return false;
344 }
345 for (size_t i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) {
346 if (SSL_CIPHER_is_NULL(sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i))) {
347 fprintf(stderr, "Error: cipher rule '%s' includes NULL\n",rule);
348 return false;
349 }
350 }
351 return true;
352}
353
Matt Braithwaite053931e2016-05-25 12:06:05 -0700354static bool TestRuleDoesNotIncludeCECPQ1(const char *rule) {
355 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
356 if (!ctx) {
357 return false;
358 }
359 if (!SSL_CTX_set_cipher_list(ctx.get(), rule)) {
360 fprintf(stderr, "Error: cipher rule '%s' failed\n", rule);
361 return false;
362 }
363 for (size_t i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) {
364 if (SSL_CIPHER_is_CECPQ1(sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i))) {
365 fprintf(stderr, "Error: cipher rule '%s' includes CECPQ1\n",rule);
366 return false;
367 }
368 }
369 return true;
370}
371
David Benjamin1d77e562015-03-22 17:22:08 -0400372static bool TestCipherRules() {
David Benjaminfb974e62015-12-16 19:34:22 -0500373 for (const CipherTest &test : kCipherTests) {
374 if (!TestCipherRule(test)) {
David Benjamin1d77e562015-03-22 17:22:08 -0400375 return false;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400376 }
377 }
378
David Benjaminfb974e62015-12-16 19:34:22 -0500379 for (const char *rule : kBadRules) {
David Benjamin1d77e562015-03-22 17:22:08 -0400380 ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_server_method()));
381 if (!ctx) {
382 return false;
David Benjamin65226252015-02-05 16:49:47 -0500383 }
David Benjaminfb974e62015-12-16 19:34:22 -0500384 if (SSL_CTX_set_cipher_list(ctx.get(), rule)) {
385 fprintf(stderr, "Cipher rule '%s' unexpectedly succeeded\n", rule);
David Benjamin1d77e562015-03-22 17:22:08 -0400386 return false;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400387 }
388 ERR_clear_error();
David Benjaminbb0a17c2014-09-20 15:35:39 -0400389 }
390
David Benjaminfb974e62015-12-16 19:34:22 -0500391 for (const char *rule : kMustNotIncludeNull) {
392 if (!TestRuleDoesNotIncludeNull(rule)) {
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700393 return false;
394 }
395 }
396
Matt Braithwaite053931e2016-05-25 12:06:05 -0700397 for (const char *rule : kMustNotIncludeCECPQ1) {
398 if (!TestRuleDoesNotIncludeCECPQ1(rule)) {
399 return false;
400 }
401 }
402
David Benjamin1d77e562015-03-22 17:22:08 -0400403 return true;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400404}
David Benjamin2e521212014-07-16 14:37:51 -0400405
Adam Langley10f97f32016-07-12 08:09:33 -0700406// kOpenSSLSession is a serialized SSL_SESSION generated from openssl
407// s_client -sess_out.
408static const char kOpenSSLSession[] =
409 "MIIFpQIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
410 "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
411 "IWoJoQYCBFRDO46iBAICASyjggR6MIIEdjCCA16gAwIBAgIIK9dUvsPWSlUwDQYJ"
412 "KoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMx"
413 "JTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTQxMDA4"
414 "MTIwNzU3WhcNMTUwMTA2MDAwMDAwWjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwK"
415 "Q2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29v"
416 "Z2xlIEluYzEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEB"
417 "AQUAA4IBDwAwggEKAoIBAQCcKeLrplAC+Lofy8t/wDwtB6eu72CVp0cJ4V3lknN6"
418 "huH9ct6FFk70oRIh/VBNBBz900jYy+7111Jm1b8iqOTQ9aT5C7SEhNcQFJvqzH3e"
419 "MPkb6ZSWGm1yGF7MCQTGQXF20Sk/O16FSjAynU/b3oJmOctcycWYkY0ytS/k3LBu"
420 "Id45PJaoMqjB0WypqvNeJHC3q5JjCB4RP7Nfx5jjHSrCMhw8lUMW4EaDxjaR9KDh"
421 "PLgjsk+LDIySRSRDaCQGhEOWLJZVLzLo4N6/UlctCHEllpBUSvEOyFga52qroGjg"
422 "rf3WOQ925MFwzd6AK+Ich0gDRg8sQfdLH5OuP1cfLfU1AgMBAAGjggFBMIIBPTAd"
423 "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdv"
424 "b2dsZS5jb20waAYIKwYBBQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtp"
425 "Lmdvb2dsZS5jb20vR0lBRzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50"
426 "czEuZ29vZ2xlLmNvbS9vY3NwMB0GA1UdDgQWBBQ7a+CcxsZByOpc+xpYFcIbnUMZ"
427 "hTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEv"
428 "MBcGA1UdIAQQMA4wDAYKKwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRw"
429 "Oi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCa"
430 "OXCBdoqUy5bxyq+Wrh1zsyyCFim1PH5VU2+yvDSWrgDY8ibRGJmfff3r4Lud5kal"
431 "dKs9k8YlKD3ITG7P0YT/Rk8hLgfEuLcq5cc0xqmE42xJ+Eo2uzq9rYorc5emMCxf"
432 "5L0TJOXZqHQpOEcuptZQ4OjdYMfSxk5UzueUhA3ogZKRcRkdB3WeWRp+nYRhx4St"
433 "o2rt2A0MKmY9165GHUqMK9YaaXHDXqBu7Sefr1uSoAP9gyIJKeihMivsGqJ1TD6Z"
434 "cc6LMe+dN2P8cZEQHtD1y296ul4Mivqk3jatUVL8/hCwgch9A8O4PGZq9WqBfEWm"
435 "IyHh1dPtbg1lOXdYCWtjpAIEAKUDAgEUqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36S"
436 "YTcLEkXqKwOBfF9vE4KX0NxeLwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9B"
437 "sNHM362zZnY27GpTw+Kwd751CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yE"
438 "OTDKPNj3+inbMaVigtK4PLyPq+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdA"
439 "i4gv7Y5oliyn";
440
441// kCustomSession is a custom serialized SSL_SESSION generated by
442// filling in missing fields from |kOpenSSLSession|. This includes
443// providing |peer_sha256|, so |peer| is not serialized.
444static const char kCustomSession[] =
445 "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
446 "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
447 "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
448 "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
449 "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
450 "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
451 "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
452 "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF";
453
454// kBoringSSLSession is a serialized SSL_SESSION generated from bssl client.
455static const char kBoringSSLSession[] =
456 "MIIRwQIBAQICAwMEAsAvBCDdoGxGK26mR+8lM0uq6+k9xYuxPnwAjpcF9n0Yli9R"
457 "kQQwbyshfWhdi5XQ1++7n2L1qqrcVlmHBPpr6yknT/u4pUrpQB5FZ7vqvNn8MdHf"
458 "9rWgoQYCBFXgs7uiBAICHCCjggR6MIIEdjCCA16gAwIBAgIIf+yfD7Y6UicwDQYJ"
459 "KoZIhvcNAQELBQAwSTELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMx"
460 "JTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTUwODEy"
461 "MTQ1MzE1WhcNMTUxMTEwMDAwMDAwWjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwK"
462 "Q2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29v"
463 "Z2xlIEluYzEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEB"
464 "AQUAA4IBDwAwggEKAoIBAQC0MeG5YGQ0t+IeJeoneP/PrhEaieibeKYkbKVLNZpo"
465 "PLuBinvhkXZo3DC133NpCBpy6ZktBwamqyixAyuk/NU6OjgXqwwxfQ7di1AInLIU"
466 "792c7hFyNXSUCG7At8Ifi3YwBX9Ba6u/1d6rWTGZJrdCq3QU11RkKYyTq2KT5mce"
467 "Tv9iGKqSkSTlp8puy/9SZ/3DbU3U+BuqCFqeSlz7zjwFmk35acdCilpJlVDDN5C/"
468 "RCh8/UKc8PaL+cxlt531qoTENvYrflBno14YEZlCBZsPiFeUSILpKEj3Ccwhy0eL"
469 "EucWQ72YZU8mUzXBoXGn0zA0crFl5ci/2sTBBGZsylNBAgMBAAGjggFBMIIBPTAd"
470 "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdv"
471 "b2dsZS5jb20waAYIKwYBBQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtp"
472 "Lmdvb2dsZS5jb20vR0lBRzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50"
473 "czEuZ29vZ2xlLmNvbS9vY3NwMB0GA1UdDgQWBBS/bzHxcE73Q4j3slC4BLbMtLjG"
474 "GjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEv"
475 "MBcGA1UdIAQQMA4wDAYKKwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRw"
476 "Oi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQAb"
477 "qdWPZEHk0X7iKPCTHL6S3w6q1eR67goxZGFSM1lk1hjwyu7XcLJuvALVV9uY3ovE"
478 "kQZSHwT+pyOPWQhsSjO+1GyjvCvK/CAwiUmBX+bQRGaqHsRcio7xSbdVcajQ3bXd"
479 "X+s0WdbOpn6MStKAiBVloPlSxEI8pxY6x/BBCnTIk/+DMB17uZlOjG3vbAnkDkP+"
480 "n0OTucD9sHV7EVj9XUxi51nOfNBCN/s7lpUjDS/NJ4k3iwOtbCPswiot8vLO779a"
481 "f07vR03r349Iz/KTzk95rlFtX0IU+KYNxFNsanIXZ+C9FYGRXkwhHcvFb4qMUB1y"
482 "TTlM80jBMOwyjZXmjRAhpAIEAKUDAgEUqQUCAwGJwKqBpwSBpOgebbmn9NRUtMWH"
483 "+eJpqA5JLMFSMCChOsvKey3toBaCNGU7HfAEiiXNuuAdCBoK262BjQc2YYfqFzqH"
484 "zuppopXCvhohx7j/tnCNZIMgLYt/O9SXK2RYI5z8FhCCHvB4CbD5G0LGl5EFP27s"
485 "Jb6S3aTTYPkQe8yZSlxevg6NDwmTogLO9F7UUkaYmVcMQhzssEE2ZRYNwSOU6KjE"
486 "0Yj+8fAiBtbQriIEIN2L8ZlpaVrdN5KFNdvcmOxJu81P8q53X55xQyGTnGWwsgMC"
487 "ARezggvvMIIEdjCCA16gAwIBAgIIf+yfD7Y6UicwDQYJKoZIhvcNAQELBQAwSTEL"
488 "MAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2ds"
489 "ZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTUwODEyMTQ1MzE1WhcNMTUxMTEw"
490 "MDAwMDAwWjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG"
491 "A1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UE"
492 "AwwOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB"
493 "AQC0MeG5YGQ0t+IeJeoneP/PrhEaieibeKYkbKVLNZpoPLuBinvhkXZo3DC133Np"
494 "CBpy6ZktBwamqyixAyuk/NU6OjgXqwwxfQ7di1AInLIU792c7hFyNXSUCG7At8If"
495 "i3YwBX9Ba6u/1d6rWTGZJrdCq3QU11RkKYyTq2KT5mceTv9iGKqSkSTlp8puy/9S"
496 "Z/3DbU3U+BuqCFqeSlz7zjwFmk35acdCilpJlVDDN5C/RCh8/UKc8PaL+cxlt531"
497 "qoTENvYrflBno14YEZlCBZsPiFeUSILpKEj3Ccwhy0eLEucWQ72YZU8mUzXBoXGn"
498 "0zA0crFl5ci/2sTBBGZsylNBAgMBAAGjggFBMIIBPTAdBgNVHSUEFjAUBggrBgEF"
499 "BQcDAQYIKwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYB"
500 "BQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lB"
501 "RzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9v"
502 "Y3NwMB0GA1UdDgQWBBS/bzHxcE73Q4j3slC4BLbMtLjGGjAMBgNVHRMBAf8EAjAA"
503 "MB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMBcGA1UdIAQQMA4wDAYK"
504 "KwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vcGtpLmdvb2dsZS5j"
505 "b20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQAbqdWPZEHk0X7iKPCTHL6S"
506 "3w6q1eR67goxZGFSM1lk1hjwyu7XcLJuvALVV9uY3ovEkQZSHwT+pyOPWQhsSjO+"
507 "1GyjvCvK/CAwiUmBX+bQRGaqHsRcio7xSbdVcajQ3bXdX+s0WdbOpn6MStKAiBVl"
508 "oPlSxEI8pxY6x/BBCnTIk/+DMB17uZlOjG3vbAnkDkP+n0OTucD9sHV7EVj9XUxi"
509 "51nOfNBCN/s7lpUjDS/NJ4k3iwOtbCPswiot8vLO779af07vR03r349Iz/KTzk95"
510 "rlFtX0IU+KYNxFNsanIXZ+C9FYGRXkwhHcvFb4qMUB1yTTlM80jBMOwyjZXmjRAh"
511 "MIID8DCCAtigAwIBAgIDAjqDMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlVT"
512 "MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i"
513 "YWwgQ0EwHhcNMTMwNDA1MTUxNTU2WhcNMTYxMjMxMjM1OTU5WjBJMQswCQYDVQQG"
514 "EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy"
515 "bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB"
516 "AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP"
517 "VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv"
518 "h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE"
519 "ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ"
520 "EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC"
521 "DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB5zCB5DAfBgNVHSMEGDAWgBTAephojYn7"
522 "qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wDgYD"
523 "VR0PAQH/BAQDAgEGMC4GCCsGAQUFBwEBBCIwIDAeBggrBgEFBQcwAYYSaHR0cDov"
524 "L2cuc3ltY2QuY29tMBIGA1UdEwEB/wQIMAYBAf8CAQAwNQYDVR0fBC4wLDAqoCig"
525 "JoYkaHR0cDovL2cuc3ltY2IuY29tL2NybHMvZ3RnbG9iYWwuY3JsMBcGA1UdIAQQ"
526 "MA4wDAYKKwYBBAHWeQIFATANBgkqhkiG9w0BAQsFAAOCAQEAqvqpIM1qZ4PtXtR+"
527 "3h3Ef+AlBgDFJPupyC1tft6dgmUsgWM0Zj7pUsIItMsv91+ZOmqcUHqFBYx90SpI"
528 "hNMJbHzCzTWf84LuUt5oX+QAihcglvcpjZpNy6jehsgNb1aHA30DP9z6eX0hGfnI"
529 "Oi9RdozHQZJxjyXON/hKTAAj78Q1EK7gI4BzfE00LshukNYQHpmEcxpw8u1VDu4X"
530 "Bupn7jLrLN1nBz/2i8Jw3lsA5rsb0zYaImxssDVCbJAJPZPpZAkiDoUGn8JzIdPm"
531 "X4DkjYUiOnMDsWCOrmji9D6X52ASCWg23jrW4kOVWzeBkoEfu43XrVJkFleW2V40"
532 "fsg12DCCA30wggLmoAMCAQICAxK75jANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQG"
533 "EwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUg"
534 "Q2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTAyMDUyMTA0MDAwMFoXDTE4MDgyMTA0"
535 "MDAwMFowQjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xGzAZ"
536 "BgNVBAMTEkdlb1RydXN0IEdsb2JhbCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP"
537 "ADCCAQoCggEBANrMGGMw/fQXIxpWflvfPGw45HG3eJHUvKHYTPioQ7YD6U0hBwiI"
538 "2lgvZjkpvQV4i5046AW3an5xpObEYKaw74DkiSgPniXW7YPzraaRx5jJQhg1FJ2t"
539 "mEaSLk/K8YdDwRaVVy1Q74ktgHpXrfLuX2vSAI25FPgUFTXZwEaje3LIkb/JVSvN"
540 "0Jc+nCZkzN/Ogxlxyk7m1NV7qRnNVd7I7NJeOFPlXE+MLf5QIzb8ZubLjqQ5GQC3"
541 "lQI5kQsO/jgu0R0FmvZNPm8PBx2vLB6PYDni+jZTEznUXiYr2z2oFL0y6xgDKFIE"
542 "ceWrMz3hOLsHNoRinHnqFjD0X8Ar6HFr5PkCAwEAAaOB8DCB7TAfBgNVHSMEGDAW"
543 "gBRI5mj5K9KylddH2CMgEE8zmJCf1DAdBgNVHQ4EFgQUwHqYaI2J+6sFZAwRfap9"
544 "ZbjKzE4wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMw"
545 "MTAvoC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9zZWN1cmVjYS5j"
546 "cmwwTgYDVR0gBEcwRTBDBgRVHSAAMDswOQYIKwYBBQUHAgEWLWh0dHBzOi8vd3d3"
547 "Lmdlb3RydXN0LmNvbS9yZXNvdXJjZXMvcmVwb3NpdG9yeTANBgkqhkiG9w0BAQUF"
548 "AAOBgQB24RJuTksWEoYwBrKBCM/wCMfHcX5m7sLt1Dsf//DwyE7WQziwuTB9GNBV"
549 "g6JqyzYRnOhIZqNtf7gT1Ef+i1pcc/yu2RsyGTirlzQUqpbS66McFAhJtrvlke+D"
550 "NusdVm/K2rxzY5Dkf3s+Iss9B+1fOHSc4wNQTqGvmO5h8oQ/Eg==";
551
552// kBadSessionExtraField is a custom serialized SSL_SESSION generated by replacing
553// the final (optional) element of |kCustomSession| with tag number 30.
554static const char kBadSessionExtraField[] =
555 "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
556 "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
557 "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
558 "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
559 "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
560 "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
561 "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
562 "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBL4DBAEF";
563
564// kBadSessionVersion is a custom serialized SSL_SESSION generated by replacing
565// the version of |kCustomSession| with 2.
566static const char kBadSessionVersion[] =
567 "MIIBdgIBAgICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
568 "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
569 "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
570 "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
571 "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
572 "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
573 "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
574 "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF";
575
576// kBadSessionTrailingData is a custom serialized SSL_SESSION with trailing data
577// appended.
578static const char kBadSessionTrailingData[] =
579 "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
580 "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
581 "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
582 "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
583 "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
584 "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
585 "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
586 "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEFAAAA";
587
David Benjamin1d77e562015-03-22 17:22:08 -0400588static bool DecodeBase64(std::vector<uint8_t> *out, const char *in) {
David Benjamin751e8892014-10-19 00:59:36 -0400589 size_t len;
David Benjamin751e8892014-10-19 00:59:36 -0400590 if (!EVP_DecodedLength(&len, strlen(in))) {
591 fprintf(stderr, "EVP_DecodedLength failed\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400592 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400593 }
594
David Benjamin1d77e562015-03-22 17:22:08 -0400595 out->resize(len);
David Benjaminef14b2d2015-11-11 14:01:27 -0800596 if (!EVP_DecodeBase64(out->data(), &len, len, (const uint8_t *)in,
David Benjamin751e8892014-10-19 00:59:36 -0400597 strlen(in))) {
598 fprintf(stderr, "EVP_DecodeBase64 failed\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400599 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400600 }
David Benjamin1d77e562015-03-22 17:22:08 -0400601 out->resize(len);
602 return true;
David Benjamin751e8892014-10-19 00:59:36 -0400603}
604
David Benjamin1d77e562015-03-22 17:22:08 -0400605static bool TestSSL_SESSIONEncoding(const char *input_b64) {
David Benjamin751e8892014-10-19 00:59:36 -0400606 const uint8_t *cptr;
607 uint8_t *ptr;
David Benjamin751e8892014-10-19 00:59:36 -0400608
David Benjamin1d77e562015-03-22 17:22:08 -0400609 // Decode the input.
610 std::vector<uint8_t> input;
611 if (!DecodeBase64(&input, input_b64)) {
612 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400613 }
614
David Benjamin1d77e562015-03-22 17:22:08 -0400615 // Verify the SSL_SESSION decodes.
David Benjaminef14b2d2015-11-11 14:01:27 -0800616 ScopedSSL_SESSION session(SSL_SESSION_from_bytes(input.data(), input.size()));
David Benjaminfd67aa82015-06-15 19:41:48 -0400617 if (!session) {
618 fprintf(stderr, "SSL_SESSION_from_bytes failed\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400619 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400620 }
621
David Benjamin1d77e562015-03-22 17:22:08 -0400622 // Verify the SSL_SESSION encoding round-trips.
623 size_t encoded_len;
Adam Langley10f97f32016-07-12 08:09:33 -0700624 ScopedOpenSSLBytes encoded;
David Benjamin1d77e562015-03-22 17:22:08 -0400625 uint8_t *encoded_raw;
626 if (!SSL_SESSION_to_bytes(session.get(), &encoded_raw, &encoded_len)) {
David Benjamin3cac4502014-10-21 01:46:30 -0400627 fprintf(stderr, "SSL_SESSION_to_bytes failed\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400628 return false;
David Benjamin3cac4502014-10-21 01:46:30 -0400629 }
David Benjamin1d77e562015-03-22 17:22:08 -0400630 encoded.reset(encoded_raw);
631 if (encoded_len != input.size() ||
David Benjaminef14b2d2015-11-11 14:01:27 -0800632 memcmp(input.data(), encoded.get(), input.size()) != 0) {
David Benjamin3cac4502014-10-21 01:46:30 -0400633 fprintf(stderr, "SSL_SESSION_to_bytes did not round-trip\n");
Sigbjorn Vik2b23d242015-06-29 15:07:26 +0200634 hexdump(stderr, "Before: ", input.data(), input.size());
635 hexdump(stderr, "After: ", encoded_raw, encoded_len);
David Benjamin1d77e562015-03-22 17:22:08 -0400636 return false;
David Benjamin3cac4502014-10-21 01:46:30 -0400637 }
David Benjamin3cac4502014-10-21 01:46:30 -0400638
David Benjaminfd67aa82015-06-15 19:41:48 -0400639 // Verify the SSL_SESSION also decodes with the legacy API.
David Benjaminef14b2d2015-11-11 14:01:27 -0800640 cptr = input.data();
David Benjaminfd67aa82015-06-15 19:41:48 -0400641 session.reset(d2i_SSL_SESSION(NULL, &cptr, input.size()));
David Benjaminef14b2d2015-11-11 14:01:27 -0800642 if (!session || cptr != input.data() + input.size()) {
David Benjaminfd67aa82015-06-15 19:41:48 -0400643 fprintf(stderr, "d2i_SSL_SESSION failed\n");
644 return false;
645 }
646
David Benjamin1d77e562015-03-22 17:22:08 -0400647 // Verify the SSL_SESSION encoding round-trips via the legacy API.
648 int len = i2d_SSL_SESSION(session.get(), NULL);
649 if (len < 0 || (size_t)len != input.size()) {
David Benjamin751e8892014-10-19 00:59:36 -0400650 fprintf(stderr, "i2d_SSL_SESSION(NULL) returned invalid length\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400651 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400652 }
653
David Benjamin1d77e562015-03-22 17:22:08 -0400654 encoded.reset((uint8_t *)OPENSSL_malloc(input.size()));
655 if (!encoded) {
David Benjamin751e8892014-10-19 00:59:36 -0400656 fprintf(stderr, "malloc failed\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400657 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400658 }
David Benjamin1d77e562015-03-22 17:22:08 -0400659
660 ptr = encoded.get();
661 len = i2d_SSL_SESSION(session.get(), &ptr);
662 if (len < 0 || (size_t)len != input.size()) {
David Benjamin751e8892014-10-19 00:59:36 -0400663 fprintf(stderr, "i2d_SSL_SESSION returned invalid length\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400664 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400665 }
David Benjamin1d77e562015-03-22 17:22:08 -0400666 if (ptr != encoded.get() + input.size()) {
David Benjamin751e8892014-10-19 00:59:36 -0400667 fprintf(stderr, "i2d_SSL_SESSION did not advance ptr correctly\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400668 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400669 }
David Benjaminef14b2d2015-11-11 14:01:27 -0800670 if (memcmp(input.data(), encoded.get(), input.size()) != 0) {
David Benjamin751e8892014-10-19 00:59:36 -0400671 fprintf(stderr, "i2d_SSL_SESSION did not round-trip\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400672 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400673 }
674
David Benjamin1d77e562015-03-22 17:22:08 -0400675 return true;
David Benjamin751e8892014-10-19 00:59:36 -0400676}
677
David Benjaminf297e022015-05-28 19:55:29 -0400678static bool TestBadSSL_SESSIONEncoding(const char *input_b64) {
679 std::vector<uint8_t> input;
680 if (!DecodeBase64(&input, input_b64)) {
681 return false;
682 }
683
684 // Verify that the SSL_SESSION fails to decode.
David Benjaminef14b2d2015-11-11 14:01:27 -0800685 ScopedSSL_SESSION session(SSL_SESSION_from_bytes(input.data(), input.size()));
David Benjaminf297e022015-05-28 19:55:29 -0400686 if (session) {
David Benjaminfd67aa82015-06-15 19:41:48 -0400687 fprintf(stderr, "SSL_SESSION_from_bytes unexpectedly succeeded\n");
David Benjaminf297e022015-05-28 19:55:29 -0400688 return false;
689 }
690 ERR_clear_error();
691 return true;
692}
693
David Benjamin10e664b2016-06-20 22:20:47 -0400694static bool TestDefaultVersion(uint16_t min_version, uint16_t max_version,
David Benjamin1d77e562015-03-22 17:22:08 -0400695 const SSL_METHOD *(*method)(void)) {
696 ScopedSSL_CTX ctx(SSL_CTX_new(method()));
697 if (!ctx) {
698 return false;
David Benjamin82c9e902014-12-12 15:55:27 -0500699 }
David Benjaminb6a0a512016-06-21 10:33:21 -0400700 if (ctx->min_version != min_version || ctx->max_version != max_version) {
701 fprintf(stderr, "Got min %04x, max %04x; wanted min %04x, max %04x\n",
702 ctx->min_version, ctx->max_version, min_version, max_version);
703 return false;
704 }
705 return true;
David Benjamin82c9e902014-12-12 15:55:27 -0500706}
707
David Benjamin1d77e562015-03-22 17:22:08 -0400708static bool CipherGetRFCName(std::string *out, uint16_t value) {
David Benjamin2bdb35c2015-02-21 11:03:06 -0500709 const SSL_CIPHER *cipher = SSL_get_cipher_by_value(value);
710 if (cipher == NULL) {
David Benjamin1d77e562015-03-22 17:22:08 -0400711 return false;
David Benjamin65226252015-02-05 16:49:47 -0500712 }
Adam Langley10f97f32016-07-12 08:09:33 -0700713 ScopedOpenSSLString rfc_name(SSL_CIPHER_get_rfc_name(cipher));
David Benjamin3fa65f02015-05-15 19:11:57 -0400714 if (!rfc_name) {
715 return false;
716 }
David Benjamin67be0482015-04-20 16:19:00 -0400717 out->assign(rfc_name.get());
David Benjamin1d77e562015-03-22 17:22:08 -0400718 return true;
David Benjamin65226252015-02-05 16:49:47 -0500719}
720
721typedef struct {
David Benjamin2bdb35c2015-02-21 11:03:06 -0500722 int id;
David Benjamin65226252015-02-05 16:49:47 -0500723 const char *rfc_name;
724} CIPHER_RFC_NAME_TEST;
725
726static const CIPHER_RFC_NAME_TEST kCipherRFCNameTests[] = {
David Benjamin2bdb35c2015-02-21 11:03:06 -0500727 { SSL3_CK_RSA_DES_192_CBC3_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA" },
728 { SSL3_CK_RSA_RC4_128_MD5, "TLS_RSA_WITH_RC4_MD5" },
729 { TLS1_CK_RSA_WITH_AES_128_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA" },
David Benjamin2bdb35c2015-02-21 11:03:06 -0500730 { TLS1_CK_DHE_RSA_WITH_AES_256_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA" },
731 { TLS1_CK_DHE_RSA_WITH_AES_256_SHA256,
732 "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256" },
David Benjamin2bdb35c2015-02-21 11:03:06 -0500733 { TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256,
734 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" },
735 { TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
736 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" },
737 { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
738 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" },
739 { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
740 "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" },
741 { TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
742 "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" },
743 { TLS1_CK_PSK_WITH_RC4_128_SHA, "TLS_PSK_WITH_RC4_SHA" },
Adam Langley85bc5602015-06-09 09:54:04 -0700744 { TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA,
745 "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA" },
David Benjamin13414b32015-12-09 23:02:39 -0500746 { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
747 "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" },
David Benjamin1d77e562015-03-22 17:22:08 -0400748 // These names are non-standard:
Brian Smith271777f2015-10-03 13:53:33 -1000749 { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD,
David Benjamin2bdb35c2015-02-21 11:03:06 -0500750 "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" },
Brian Smith271777f2015-10-03 13:53:33 -1000751 { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD,
David Benjamin2bdb35c2015-02-21 11:03:06 -0500752 "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" },
David Benjamin65226252015-02-05 16:49:47 -0500753};
754
David Benjamin1d77e562015-03-22 17:22:08 -0400755static bool TestCipherGetRFCName(void) {
756 for (size_t i = 0;
757 i < sizeof(kCipherRFCNameTests) / sizeof(kCipherRFCNameTests[0]); i++) {
David Benjamin65226252015-02-05 16:49:47 -0500758 const CIPHER_RFC_NAME_TEST *test = &kCipherRFCNameTests[i];
David Benjamin1d77e562015-03-22 17:22:08 -0400759 std::string rfc_name;
760 if (!CipherGetRFCName(&rfc_name, test->id & 0xffff)) {
761 fprintf(stderr, "SSL_CIPHER_get_rfc_name failed\n");
762 return false;
David Benjamin65226252015-02-05 16:49:47 -0500763 }
David Benjamin1d77e562015-03-22 17:22:08 -0400764 if (rfc_name != test->rfc_name) {
David Benjamin65226252015-02-05 16:49:47 -0500765 fprintf(stderr, "SSL_CIPHER_get_rfc_name: got '%s', wanted '%s'\n",
David Benjamin1d77e562015-03-22 17:22:08 -0400766 rfc_name.c_str(), test->rfc_name);
767 return false;
David Benjamin65226252015-02-05 16:49:47 -0500768 }
David Benjamin65226252015-02-05 16:49:47 -0500769 }
David Benjamin1d77e562015-03-22 17:22:08 -0400770 return true;
David Benjamin65226252015-02-05 16:49:47 -0500771}
772
David Benjamin422fe082015-07-21 22:03:43 -0400773// CreateSessionWithTicket returns a sample |SSL_SESSION| with the ticket
774// replaced for one of length |ticket_len| or nullptr on failure.
775static ScopedSSL_SESSION CreateSessionWithTicket(size_t ticket_len) {
776 std::vector<uint8_t> der;
777 if (!DecodeBase64(&der, kOpenSSLSession)) {
778 return nullptr;
779 }
David Benjaminef14b2d2015-11-11 14:01:27 -0800780 ScopedSSL_SESSION session(SSL_SESSION_from_bytes(der.data(), der.size()));
David Benjamin422fe082015-07-21 22:03:43 -0400781 if (!session) {
782 return nullptr;
783 }
784
785 // Swap out the ticket for a garbage one.
786 OPENSSL_free(session->tlsext_tick);
787 session->tlsext_tick = reinterpret_cast<uint8_t*>(OPENSSL_malloc(ticket_len));
788 if (session->tlsext_tick == nullptr) {
789 return nullptr;
790 }
791 memset(session->tlsext_tick, 'a', ticket_len);
792 session->tlsext_ticklen = ticket_len;
David Benjamin1269ddd2015-10-18 15:18:55 -0400793
794 // Fix up the timeout.
795 session->time = time(NULL);
David Benjamin422fe082015-07-21 22:03:43 -0400796 return session;
797}
798
799// GetClientHelloLen creates a client SSL connection with a ticket of length
800// |ticket_len| and records the ClientHello. It returns the length of the
801// ClientHello, not including the record header, on success and zero on error.
802static size_t GetClientHelloLen(size_t ticket_len) {
803 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
804 ScopedSSL_SESSION session = CreateSessionWithTicket(ticket_len);
805 if (!ctx || !session) {
806 return 0;
807 }
808 ScopedSSL ssl(SSL_new(ctx.get()));
David Benjamin14a077c2016-07-20 11:16:57 +0200809 ScopedBIO bio(BIO_new(BIO_s_mem()));
810 if (!ssl || !bio || !SSL_set_session(ssl.get(), session.get())) {
David Benjamin422fe082015-07-21 22:03:43 -0400811 return 0;
812 }
David Benjamin14a077c2016-07-20 11:16:57 +0200813 // Do not configure a reading BIO, but record what's written to a memory BIO.
814 SSL_set_bio(ssl.get(), nullptr /* rbio */, BIO_up_ref(bio.get()));
815 int ret = SSL_connect(ssl.get());
816 if (ret > 0) {
817 // SSL_connect should fail without a BIO to write to.
David Benjamin422fe082015-07-21 22:03:43 -0400818 return 0;
819 }
David Benjamin14a077c2016-07-20 11:16:57 +0200820 ERR_clear_error();
821
822 const uint8_t *unused;
823 size_t client_hello_len;
824 if (!BIO_mem_contents(bio.get(), &unused, &client_hello_len) ||
825 client_hello_len <= SSL3_RT_HEADER_LENGTH) {
826 return 0;
827 }
828 return client_hello_len - SSL3_RT_HEADER_LENGTH;
David Benjamin422fe082015-07-21 22:03:43 -0400829}
830
831struct PaddingTest {
832 size_t input_len, padded_len;
833};
834
835static const PaddingTest kPaddingTests[] = {
836 // ClientHellos of length below 0x100 do not require padding.
837 {0xfe, 0xfe},
838 {0xff, 0xff},
839 // ClientHellos of length 0x100 through 0x1fb are padded up to 0x200.
840 {0x100, 0x200},
841 {0x123, 0x200},
842 {0x1fb, 0x200},
843 // ClientHellos of length 0x1fc through 0x1ff get padded beyond 0x200. The
844 // padding extension takes a minimum of four bytes plus one required content
845 // byte. (To work around yet more server bugs, we avoid empty final
846 // extensions.)
847 {0x1fc, 0x201},
848 {0x1fd, 0x202},
849 {0x1fe, 0x203},
850 {0x1ff, 0x204},
851 // Finally, larger ClientHellos need no padding.
852 {0x200, 0x200},
853 {0x201, 0x201},
854};
855
856static bool TestPaddingExtension() {
857 // Sample a baseline length.
858 size_t base_len = GetClientHelloLen(1);
859 if (base_len == 0) {
860 return false;
861 }
862
863 for (const PaddingTest &test : kPaddingTests) {
864 if (base_len > test.input_len) {
865 fprintf(stderr, "Baseline ClientHello too long.\n");
866 return false;
867 }
868
869 size_t padded_len = GetClientHelloLen(1 + test.input_len - base_len);
870 if (padded_len != test.padded_len) {
871 fprintf(stderr, "%u-byte ClientHello padded to %u bytes, not %u.\n",
872 static_cast<unsigned>(test.input_len),
873 static_cast<unsigned>(padded_len),
874 static_cast<unsigned>(test.padded_len));
875 return false;
876 }
877 }
878 return true;
879}
880
David Benjamin1d128f32015-09-08 17:41:40 -0400881// Test that |SSL_get_client_CA_list| echoes back the configured parameter even
882// before configuring as a server.
883static bool TestClientCAList() {
884 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
885 if (!ctx) {
886 return false;
887 }
888 ScopedSSL ssl(SSL_new(ctx.get()));
889 if (!ssl) {
890 return false;
891 }
892
893 STACK_OF(X509_NAME) *stack = sk_X509_NAME_new_null();
894 if (stack == nullptr) {
895 return false;
896 }
897 // |SSL_set_client_CA_list| takes ownership.
898 SSL_set_client_CA_list(ssl.get(), stack);
899
900 return SSL_get_client_CA_list(ssl.get()) == stack;
901}
902
David Benjamin0f653952015-10-18 14:28:01 -0400903static void AppendSession(SSL_SESSION *session, void *arg) {
904 std::vector<SSL_SESSION*> *out =
905 reinterpret_cast<std::vector<SSL_SESSION*>*>(arg);
906 out->push_back(session);
907}
908
909// ExpectCache returns true if |ctx|'s session cache consists of |expected|, in
910// order.
911static bool ExpectCache(SSL_CTX *ctx,
912 const std::vector<SSL_SESSION*> &expected) {
913 // Check the linked list.
914 SSL_SESSION *ptr = ctx->session_cache_head;
915 for (SSL_SESSION *session : expected) {
916 if (ptr != session) {
917 return false;
918 }
919 // TODO(davidben): This is an absurd way to denote the end of the list.
920 if (ptr->next ==
921 reinterpret_cast<SSL_SESSION *>(&ctx->session_cache_tail)) {
922 ptr = nullptr;
923 } else {
924 ptr = ptr->next;
925 }
926 }
927 if (ptr != nullptr) {
928 return false;
929 }
930
931 // Check the hash table.
932 std::vector<SSL_SESSION*> actual, expected_copy;
933 lh_SSL_SESSION_doall_arg(SSL_CTX_sessions(ctx), AppendSession, &actual);
934 expected_copy = expected;
935
936 std::sort(actual.begin(), actual.end());
937 std::sort(expected_copy.begin(), expected_copy.end());
938
939 return actual == expected_copy;
940}
941
942static ScopedSSL_SESSION CreateTestSession(uint32_t number) {
943 ScopedSSL_SESSION ret(SSL_SESSION_new());
944 if (!ret) {
945 return nullptr;
946 }
947
948 ret->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
949 memset(ret->session_id, 0, ret->session_id_length);
950 memcpy(ret->session_id, &number, sizeof(number));
951 return ret;
952}
953
David Benjamin0f653952015-10-18 14:28:01 -0400954// Test that the internal session cache behaves as expected.
955static bool TestInternalSessionCache() {
956 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
957 if (!ctx) {
958 return false;
959 }
960
961 // Prepare 10 test sessions.
David Benjamin4f6acaf2015-11-21 03:00:50 -0500962 std::vector<ScopedSSL_SESSION> sessions;
David Benjamin0f653952015-10-18 14:28:01 -0400963 for (int i = 0; i < 10; i++) {
964 ScopedSSL_SESSION session = CreateTestSession(i);
965 if (!session) {
966 return false;
967 }
David Benjamin4f6acaf2015-11-21 03:00:50 -0500968 sessions.push_back(std::move(session));
David Benjamin0f653952015-10-18 14:28:01 -0400969 }
970
971 SSL_CTX_sess_set_cache_size(ctx.get(), 5);
972
973 // Insert all the test sessions.
David Benjamin4f6acaf2015-11-21 03:00:50 -0500974 for (const auto &session : sessions) {
975 if (!SSL_CTX_add_session(ctx.get(), session.get())) {
David Benjamin0f653952015-10-18 14:28:01 -0400976 return false;
977 }
978 }
979
980 // Only the last five should be in the list.
David Benjamin4f6acaf2015-11-21 03:00:50 -0500981 std::vector<SSL_SESSION*> expected = {
982 sessions[9].get(),
983 sessions[8].get(),
984 sessions[7].get(),
985 sessions[6].get(),
986 sessions[5].get(),
987 };
David Benjamin0f653952015-10-18 14:28:01 -0400988 if (!ExpectCache(ctx.get(), expected)) {
989 return false;
990 }
991
992 // Inserting an element already in the cache should fail.
David Benjamin4f6acaf2015-11-21 03:00:50 -0500993 if (SSL_CTX_add_session(ctx.get(), sessions[7].get()) ||
David Benjamin0f653952015-10-18 14:28:01 -0400994 !ExpectCache(ctx.get(), expected)) {
995 return false;
996 }
997
998 // Although collisions should be impossible (256-bit session IDs), the cache
999 // must handle them gracefully.
1000 ScopedSSL_SESSION collision(CreateTestSession(7));
1001 if (!collision || !SSL_CTX_add_session(ctx.get(), collision.get())) {
1002 return false;
1003 }
David Benjamin4f6acaf2015-11-21 03:00:50 -05001004 expected = {
1005 collision.get(),
1006 sessions[9].get(),
1007 sessions[8].get(),
1008 sessions[6].get(),
1009 sessions[5].get(),
1010 };
David Benjamin0f653952015-10-18 14:28:01 -04001011 if (!ExpectCache(ctx.get(), expected)) {
1012 return false;
1013 }
1014
1015 // Removing sessions behaves correctly.
David Benjamin4f6acaf2015-11-21 03:00:50 -05001016 if (!SSL_CTX_remove_session(ctx.get(), sessions[6].get())) {
David Benjamin0f653952015-10-18 14:28:01 -04001017 return false;
1018 }
David Benjamin4f6acaf2015-11-21 03:00:50 -05001019 expected = {
1020 collision.get(),
1021 sessions[9].get(),
1022 sessions[8].get(),
1023 sessions[5].get(),
1024 };
David Benjamin0f653952015-10-18 14:28:01 -04001025 if (!ExpectCache(ctx.get(), expected)) {
1026 return false;
1027 }
1028
1029 // Removing sessions requires an exact match.
David Benjamin4f6acaf2015-11-21 03:00:50 -05001030 if (SSL_CTX_remove_session(ctx.get(), sessions[0].get()) ||
1031 SSL_CTX_remove_session(ctx.get(), sessions[7].get()) ||
David Benjamin0f653952015-10-18 14:28:01 -04001032 !ExpectCache(ctx.get(), expected)) {
1033 return false;
1034 }
1035
1036 return true;
1037}
1038
David Benjaminde942382016-02-11 12:02:01 -05001039static uint16_t EpochFromSequence(uint64_t seq) {
1040 return static_cast<uint16_t>(seq >> 48);
1041}
1042
1043static ScopedX509 GetTestCertificate() {
1044 static const char kCertPEM[] =
1045 "-----BEGIN CERTIFICATE-----\n"
1046 "MIICWDCCAcGgAwIBAgIJAPuwTC6rEJsMMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV\n"
1047 "BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX\n"
1048 "aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDIzMjA1MDQwWhcNMTcwNDIyMjA1MDQwWjBF\n"
1049 "MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50\n"
1050 "ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n"
1051 "gQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92kWdGMdAQhLci\n"
1052 "HnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiFKKAnHmUcrgfV\n"
1053 "W28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQABo1AwTjAdBgNV\n"
1054 "HQ4EFgQUi3XVrMsIvg4fZbf6Vr5sp3Xaha8wHwYDVR0jBBgwFoAUi3XVrMsIvg4f\n"
1055 "Zbf6Vr5sp3Xaha8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQA76Hht\n"
1056 "ldY9avcTGSwbwoiuIqv0jTL1fHFnzy3RHMLDh+Lpvolc5DSrSJHCP5WuK0eeJXhr\n"
1057 "T5oQpHL9z/cCDLAKCKRa4uV0fhEdOWBqyR9p8y5jJtye72t6CuFUV5iqcpF4BH4f\n"
1058 "j2VNHwsSrJwkD4QUGlUtH7vwnQmyCFxZMmWAJg==\n"
1059 "-----END CERTIFICATE-----\n";
Steven Valdezd8eea142016-02-24 14:00:22 -05001060 ScopedBIO bio(BIO_new_mem_buf(kCertPEM, strlen(kCertPEM)));
David Benjaminde942382016-02-11 12:02:01 -05001061 return ScopedX509(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
1062}
1063
1064static ScopedEVP_PKEY GetTestKey() {
1065 static const char kKeyPEM[] =
1066 "-----BEGIN RSA PRIVATE KEY-----\n"
1067 "MIICXgIBAAKBgQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92\n"
1068 "kWdGMdAQhLciHnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiF\n"
1069 "KKAnHmUcrgfVW28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQAB\n"
1070 "AoGBAIBy09Fd4DOq/Ijp8HeKuCMKTHqTW1xGHshLQ6jwVV2vWZIn9aIgmDsvkjCe\n"
1071 "i6ssZvnbjVcwzSoByhjN8ZCf/i15HECWDFFh6gt0P5z0MnChwzZmvatV/FXCT0j+\n"
1072 "WmGNB/gkehKjGXLLcjTb6dRYVJSCZhVuOLLcbWIV10gggJQBAkEA8S8sGe4ezyyZ\n"
1073 "m4e9r95g6s43kPqtj5rewTsUxt+2n4eVodD+ZUlCULWVNAFLkYRTBCASlSrm9Xhj\n"
1074 "QpmWAHJUkQJBAOVzQdFUaewLtdOJoPCtpYoY1zd22eae8TQEmpGOR11L6kbxLQsk\n"
1075 "aMly/DOnOaa82tqAGTdqDEZgSNmCeKKknmECQAvpnY8GUOVAubGR6c+W90iBuQLj\n"
1076 "LtFp/9ihd2w/PoDwrHZaoUYVcT4VSfJQog/k7kjE4MYXYWL8eEKg3WTWQNECQQDk\n"
1077 "104Wi91Umd1PzF0ijd2jXOERJU1wEKe6XLkYYNHWQAe5l4J4MWj9OdxFXAxIuuR/\n"
1078 "tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd\n"
1079 "moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==\n"
1080 "-----END RSA PRIVATE KEY-----\n";
Steven Valdezd8eea142016-02-24 14:00:22 -05001081 ScopedBIO bio(BIO_new_mem_buf(kKeyPEM, strlen(kKeyPEM)));
David Benjaminde942382016-02-11 12:02:01 -05001082 return ScopedEVP_PKEY(
1083 PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
1084}
1085
David Benjamin686bb192016-05-10 15:15:41 -04001086static bool ConnectClientAndServer(ScopedSSL *out_client, ScopedSSL *out_server,
1087 SSL_CTX *client_ctx, SSL_CTX *server_ctx) {
1088 ScopedSSL client(SSL_new(client_ctx)), server(SSL_new(server_ctx));
David Benjaminde942382016-02-11 12:02:01 -05001089 if (!client || !server) {
1090 return false;
1091 }
1092 SSL_set_connect_state(client.get());
1093 SSL_set_accept_state(server.get());
1094
1095 BIO *bio1, *bio2;
1096 if (!BIO_new_bio_pair(&bio1, 0, &bio2, 0)) {
1097 return false;
1098 }
1099 // SSL_set_bio takes ownership.
1100 SSL_set_bio(client.get(), bio1, bio1);
1101 SSL_set_bio(server.get(), bio2, bio2);
1102
1103 // Drive both their handshakes to completion.
1104 for (;;) {
1105 int client_ret = SSL_do_handshake(client.get());
1106 int client_err = SSL_get_error(client.get(), client_ret);
1107 if (client_err != SSL_ERROR_NONE &&
1108 client_err != SSL_ERROR_WANT_READ &&
1109 client_err != SSL_ERROR_WANT_WRITE) {
1110 fprintf(stderr, "Client error: %d\n", client_err);
1111 return false;
1112 }
1113
1114 int server_ret = SSL_do_handshake(server.get());
1115 int server_err = SSL_get_error(server.get(), server_ret);
1116 if (server_err != SSL_ERROR_NONE &&
1117 server_err != SSL_ERROR_WANT_READ &&
1118 server_err != SSL_ERROR_WANT_WRITE) {
1119 fprintf(stderr, "Server error: %d\n", server_err);
1120 return false;
1121 }
1122
1123 if (client_ret == 1 && server_ret == 1) {
1124 break;
1125 }
1126 }
1127
David Benjamin686bb192016-05-10 15:15:41 -04001128 *out_client = std::move(client);
1129 *out_server = std::move(server);
1130 return true;
1131}
1132
1133static bool TestSequenceNumber(bool dtls) {
1134 ScopedSSL_CTX client_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
1135 ScopedSSL_CTX server_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
1136 if (!client_ctx || !server_ctx) {
1137 return false;
1138 }
1139
1140 ScopedX509 cert = GetTestCertificate();
1141 ScopedEVP_PKEY key = GetTestKey();
1142 if (!cert || !key ||
1143 !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
1144 !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
1145 return false;
1146 }
1147
1148 ScopedSSL client, server;
1149 if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
1150 server_ctx.get())) {
1151 return false;
1152 }
1153
David Benjaminde942382016-02-11 12:02:01 -05001154 uint64_t client_read_seq = SSL_get_read_sequence(client.get());
1155 uint64_t client_write_seq = SSL_get_write_sequence(client.get());
1156 uint64_t server_read_seq = SSL_get_read_sequence(server.get());
1157 uint64_t server_write_seq = SSL_get_write_sequence(server.get());
1158
1159 if (dtls) {
1160 // Both client and server must be at epoch 1.
1161 if (EpochFromSequence(client_read_seq) != 1 ||
1162 EpochFromSequence(client_write_seq) != 1 ||
1163 EpochFromSequence(server_read_seq) != 1 ||
1164 EpochFromSequence(server_write_seq) != 1) {
1165 fprintf(stderr, "Bad epochs.\n");
1166 return false;
1167 }
1168
1169 // The next record to be written should exceed the largest received.
1170 if (client_write_seq <= server_read_seq ||
1171 server_write_seq <= client_read_seq) {
1172 fprintf(stderr, "Inconsistent sequence numbers.\n");
1173 return false;
1174 }
1175 } else {
1176 // The next record to be written should equal the next to be received.
1177 if (client_write_seq != server_read_seq ||
1178 server_write_seq != client_write_seq) {
1179 fprintf(stderr, "Inconsistent sequence numbers.\n");
1180 return false;
1181 }
1182 }
1183
1184 // Send a record from client to server.
1185 uint8_t byte = 0;
1186 if (SSL_write(client.get(), &byte, 1) != 1 ||
1187 SSL_read(server.get(), &byte, 1) != 1) {
1188 fprintf(stderr, "Could not send byte.\n");
1189 return false;
1190 }
1191
1192 // The client write and server read sequence numbers should have incremented.
1193 if (client_write_seq + 1 != SSL_get_write_sequence(client.get()) ||
1194 server_read_seq + 1 != SSL_get_read_sequence(server.get())) {
1195 fprintf(stderr, "Sequence numbers did not increment.\n");\
1196 return false;
1197 }
1198
1199 return true;
1200}
1201
David Benjamin686bb192016-05-10 15:15:41 -04001202static bool TestOneSidedShutdown() {
1203 ScopedSSL_CTX client_ctx(SSL_CTX_new(TLS_method()));
1204 ScopedSSL_CTX server_ctx(SSL_CTX_new(TLS_method()));
1205 if (!client_ctx || !server_ctx) {
1206 return false;
1207 }
1208
1209 ScopedX509 cert = GetTestCertificate();
1210 ScopedEVP_PKEY key = GetTestKey();
1211 if (!cert || !key ||
1212 !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
1213 !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
1214 return false;
1215 }
1216
1217 ScopedSSL client, server;
1218 if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
1219 server_ctx.get())) {
1220 return false;
1221 }
1222
1223 // Shut down half the connection. SSL_shutdown will return 0 to signal only
1224 // one side has shut down.
1225 if (SSL_shutdown(client.get()) != 0) {
1226 fprintf(stderr, "Could not shutdown.\n");
1227 return false;
1228 }
1229
1230 // Reading from the server should consume the EOF.
1231 uint8_t byte;
1232 if (SSL_read(server.get(), &byte, 1) != 0 ||
1233 SSL_get_error(server.get(), 0) != SSL_ERROR_ZERO_RETURN) {
1234 fprintf(stderr, "Connection was not shut down cleanly.\n");
1235 return false;
1236 }
1237
1238 // However, the server may continue to write data and then shut down the
1239 // connection.
1240 byte = 42;
1241 if (SSL_write(server.get(), &byte, 1) != 1 ||
1242 SSL_read(client.get(), &byte, 1) != 1 ||
1243 byte != 42) {
1244 fprintf(stderr, "Could not send byte.\n");
1245 return false;
1246 }
1247
1248 // The server may then shutdown the connection.
1249 if (SSL_shutdown(server.get()) != 1 ||
1250 SSL_shutdown(client.get()) != 1) {
1251 fprintf(stderr, "Could not complete shutdown.\n");
1252 return false;
1253 }
1254
1255 return true;
1256}
Steven Valdez87eab492016-06-27 16:34:59 -04001257static bool TestSessionDuplication() {
1258 ScopedSSL_CTX client_ctx(SSL_CTX_new(TLS_method()));
1259 ScopedSSL_CTX server_ctx(SSL_CTX_new(TLS_method()));
1260 if (!client_ctx || !server_ctx) {
1261 return false;
1262 }
1263
1264 ScopedX509 cert = GetTestCertificate();
1265 ScopedEVP_PKEY key = GetTestKey();
1266 if (!cert || !key ||
1267 !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
1268 !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
1269 return false;
1270 }
1271
1272 ScopedSSL client, server;
1273 if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
1274 server_ctx.get())) {
1275 return false;
1276 }
1277
1278 SSL_SESSION *session0 = SSL_get_session(client.get());
1279 ScopedSSL_SESSION session1(SSL_SESSION_dup(session0, 1));
1280 if (!session1) {
1281 return false;
1282 }
1283
1284 uint8_t *s0_bytes, *s1_bytes;
1285 size_t s0_len, s1_len;
1286
1287 if (!SSL_SESSION_to_bytes(session0, &s0_bytes, &s0_len)) {
1288 return false;
1289 }
1290 ScopedOpenSSLBytes free_s0(s0_bytes);
1291
1292 if (!SSL_SESSION_to_bytes(session1.get(), &s1_bytes, &s1_len)) {
1293 return false;
1294 }
1295 ScopedOpenSSLBytes free_s1(s1_bytes);
1296
1297 return s0_len == s1_len && memcmp(s0_bytes, s1_bytes, s0_len) == 0;
1298}
David Benjamin686bb192016-05-10 15:15:41 -04001299
David Benjamin5c0fb882016-06-14 14:03:51 -04001300static bool ExpectFDs(const SSL *ssl, int rfd, int wfd) {
1301 if (SSL_get_rfd(ssl) != rfd || SSL_get_wfd(ssl) != wfd) {
1302 fprintf(stderr, "Got fds %d and %d, wanted %d and %d.\n", SSL_get_rfd(ssl),
1303 SSL_get_wfd(ssl), rfd, wfd);
1304 return false;
1305 }
1306
1307 // The wrapper BIOs are always equal when fds are equal, even if set
1308 // individually.
1309 if (rfd == wfd && SSL_get_rbio(ssl) != SSL_get_wbio(ssl)) {
1310 fprintf(stderr, "rbio and wbio did not match.\n");
1311 return false;
1312 }
1313
1314 return true;
1315}
1316
1317static bool TestSetFD() {
1318 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
1319 if (!ctx) {
1320 return false;
1321 }
1322
1323 // Test setting different read and write FDs.
1324 ScopedSSL ssl(SSL_new(ctx.get()));
1325 if (!ssl ||
1326 !SSL_set_rfd(ssl.get(), 1) ||
1327 !SSL_set_wfd(ssl.get(), 2) ||
1328 !ExpectFDs(ssl.get(), 1, 2)) {
1329 return false;
1330 }
1331
1332 // Test setting the same FD.
1333 ssl.reset(SSL_new(ctx.get()));
1334 if (!ssl ||
1335 !SSL_set_fd(ssl.get(), 1) ||
1336 !ExpectFDs(ssl.get(), 1, 1)) {
1337 return false;
1338 }
1339
1340 // Test setting the same FD one side at a time.
1341 ssl.reset(SSL_new(ctx.get()));
1342 if (!ssl ||
1343 !SSL_set_rfd(ssl.get(), 1) ||
1344 !SSL_set_wfd(ssl.get(), 1) ||
1345 !ExpectFDs(ssl.get(), 1, 1)) {
1346 return false;
1347 }
1348
1349 // Test setting the same FD in the other order.
1350 ssl.reset(SSL_new(ctx.get()));
1351 if (!ssl ||
1352 !SSL_set_wfd(ssl.get(), 1) ||
1353 !SSL_set_rfd(ssl.get(), 1) ||
1354 !ExpectFDs(ssl.get(), 1, 1)) {
1355 return false;
1356 }
1357
David Benjamin5c0fb882016-06-14 14:03:51 -04001358 // Test changing the read FD partway through.
1359 ssl.reset(SSL_new(ctx.get()));
1360 if (!ssl ||
1361 !SSL_set_fd(ssl.get(), 1) ||
1362 !SSL_set_rfd(ssl.get(), 2) ||
1363 !ExpectFDs(ssl.get(), 2, 1)) {
1364 return false;
1365 }
David Benjamin5c0fb882016-06-14 14:03:51 -04001366
1367 // Test changing the write FD partway through.
1368 ssl.reset(SSL_new(ctx.get()));
1369 if (!ssl ||
1370 !SSL_set_fd(ssl.get(), 1) ||
1371 !SSL_set_wfd(ssl.get(), 2) ||
1372 !ExpectFDs(ssl.get(), 1, 2)) {
1373 return false;
1374 }
1375
1376 // Test a no-op change to the read FD partway through.
1377 ssl.reset(SSL_new(ctx.get()));
1378 if (!ssl ||
1379 !SSL_set_fd(ssl.get(), 1) ||
1380 !SSL_set_rfd(ssl.get(), 1) ||
1381 !ExpectFDs(ssl.get(), 1, 1)) {
1382 return false;
1383 }
1384
1385 // Test a no-op change to the write FD partway through.
1386 ssl.reset(SSL_new(ctx.get()));
1387 if (!ssl ||
1388 !SSL_set_fd(ssl.get(), 1) ||
1389 !SSL_set_wfd(ssl.get(), 1) ||
1390 !ExpectFDs(ssl.get(), 1, 1)) {
1391 return false;
1392 }
1393
1394 // ASan builds will implicitly test that the internal |BIO| reference-counting
1395 // is correct.
1396
1397 return true;
1398}
1399
David Benjamin25490f22016-07-14 00:22:54 -04001400static uint16_t kVersions[] = {
1401 SSL3_VERSION, TLS1_VERSION, TLS1_1_VERSION, TLS1_2_VERSION, TLS1_3_VERSION,
1402};
1403
1404static int VerifySucceed(X509_STORE_CTX *store_ctx, void *arg) { return 1; }
1405
David Benjaminadd5e522016-07-14 00:33:24 -04001406static bool TestGetPeerCertificate() {
1407 ScopedX509 cert = GetTestCertificate();
1408 ScopedEVP_PKEY key = GetTestKey();
1409 if (!cert || !key) {
1410 return false;
1411 }
1412
1413 for (uint16_t version : kVersions) {
1414 // Configure both client and server to accept any certificate.
1415 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
1416 if (!ctx ||
1417 !SSL_CTX_use_certificate(ctx.get(), cert.get()) ||
1418 !SSL_CTX_use_PrivateKey(ctx.get(), key.get())) {
1419 return false;
1420 }
1421 SSL_CTX_set_min_version(ctx.get(), version);
1422 SSL_CTX_set_max_version(ctx.get(), version);
1423 SSL_CTX_set_verify(
1424 ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
1425 SSL_CTX_set_cert_verify_callback(ctx.get(), VerifySucceed, NULL);
1426
1427 ScopedSSL client, server;
1428 if (!ConnectClientAndServer(&client, &server, ctx.get(), ctx.get())) {
1429 return false;
1430 }
1431
1432 // Client and server should both see the leaf certificate.
1433 ScopedX509 peer(SSL_get_peer_certificate(server.get()));
1434 if (!peer || X509_cmp(cert.get(), peer.get()) != 0) {
1435 fprintf(stderr, "%x: Server peer certificate did not match.\n", version);
1436 return false;
1437 }
1438
1439 peer.reset(SSL_get_peer_certificate(client.get()));
1440 if (!peer || X509_cmp(cert.get(), peer.get()) != 0) {
1441 fprintf(stderr, "%x: Client peer certificate did not match.\n", version);
1442 return false;
1443 }
1444
1445 // However, for historical reasons, the chain includes the leaf on the
1446 // client, but does not on the server.
1447 if (sk_X509_num(SSL_get_peer_cert_chain(client.get())) != 1) {
1448 fprintf(stderr, "%x: Client peer chain was incorrect.\n", version);
1449 return false;
1450 }
1451
1452 if (sk_X509_num(SSL_get_peer_cert_chain(server.get())) != 0) {
1453 fprintf(stderr, "%x: Server peer chain was incorrect.\n", version);
1454 return false;
1455 }
1456 }
1457
1458 return true;
1459}
1460
David Benjamin25490f22016-07-14 00:22:54 -04001461static bool TestRetainOnlySHA256OfCerts() {
1462 ScopedX509 cert = GetTestCertificate();
1463 ScopedEVP_PKEY key = GetTestKey();
1464 if (!cert || !key) {
1465 return false;
1466 }
1467
1468 uint8_t *cert_der = NULL;
1469 int cert_der_len = i2d_X509(cert.get(), &cert_der);
1470 if (cert_der_len < 0) {
1471 return false;
1472 }
1473 ScopedOpenSSLBytes free_cert_der(cert_der);
1474
1475 uint8_t cert_sha256[SHA256_DIGEST_LENGTH];
1476 SHA256(cert_der, cert_der_len, cert_sha256);
1477
1478 for (uint16_t version : kVersions) {
1479 // Configure both client and server to accept any certificate, but the
1480 // server must retain only the SHA-256 of the peer.
1481 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
1482 if (!ctx ||
1483 !SSL_CTX_use_certificate(ctx.get(), cert.get()) ||
1484 !SSL_CTX_use_PrivateKey(ctx.get(), key.get())) {
1485 return false;
1486 }
1487 SSL_CTX_set_min_version(ctx.get(), version);
1488 SSL_CTX_set_max_version(ctx.get(), version);
1489 SSL_CTX_set_verify(
1490 ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
1491 SSL_CTX_set_cert_verify_callback(ctx.get(), VerifySucceed, NULL);
1492 SSL_CTX_set_retain_only_sha256_of_client_certs(ctx.get(), 1);
1493
1494 ScopedSSL client, server;
1495 if (!ConnectClientAndServer(&client, &server, ctx.get(), ctx.get())) {
1496 return false;
1497 }
1498
1499 // The peer certificate has been dropped.
1500 ScopedX509 peer(SSL_get_peer_certificate(server.get()));
1501 if (peer) {
1502 fprintf(stderr, "%x: Peer certificate was retained.\n", version);
1503 return false;
1504 }
1505
1506 SSL_SESSION *session = SSL_get_session(server.get());
1507 if (!session->peer_sha256_valid) {
1508 fprintf(stderr, "%x: peer_sha256_valid was not set.\n", version);
1509 return false;
1510 }
1511
1512 if (memcmp(cert_sha256, session->peer_sha256, SHA256_DIGEST_LENGTH) != 0) {
1513 fprintf(stderr, "%x: peer_sha256 did not match.\n", version);
1514 return false;
1515 }
1516 }
1517
1518 return true;
1519}
1520
David Benjamin1d128f32015-09-08 17:41:40 -04001521int main() {
David Benjamin7a1eefd2015-10-17 23:39:22 -04001522 CRYPTO_library_init();
David Benjaminbb0a17c2014-09-20 15:35:39 -04001523
Adam Langley10f97f32016-07-12 08:09:33 -07001524 if (!TestCipherRules() ||
1525 !TestSSL_SESSIONEncoding(kOpenSSLSession) ||
1526 !TestSSL_SESSIONEncoding(kCustomSession) ||
1527 !TestSSL_SESSIONEncoding(kBoringSSLSession) ||
1528 !TestBadSSL_SESSIONEncoding(kBadSessionExtraField) ||
1529 !TestBadSSL_SESSIONEncoding(kBadSessionVersion) ||
1530 !TestBadSSL_SESSIONEncoding(kBadSessionTrailingData) ||
David Benjamin10e664b2016-06-20 22:20:47 -04001531 // TODO(svaldez): Update this when TLS 1.3 is enabled by default.
Adam Langley10f97f32016-07-12 08:09:33 -07001532 !TestDefaultVersion(SSL3_VERSION, TLS1_2_VERSION, &TLS_method) ||
1533 !TestDefaultVersion(SSL3_VERSION, SSL3_VERSION, &SSLv3_method) ||
1534 !TestDefaultVersion(TLS1_VERSION, TLS1_VERSION, &TLSv1_method) ||
1535 !TestDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION, &TLSv1_1_method) ||
1536 !TestDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION, &TLSv1_2_method) ||
1537 !TestDefaultVersion(TLS1_1_VERSION, TLS1_2_VERSION, &DTLS_method) ||
1538 !TestDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION, &DTLSv1_method) ||
1539 !TestDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION, &DTLSv1_2_method) ||
1540 !TestCipherGetRFCName() ||
1541 !TestPaddingExtension() ||
1542 !TestClientCAList() ||
1543 !TestInternalSessionCache() ||
1544 !TestSequenceNumber(false /* TLS */) ||
1545 !TestSequenceNumber(true /* DTLS */) ||
1546 !TestOneSidedShutdown() ||
Steven Valdez87eab492016-06-27 16:34:59 -04001547 !TestSessionDuplication() ||
David Benjamin25490f22016-07-14 00:22:54 -04001548 !TestSetFD() ||
David Benjaminadd5e522016-07-14 00:33:24 -04001549 !TestGetPeerCertificate() ||
David Benjamin14a077c2016-07-20 11:16:57 +02001550 !TestRetainOnlySHA256OfCerts()) {
Brian Smith83a82982015-04-09 16:21:10 -10001551 ERR_print_errors_fp(stderr);
David Benjaminbb0a17c2014-09-20 15:35:39 -04001552 return 1;
1553 }
1554
David Benjamin2e521212014-07-16 14:37:51 -04001555 printf("PASS\n");
1556 return 0;
1557}