blob: 97ade039fefc0739dd26c6f3a820a6c145b06e6e [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
David Benjaminafc64de2016-07-19 17:12:41 +0200799static bool GetClientHello(SSL *ssl, std::vector<uint8_t> *out) {
800 ScopedBIO bio(BIO_new(BIO_s_mem()));
801 if (!bio) {
802 return false;
803 }
804 // Do not configure a reading BIO, but record what's written to a memory BIO.
805 SSL_set_bio(ssl, nullptr /* rbio */, BIO_up_ref(bio.get()));
806 int ret = SSL_connect(ssl);
807 if (ret > 0) {
808 // SSL_connect should fail without a BIO to write to.
809 return false;
810 }
811 ERR_clear_error();
812
813 const uint8_t *client_hello;
814 size_t client_hello_len;
815 if (!BIO_mem_contents(bio.get(), &client_hello, &client_hello_len)) {
816 return false;
817 }
818 *out = std::vector<uint8_t>(client_hello, client_hello + client_hello_len);
819 return true;
820}
821
David Benjamin422fe082015-07-21 22:03:43 -0400822// GetClientHelloLen creates a client SSL connection with a ticket of length
823// |ticket_len| and records the ClientHello. It returns the length of the
824// ClientHello, not including the record header, on success and zero on error.
825static size_t GetClientHelloLen(size_t ticket_len) {
826 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
827 ScopedSSL_SESSION session = CreateSessionWithTicket(ticket_len);
828 if (!ctx || !session) {
829 return 0;
830 }
831 ScopedSSL ssl(SSL_new(ctx.get()));
David Benjaminafc64de2016-07-19 17:12:41 +0200832 if (!ssl || !SSL_set_session(ssl.get(), session.get())) {
David Benjamin422fe082015-07-21 22:03:43 -0400833 return 0;
834 }
David Benjaminafc64de2016-07-19 17:12:41 +0200835 std::vector<uint8_t> client_hello;
836 if (!GetClientHello(ssl.get(), &client_hello) ||
837 client_hello.size() <= SSL3_RT_HEADER_LENGTH) {
David Benjamin422fe082015-07-21 22:03:43 -0400838 return 0;
839 }
David Benjaminafc64de2016-07-19 17:12:41 +0200840 return client_hello.size() - SSL3_RT_HEADER_LENGTH;
David Benjamin422fe082015-07-21 22:03:43 -0400841}
842
843struct PaddingTest {
844 size_t input_len, padded_len;
845};
846
847static const PaddingTest kPaddingTests[] = {
848 // ClientHellos of length below 0x100 do not require padding.
849 {0xfe, 0xfe},
850 {0xff, 0xff},
851 // ClientHellos of length 0x100 through 0x1fb are padded up to 0x200.
852 {0x100, 0x200},
853 {0x123, 0x200},
854 {0x1fb, 0x200},
855 // ClientHellos of length 0x1fc through 0x1ff get padded beyond 0x200. The
856 // padding extension takes a minimum of four bytes plus one required content
857 // byte. (To work around yet more server bugs, we avoid empty final
858 // extensions.)
859 {0x1fc, 0x201},
860 {0x1fd, 0x202},
861 {0x1fe, 0x203},
862 {0x1ff, 0x204},
863 // Finally, larger ClientHellos need no padding.
864 {0x200, 0x200},
865 {0x201, 0x201},
866};
867
868static bool TestPaddingExtension() {
869 // Sample a baseline length.
870 size_t base_len = GetClientHelloLen(1);
871 if (base_len == 0) {
872 return false;
873 }
874
875 for (const PaddingTest &test : kPaddingTests) {
876 if (base_len > test.input_len) {
877 fprintf(stderr, "Baseline ClientHello too long.\n");
878 return false;
879 }
880
881 size_t padded_len = GetClientHelloLen(1 + test.input_len - base_len);
882 if (padded_len != test.padded_len) {
883 fprintf(stderr, "%u-byte ClientHello padded to %u bytes, not %u.\n",
884 static_cast<unsigned>(test.input_len),
885 static_cast<unsigned>(padded_len),
886 static_cast<unsigned>(test.padded_len));
887 return false;
888 }
889 }
890 return true;
891}
892
David Benjamin1d128f32015-09-08 17:41:40 -0400893// Test that |SSL_get_client_CA_list| echoes back the configured parameter even
894// before configuring as a server.
895static bool TestClientCAList() {
896 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
897 if (!ctx) {
898 return false;
899 }
900 ScopedSSL ssl(SSL_new(ctx.get()));
901 if (!ssl) {
902 return false;
903 }
904
905 STACK_OF(X509_NAME) *stack = sk_X509_NAME_new_null();
906 if (stack == nullptr) {
907 return false;
908 }
909 // |SSL_set_client_CA_list| takes ownership.
910 SSL_set_client_CA_list(ssl.get(), stack);
911
912 return SSL_get_client_CA_list(ssl.get()) == stack;
913}
914
David Benjamin0f653952015-10-18 14:28:01 -0400915static void AppendSession(SSL_SESSION *session, void *arg) {
916 std::vector<SSL_SESSION*> *out =
917 reinterpret_cast<std::vector<SSL_SESSION*>*>(arg);
918 out->push_back(session);
919}
920
921// ExpectCache returns true if |ctx|'s session cache consists of |expected|, in
922// order.
923static bool ExpectCache(SSL_CTX *ctx,
924 const std::vector<SSL_SESSION*> &expected) {
925 // Check the linked list.
926 SSL_SESSION *ptr = ctx->session_cache_head;
927 for (SSL_SESSION *session : expected) {
928 if (ptr != session) {
929 return false;
930 }
931 // TODO(davidben): This is an absurd way to denote the end of the list.
932 if (ptr->next ==
933 reinterpret_cast<SSL_SESSION *>(&ctx->session_cache_tail)) {
934 ptr = nullptr;
935 } else {
936 ptr = ptr->next;
937 }
938 }
939 if (ptr != nullptr) {
940 return false;
941 }
942
943 // Check the hash table.
944 std::vector<SSL_SESSION*> actual, expected_copy;
945 lh_SSL_SESSION_doall_arg(SSL_CTX_sessions(ctx), AppendSession, &actual);
946 expected_copy = expected;
947
948 std::sort(actual.begin(), actual.end());
949 std::sort(expected_copy.begin(), expected_copy.end());
950
951 return actual == expected_copy;
952}
953
954static ScopedSSL_SESSION CreateTestSession(uint32_t number) {
955 ScopedSSL_SESSION ret(SSL_SESSION_new());
956 if (!ret) {
957 return nullptr;
958 }
959
960 ret->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
961 memset(ret->session_id, 0, ret->session_id_length);
962 memcpy(ret->session_id, &number, sizeof(number));
963 return ret;
964}
965
David Benjamin0f653952015-10-18 14:28:01 -0400966// Test that the internal session cache behaves as expected.
967static bool TestInternalSessionCache() {
968 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
969 if (!ctx) {
970 return false;
971 }
972
973 // Prepare 10 test sessions.
David Benjamin4f6acaf2015-11-21 03:00:50 -0500974 std::vector<ScopedSSL_SESSION> sessions;
David Benjamin0f653952015-10-18 14:28:01 -0400975 for (int i = 0; i < 10; i++) {
976 ScopedSSL_SESSION session = CreateTestSession(i);
977 if (!session) {
978 return false;
979 }
David Benjamin4f6acaf2015-11-21 03:00:50 -0500980 sessions.push_back(std::move(session));
David Benjamin0f653952015-10-18 14:28:01 -0400981 }
982
983 SSL_CTX_sess_set_cache_size(ctx.get(), 5);
984
985 // Insert all the test sessions.
David Benjamin4f6acaf2015-11-21 03:00:50 -0500986 for (const auto &session : sessions) {
987 if (!SSL_CTX_add_session(ctx.get(), session.get())) {
David Benjamin0f653952015-10-18 14:28:01 -0400988 return false;
989 }
990 }
991
992 // Only the last five should be in the list.
David Benjamin4f6acaf2015-11-21 03:00:50 -0500993 std::vector<SSL_SESSION*> expected = {
994 sessions[9].get(),
995 sessions[8].get(),
996 sessions[7].get(),
997 sessions[6].get(),
998 sessions[5].get(),
999 };
David Benjamin0f653952015-10-18 14:28:01 -04001000 if (!ExpectCache(ctx.get(), expected)) {
1001 return false;
1002 }
1003
1004 // Inserting an element already in the cache should fail.
David Benjamin4f6acaf2015-11-21 03:00:50 -05001005 if (SSL_CTX_add_session(ctx.get(), sessions[7].get()) ||
David Benjamin0f653952015-10-18 14:28:01 -04001006 !ExpectCache(ctx.get(), expected)) {
1007 return false;
1008 }
1009
1010 // Although collisions should be impossible (256-bit session IDs), the cache
1011 // must handle them gracefully.
1012 ScopedSSL_SESSION collision(CreateTestSession(7));
1013 if (!collision || !SSL_CTX_add_session(ctx.get(), collision.get())) {
1014 return false;
1015 }
David Benjamin4f6acaf2015-11-21 03:00:50 -05001016 expected = {
1017 collision.get(),
1018 sessions[9].get(),
1019 sessions[8].get(),
1020 sessions[6].get(),
1021 sessions[5].get(),
1022 };
David Benjamin0f653952015-10-18 14:28:01 -04001023 if (!ExpectCache(ctx.get(), expected)) {
1024 return false;
1025 }
1026
1027 // Removing sessions behaves correctly.
David Benjamin4f6acaf2015-11-21 03:00:50 -05001028 if (!SSL_CTX_remove_session(ctx.get(), sessions[6].get())) {
David Benjamin0f653952015-10-18 14:28:01 -04001029 return false;
1030 }
David Benjamin4f6acaf2015-11-21 03:00:50 -05001031 expected = {
1032 collision.get(),
1033 sessions[9].get(),
1034 sessions[8].get(),
1035 sessions[5].get(),
1036 };
David Benjamin0f653952015-10-18 14:28:01 -04001037 if (!ExpectCache(ctx.get(), expected)) {
1038 return false;
1039 }
1040
1041 // Removing sessions requires an exact match.
David Benjamin4f6acaf2015-11-21 03:00:50 -05001042 if (SSL_CTX_remove_session(ctx.get(), sessions[0].get()) ||
1043 SSL_CTX_remove_session(ctx.get(), sessions[7].get()) ||
David Benjamin0f653952015-10-18 14:28:01 -04001044 !ExpectCache(ctx.get(), expected)) {
1045 return false;
1046 }
1047
1048 return true;
1049}
1050
David Benjaminde942382016-02-11 12:02:01 -05001051static uint16_t EpochFromSequence(uint64_t seq) {
1052 return static_cast<uint16_t>(seq >> 48);
1053}
1054
1055static ScopedX509 GetTestCertificate() {
1056 static const char kCertPEM[] =
1057 "-----BEGIN CERTIFICATE-----\n"
1058 "MIICWDCCAcGgAwIBAgIJAPuwTC6rEJsMMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV\n"
1059 "BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX\n"
1060 "aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDIzMjA1MDQwWhcNMTcwNDIyMjA1MDQwWjBF\n"
1061 "MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50\n"
1062 "ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n"
1063 "gQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92kWdGMdAQhLci\n"
1064 "HnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiFKKAnHmUcrgfV\n"
1065 "W28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQABo1AwTjAdBgNV\n"
1066 "HQ4EFgQUi3XVrMsIvg4fZbf6Vr5sp3Xaha8wHwYDVR0jBBgwFoAUi3XVrMsIvg4f\n"
1067 "Zbf6Vr5sp3Xaha8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQA76Hht\n"
1068 "ldY9avcTGSwbwoiuIqv0jTL1fHFnzy3RHMLDh+Lpvolc5DSrSJHCP5WuK0eeJXhr\n"
1069 "T5oQpHL9z/cCDLAKCKRa4uV0fhEdOWBqyR9p8y5jJtye72t6CuFUV5iqcpF4BH4f\n"
1070 "j2VNHwsSrJwkD4QUGlUtH7vwnQmyCFxZMmWAJg==\n"
1071 "-----END CERTIFICATE-----\n";
Steven Valdezd8eea142016-02-24 14:00:22 -05001072 ScopedBIO bio(BIO_new_mem_buf(kCertPEM, strlen(kCertPEM)));
David Benjaminde942382016-02-11 12:02:01 -05001073 return ScopedX509(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
1074}
1075
1076static ScopedEVP_PKEY GetTestKey() {
1077 static const char kKeyPEM[] =
1078 "-----BEGIN RSA PRIVATE KEY-----\n"
1079 "MIICXgIBAAKBgQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92\n"
1080 "kWdGMdAQhLciHnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiF\n"
1081 "KKAnHmUcrgfVW28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQAB\n"
1082 "AoGBAIBy09Fd4DOq/Ijp8HeKuCMKTHqTW1xGHshLQ6jwVV2vWZIn9aIgmDsvkjCe\n"
1083 "i6ssZvnbjVcwzSoByhjN8ZCf/i15HECWDFFh6gt0P5z0MnChwzZmvatV/FXCT0j+\n"
1084 "WmGNB/gkehKjGXLLcjTb6dRYVJSCZhVuOLLcbWIV10gggJQBAkEA8S8sGe4ezyyZ\n"
1085 "m4e9r95g6s43kPqtj5rewTsUxt+2n4eVodD+ZUlCULWVNAFLkYRTBCASlSrm9Xhj\n"
1086 "QpmWAHJUkQJBAOVzQdFUaewLtdOJoPCtpYoY1zd22eae8TQEmpGOR11L6kbxLQsk\n"
1087 "aMly/DOnOaa82tqAGTdqDEZgSNmCeKKknmECQAvpnY8GUOVAubGR6c+W90iBuQLj\n"
1088 "LtFp/9ihd2w/PoDwrHZaoUYVcT4VSfJQog/k7kjE4MYXYWL8eEKg3WTWQNECQQDk\n"
1089 "104Wi91Umd1PzF0ijd2jXOERJU1wEKe6XLkYYNHWQAe5l4J4MWj9OdxFXAxIuuR/\n"
1090 "tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd\n"
1091 "moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==\n"
1092 "-----END RSA PRIVATE KEY-----\n";
Steven Valdezd8eea142016-02-24 14:00:22 -05001093 ScopedBIO bio(BIO_new_mem_buf(kKeyPEM, strlen(kKeyPEM)));
David Benjaminde942382016-02-11 12:02:01 -05001094 return ScopedEVP_PKEY(
1095 PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
1096}
1097
David Benjamin686bb192016-05-10 15:15:41 -04001098static bool ConnectClientAndServer(ScopedSSL *out_client, ScopedSSL *out_server,
David Benjamina20e5352016-08-02 19:09:41 -04001099 SSL_CTX *client_ctx, SSL_CTX *server_ctx,
1100 SSL_SESSION *session) {
David Benjamin686bb192016-05-10 15:15:41 -04001101 ScopedSSL client(SSL_new(client_ctx)), server(SSL_new(server_ctx));
David Benjaminde942382016-02-11 12:02:01 -05001102 if (!client || !server) {
1103 return false;
1104 }
1105 SSL_set_connect_state(client.get());
1106 SSL_set_accept_state(server.get());
1107
David Benjamina20e5352016-08-02 19:09:41 -04001108 SSL_set_session(client.get(), session);
1109
David Benjaminde942382016-02-11 12:02:01 -05001110 BIO *bio1, *bio2;
1111 if (!BIO_new_bio_pair(&bio1, 0, &bio2, 0)) {
1112 return false;
1113 }
1114 // SSL_set_bio takes ownership.
1115 SSL_set_bio(client.get(), bio1, bio1);
1116 SSL_set_bio(server.get(), bio2, bio2);
1117
1118 // Drive both their handshakes to completion.
1119 for (;;) {
1120 int client_ret = SSL_do_handshake(client.get());
1121 int client_err = SSL_get_error(client.get(), client_ret);
1122 if (client_err != SSL_ERROR_NONE &&
1123 client_err != SSL_ERROR_WANT_READ &&
1124 client_err != SSL_ERROR_WANT_WRITE) {
1125 fprintf(stderr, "Client error: %d\n", client_err);
1126 return false;
1127 }
1128
1129 int server_ret = SSL_do_handshake(server.get());
1130 int server_err = SSL_get_error(server.get(), server_ret);
1131 if (server_err != SSL_ERROR_NONE &&
1132 server_err != SSL_ERROR_WANT_READ &&
1133 server_err != SSL_ERROR_WANT_WRITE) {
1134 fprintf(stderr, "Server error: %d\n", server_err);
1135 return false;
1136 }
1137
1138 if (client_ret == 1 && server_ret == 1) {
1139 break;
1140 }
1141 }
1142
David Benjamin686bb192016-05-10 15:15:41 -04001143 *out_client = std::move(client);
1144 *out_server = std::move(server);
1145 return true;
1146}
1147
1148static bool TestSequenceNumber(bool dtls) {
1149 ScopedSSL_CTX client_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
1150 ScopedSSL_CTX server_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
1151 if (!client_ctx || !server_ctx) {
1152 return false;
1153 }
1154
1155 ScopedX509 cert = GetTestCertificate();
1156 ScopedEVP_PKEY key = GetTestKey();
1157 if (!cert || !key ||
1158 !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
1159 !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
1160 return false;
1161 }
1162
1163 ScopedSSL client, server;
1164 if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
David Benjamina20e5352016-08-02 19:09:41 -04001165 server_ctx.get(), nullptr /* no session */)) {
David Benjamin686bb192016-05-10 15:15:41 -04001166 return false;
1167 }
1168
David Benjaminde942382016-02-11 12:02:01 -05001169 uint64_t client_read_seq = SSL_get_read_sequence(client.get());
1170 uint64_t client_write_seq = SSL_get_write_sequence(client.get());
1171 uint64_t server_read_seq = SSL_get_read_sequence(server.get());
1172 uint64_t server_write_seq = SSL_get_write_sequence(server.get());
1173
1174 if (dtls) {
1175 // Both client and server must be at epoch 1.
1176 if (EpochFromSequence(client_read_seq) != 1 ||
1177 EpochFromSequence(client_write_seq) != 1 ||
1178 EpochFromSequence(server_read_seq) != 1 ||
1179 EpochFromSequence(server_write_seq) != 1) {
1180 fprintf(stderr, "Bad epochs.\n");
1181 return false;
1182 }
1183
1184 // The next record to be written should exceed the largest received.
1185 if (client_write_seq <= server_read_seq ||
1186 server_write_seq <= client_read_seq) {
1187 fprintf(stderr, "Inconsistent sequence numbers.\n");
1188 return false;
1189 }
1190 } else {
1191 // The next record to be written should equal the next to be received.
1192 if (client_write_seq != server_read_seq ||
1193 server_write_seq != client_write_seq) {
1194 fprintf(stderr, "Inconsistent sequence numbers.\n");
1195 return false;
1196 }
1197 }
1198
1199 // Send a record from client to server.
1200 uint8_t byte = 0;
1201 if (SSL_write(client.get(), &byte, 1) != 1 ||
1202 SSL_read(server.get(), &byte, 1) != 1) {
1203 fprintf(stderr, "Could not send byte.\n");
1204 return false;
1205 }
1206
1207 // The client write and server read sequence numbers should have incremented.
1208 if (client_write_seq + 1 != SSL_get_write_sequence(client.get()) ||
1209 server_read_seq + 1 != SSL_get_read_sequence(server.get())) {
1210 fprintf(stderr, "Sequence numbers did not increment.\n");\
1211 return false;
1212 }
1213
1214 return true;
1215}
1216
David Benjamin686bb192016-05-10 15:15:41 -04001217static bool TestOneSidedShutdown() {
1218 ScopedSSL_CTX client_ctx(SSL_CTX_new(TLS_method()));
1219 ScopedSSL_CTX server_ctx(SSL_CTX_new(TLS_method()));
1220 if (!client_ctx || !server_ctx) {
1221 return false;
1222 }
1223
1224 ScopedX509 cert = GetTestCertificate();
1225 ScopedEVP_PKEY key = GetTestKey();
1226 if (!cert || !key ||
1227 !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
1228 !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
1229 return false;
1230 }
1231
1232 ScopedSSL client, server;
1233 if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
David Benjamina20e5352016-08-02 19:09:41 -04001234 server_ctx.get(), nullptr /* no session */)) {
David Benjamin686bb192016-05-10 15:15:41 -04001235 return false;
1236 }
1237
1238 // Shut down half the connection. SSL_shutdown will return 0 to signal only
1239 // one side has shut down.
1240 if (SSL_shutdown(client.get()) != 0) {
1241 fprintf(stderr, "Could not shutdown.\n");
1242 return false;
1243 }
1244
1245 // Reading from the server should consume the EOF.
1246 uint8_t byte;
1247 if (SSL_read(server.get(), &byte, 1) != 0 ||
1248 SSL_get_error(server.get(), 0) != SSL_ERROR_ZERO_RETURN) {
1249 fprintf(stderr, "Connection was not shut down cleanly.\n");
1250 return false;
1251 }
1252
1253 // However, the server may continue to write data and then shut down the
1254 // connection.
1255 byte = 42;
1256 if (SSL_write(server.get(), &byte, 1) != 1 ||
1257 SSL_read(client.get(), &byte, 1) != 1 ||
1258 byte != 42) {
1259 fprintf(stderr, "Could not send byte.\n");
1260 return false;
1261 }
1262
1263 // The server may then shutdown the connection.
1264 if (SSL_shutdown(server.get()) != 1 ||
1265 SSL_shutdown(client.get()) != 1) {
1266 fprintf(stderr, "Could not complete shutdown.\n");
1267 return false;
1268 }
1269
1270 return true;
1271}
Steven Valdez87eab492016-06-27 16:34:59 -04001272static bool TestSessionDuplication() {
1273 ScopedSSL_CTX client_ctx(SSL_CTX_new(TLS_method()));
1274 ScopedSSL_CTX server_ctx(SSL_CTX_new(TLS_method()));
1275 if (!client_ctx || !server_ctx) {
1276 return false;
1277 }
1278
1279 ScopedX509 cert = GetTestCertificate();
1280 ScopedEVP_PKEY key = GetTestKey();
1281 if (!cert || !key ||
1282 !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
1283 !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
1284 return false;
1285 }
1286
1287 ScopedSSL client, server;
1288 if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
David Benjamina20e5352016-08-02 19:09:41 -04001289 server_ctx.get(), nullptr /* no session */)) {
Steven Valdez87eab492016-06-27 16:34:59 -04001290 return false;
1291 }
1292
1293 SSL_SESSION *session0 = SSL_get_session(client.get());
1294 ScopedSSL_SESSION session1(SSL_SESSION_dup(session0, 1));
1295 if (!session1) {
David Benjamin4501bd52016-08-01 13:39:41 -04001296 return false;
Steven Valdez87eab492016-06-27 16:34:59 -04001297 }
David Benjamin4501bd52016-08-01 13:39:41 -04001298
Steven Valdez87eab492016-06-27 16:34:59 -04001299 uint8_t *s0_bytes, *s1_bytes;
1300 size_t s0_len, s1_len;
1301
1302 if (!SSL_SESSION_to_bytes(session0, &s0_bytes, &s0_len)) {
1303 return false;
1304 }
1305 ScopedOpenSSLBytes free_s0(s0_bytes);
1306
1307 if (!SSL_SESSION_to_bytes(session1.get(), &s1_bytes, &s1_len)) {
1308 return false;
1309 }
1310 ScopedOpenSSLBytes free_s1(s1_bytes);
1311
1312 return s0_len == s1_len && memcmp(s0_bytes, s1_bytes, s0_len) == 0;
1313}
David Benjamin686bb192016-05-10 15:15:41 -04001314
David Benjamin5c0fb882016-06-14 14:03:51 -04001315static bool ExpectFDs(const SSL *ssl, int rfd, int wfd) {
1316 if (SSL_get_rfd(ssl) != rfd || SSL_get_wfd(ssl) != wfd) {
1317 fprintf(stderr, "Got fds %d and %d, wanted %d and %d.\n", SSL_get_rfd(ssl),
1318 SSL_get_wfd(ssl), rfd, wfd);
1319 return false;
1320 }
1321
1322 // The wrapper BIOs are always equal when fds are equal, even if set
1323 // individually.
1324 if (rfd == wfd && SSL_get_rbio(ssl) != SSL_get_wbio(ssl)) {
1325 fprintf(stderr, "rbio and wbio did not match.\n");
1326 return false;
1327 }
1328
1329 return true;
1330}
1331
1332static bool TestSetFD() {
1333 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
1334 if (!ctx) {
1335 return false;
1336 }
1337
1338 // Test setting different read and write FDs.
1339 ScopedSSL ssl(SSL_new(ctx.get()));
1340 if (!ssl ||
1341 !SSL_set_rfd(ssl.get(), 1) ||
1342 !SSL_set_wfd(ssl.get(), 2) ||
1343 !ExpectFDs(ssl.get(), 1, 2)) {
1344 return false;
1345 }
1346
1347 // Test setting the same FD.
1348 ssl.reset(SSL_new(ctx.get()));
1349 if (!ssl ||
1350 !SSL_set_fd(ssl.get(), 1) ||
1351 !ExpectFDs(ssl.get(), 1, 1)) {
1352 return false;
1353 }
1354
1355 // Test setting the same FD one side at a time.
1356 ssl.reset(SSL_new(ctx.get()));
1357 if (!ssl ||
1358 !SSL_set_rfd(ssl.get(), 1) ||
1359 !SSL_set_wfd(ssl.get(), 1) ||
1360 !ExpectFDs(ssl.get(), 1, 1)) {
1361 return false;
1362 }
1363
1364 // Test setting the same FD in the other order.
1365 ssl.reset(SSL_new(ctx.get()));
1366 if (!ssl ||
1367 !SSL_set_wfd(ssl.get(), 1) ||
1368 !SSL_set_rfd(ssl.get(), 1) ||
1369 !ExpectFDs(ssl.get(), 1, 1)) {
1370 return false;
1371 }
1372
David Benjamin5c0fb882016-06-14 14:03:51 -04001373 // Test changing the read FD partway through.
1374 ssl.reset(SSL_new(ctx.get()));
1375 if (!ssl ||
1376 !SSL_set_fd(ssl.get(), 1) ||
1377 !SSL_set_rfd(ssl.get(), 2) ||
1378 !ExpectFDs(ssl.get(), 2, 1)) {
1379 return false;
1380 }
David Benjamin5c0fb882016-06-14 14:03:51 -04001381
1382 // Test changing the write FD partway through.
1383 ssl.reset(SSL_new(ctx.get()));
1384 if (!ssl ||
1385 !SSL_set_fd(ssl.get(), 1) ||
1386 !SSL_set_wfd(ssl.get(), 2) ||
1387 !ExpectFDs(ssl.get(), 1, 2)) {
1388 return false;
1389 }
1390
1391 // Test a no-op change to the read FD partway through.
1392 ssl.reset(SSL_new(ctx.get()));
1393 if (!ssl ||
1394 !SSL_set_fd(ssl.get(), 1) ||
1395 !SSL_set_rfd(ssl.get(), 1) ||
1396 !ExpectFDs(ssl.get(), 1, 1)) {
1397 return false;
1398 }
1399
1400 // Test a no-op change to the write FD partway through.
1401 ssl.reset(SSL_new(ctx.get()));
1402 if (!ssl ||
1403 !SSL_set_fd(ssl.get(), 1) ||
1404 !SSL_set_wfd(ssl.get(), 1) ||
1405 !ExpectFDs(ssl.get(), 1, 1)) {
1406 return false;
1407 }
1408
1409 // ASan builds will implicitly test that the internal |BIO| reference-counting
1410 // is correct.
1411
1412 return true;
1413}
1414
David Benjamin4501bd52016-08-01 13:39:41 -04001415static bool TestSetBIO() {
1416 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
1417 if (!ctx) {
1418 return false;
1419 }
1420
1421 ScopedSSL ssl(SSL_new(ctx.get()));
1422 ScopedBIO bio1(BIO_new(BIO_s_mem())), bio2(BIO_new(BIO_s_mem())),
1423 bio3(BIO_new(BIO_s_mem()));
1424 if (!ssl || !bio1 || !bio2 || !bio3) {
1425 return false;
1426 }
1427
1428 // SSL_set_bio takes one reference when the parameters are the same.
1429 BIO_up_ref(bio1.get());
1430 SSL_set_bio(ssl.get(), bio1.get(), bio1.get());
1431
1432 // Repeating the call does nothing.
1433 SSL_set_bio(ssl.get(), bio1.get(), bio1.get());
1434
1435 // It takes one reference each when the parameters are different.
1436 BIO_up_ref(bio2.get());
1437 BIO_up_ref(bio3.get());
1438 SSL_set_bio(ssl.get(), bio2.get(), bio3.get());
1439
1440 // Repeating the call does nothing.
1441 SSL_set_bio(ssl.get(), bio2.get(), bio3.get());
1442
1443 // It takes one reference when changing only wbio.
1444 BIO_up_ref(bio1.get());
1445 SSL_set_bio(ssl.get(), bio2.get(), bio1.get());
1446
1447 // It takes one reference when changing only rbio and the two are different.
1448 BIO_up_ref(bio3.get());
1449 SSL_set_bio(ssl.get(), bio3.get(), bio1.get());
1450
1451 // If setting wbio to rbio, it takes no additional references.
1452 SSL_set_bio(ssl.get(), bio3.get(), bio3.get());
1453
1454 // From there, wbio may be switched to something else.
1455 BIO_up_ref(bio1.get());
1456 SSL_set_bio(ssl.get(), bio3.get(), bio1.get());
1457
1458 // If setting rbio to wbio, it takes no additional references.
1459 SSL_set_bio(ssl.get(), bio1.get(), bio1.get());
1460
1461 // From there, rbio may be switched to something else, but, for historical
1462 // reasons, it takes a reference to both parameters.
1463 BIO_up_ref(bio1.get());
1464 BIO_up_ref(bio2.get());
1465 SSL_set_bio(ssl.get(), bio2.get(), bio1.get());
1466
1467 // ASAN builds will implicitly test that the internal |BIO| reference-counting
1468 // is correct.
1469 return true;
1470}
1471
David Benjamin25490f22016-07-14 00:22:54 -04001472static uint16_t kVersions[] = {
1473 SSL3_VERSION, TLS1_VERSION, TLS1_1_VERSION, TLS1_2_VERSION, TLS1_3_VERSION,
1474};
1475
1476static int VerifySucceed(X509_STORE_CTX *store_ctx, void *arg) { return 1; }
1477
David Benjaminadd5e522016-07-14 00:33:24 -04001478static bool TestGetPeerCertificate() {
1479 ScopedX509 cert = GetTestCertificate();
1480 ScopedEVP_PKEY key = GetTestKey();
1481 if (!cert || !key) {
1482 return false;
1483 }
1484
1485 for (uint16_t version : kVersions) {
1486 // Configure both client and server to accept any certificate.
1487 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
1488 if (!ctx ||
1489 !SSL_CTX_use_certificate(ctx.get(), cert.get()) ||
1490 !SSL_CTX_use_PrivateKey(ctx.get(), key.get())) {
1491 return false;
1492 }
1493 SSL_CTX_set_min_version(ctx.get(), version);
1494 SSL_CTX_set_max_version(ctx.get(), version);
1495 SSL_CTX_set_verify(
1496 ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
1497 SSL_CTX_set_cert_verify_callback(ctx.get(), VerifySucceed, NULL);
1498
1499 ScopedSSL client, server;
David Benjamina20e5352016-08-02 19:09:41 -04001500 if (!ConnectClientAndServer(&client, &server, ctx.get(), ctx.get(),
1501 nullptr /* no session */)) {
David Benjaminadd5e522016-07-14 00:33:24 -04001502 return false;
1503 }
1504
1505 // Client and server should both see the leaf certificate.
1506 ScopedX509 peer(SSL_get_peer_certificate(server.get()));
1507 if (!peer || X509_cmp(cert.get(), peer.get()) != 0) {
1508 fprintf(stderr, "%x: Server peer certificate did not match.\n", version);
1509 return false;
1510 }
1511
1512 peer.reset(SSL_get_peer_certificate(client.get()));
1513 if (!peer || X509_cmp(cert.get(), peer.get()) != 0) {
1514 fprintf(stderr, "%x: Client peer certificate did not match.\n", version);
1515 return false;
1516 }
1517
1518 // However, for historical reasons, the chain includes the leaf on the
1519 // client, but does not on the server.
1520 if (sk_X509_num(SSL_get_peer_cert_chain(client.get())) != 1) {
1521 fprintf(stderr, "%x: Client peer chain was incorrect.\n", version);
1522 return false;
1523 }
1524
1525 if (sk_X509_num(SSL_get_peer_cert_chain(server.get())) != 0) {
1526 fprintf(stderr, "%x: Server peer chain was incorrect.\n", version);
1527 return false;
1528 }
1529 }
1530
1531 return true;
1532}
1533
David Benjamin25490f22016-07-14 00:22:54 -04001534static bool TestRetainOnlySHA256OfCerts() {
1535 ScopedX509 cert = GetTestCertificate();
1536 ScopedEVP_PKEY key = GetTestKey();
1537 if (!cert || !key) {
1538 return false;
1539 }
1540
1541 uint8_t *cert_der = NULL;
1542 int cert_der_len = i2d_X509(cert.get(), &cert_der);
1543 if (cert_der_len < 0) {
1544 return false;
1545 }
1546 ScopedOpenSSLBytes free_cert_der(cert_der);
1547
1548 uint8_t cert_sha256[SHA256_DIGEST_LENGTH];
1549 SHA256(cert_der, cert_der_len, cert_sha256);
1550
1551 for (uint16_t version : kVersions) {
1552 // Configure both client and server to accept any certificate, but the
1553 // server must retain only the SHA-256 of the peer.
1554 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
1555 if (!ctx ||
1556 !SSL_CTX_use_certificate(ctx.get(), cert.get()) ||
1557 !SSL_CTX_use_PrivateKey(ctx.get(), key.get())) {
1558 return false;
1559 }
1560 SSL_CTX_set_min_version(ctx.get(), version);
1561 SSL_CTX_set_max_version(ctx.get(), version);
1562 SSL_CTX_set_verify(
1563 ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
1564 SSL_CTX_set_cert_verify_callback(ctx.get(), VerifySucceed, NULL);
1565 SSL_CTX_set_retain_only_sha256_of_client_certs(ctx.get(), 1);
1566
1567 ScopedSSL client, server;
David Benjamina20e5352016-08-02 19:09:41 -04001568 if (!ConnectClientAndServer(&client, &server, ctx.get(), ctx.get(),
1569 nullptr /* no session */)) {
David Benjamin25490f22016-07-14 00:22:54 -04001570 return false;
1571 }
1572
1573 // The peer certificate has been dropped.
1574 ScopedX509 peer(SSL_get_peer_certificate(server.get()));
1575 if (peer) {
1576 fprintf(stderr, "%x: Peer certificate was retained.\n", version);
1577 return false;
1578 }
1579
1580 SSL_SESSION *session = SSL_get_session(server.get());
1581 if (!session->peer_sha256_valid) {
1582 fprintf(stderr, "%x: peer_sha256_valid was not set.\n", version);
1583 return false;
1584 }
1585
1586 if (memcmp(cert_sha256, session->peer_sha256, SHA256_DIGEST_LENGTH) != 0) {
1587 fprintf(stderr, "%x: peer_sha256 did not match.\n", version);
1588 return false;
1589 }
1590 }
1591
1592 return true;
1593}
1594
David Benjaminafc64de2016-07-19 17:12:41 +02001595static bool ClientHelloMatches(uint16_t version, const uint8_t *expected,
1596 size_t expected_len) {
1597 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
1598 if (!ctx) {
1599 return false;
1600 }
1601 SSL_CTX_set_max_version(ctx.get(), version);
1602 // Our default cipher list varies by CPU capabilities, so manually place the
1603 // ChaCha20 ciphers in front.
1604 if (!SSL_CTX_set_cipher_list(ctx.get(), "CHACHA20:ALL")) {
1605 return false;
1606 }
1607 ScopedSSL ssl(SSL_new(ctx.get()));
1608 if (!ssl) {
1609 return false;
1610 }
1611 std::vector<uint8_t> client_hello;
1612 if (!GetClientHello(ssl.get(), &client_hello)) {
1613 return false;
1614 }
1615
1616 // Zero the client_random.
1617 constexpr size_t kRandomOffset = 1 + 2 + 2 + // record header
1618 1 + 3 + // handshake message header
1619 2; // client_version
1620 if (client_hello.size() < kRandomOffset + SSL3_RANDOM_SIZE) {
1621 fprintf(stderr, "ClientHello for version %04x too short.\n", version);
1622 return false;
1623 }
1624 memset(client_hello.data() + kRandomOffset, 0, SSL3_RANDOM_SIZE);
1625
1626 if (client_hello.size() != expected_len ||
1627 memcmp(client_hello.data(), expected, expected_len) != 0) {
1628 fprintf(stderr, "ClientHello for version %04x did not match:\n", version);
1629 fprintf(stderr, "Got:\n\t");
1630 for (size_t i = 0; i < client_hello.size(); i++) {
1631 fprintf(stderr, "0x%02x, ", client_hello[i]);
1632 }
1633 fprintf(stderr, "\nWanted:\n\t");
1634 for (size_t i = 0; i < expected_len; i++) {
1635 fprintf(stderr, "0x%02x, ", expected[i]);
1636 }
1637 fprintf(stderr, "\n");
1638 return false;
1639 }
1640
1641 return true;
1642}
1643
1644// Tests that our ClientHellos do not change unexpectedly.
1645static bool TestClientHello() {
1646 static const uint8_t kSSL3ClientHello[] = {
1647 0x16, 0x03, 0x00, 0x00, 0x47, 0x01, 0x00, 0x00, 0x43, 0x03, 0x00,
1648 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1649 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1650 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1651 0x00, 0x1c, 0xc0, 0x09, 0xc0, 0x13, 0x00, 0x33, 0xc0, 0x0a, 0xc0,
1652 0x14, 0x00, 0x39, 0xc0, 0x07, 0xc0, 0x11, 0x00, 0x2f, 0x00, 0x35,
1653 0x00, 0x0a, 0x00, 0x05, 0x00, 0x04, 0x00, 0xff, 0x01, 0x00,
1654 };
1655 if (!ClientHelloMatches(SSL3_VERSION, kSSL3ClientHello,
1656 sizeof(kSSL3ClientHello))) {
1657 return false;
1658 }
1659
1660 static const uint8_t kTLS1ClientHello[] = {
1661 0x16, 0x03, 0x01, 0x00, 0x66, 0x01, 0x00, 0x00, 0x62, 0x03, 0x01, 0x00,
1662 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1663 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1664 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xc0, 0x09,
1665 0xc0, 0x13, 0x00, 0x33, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x39, 0xc0, 0x07,
1666 0xc0, 0x11, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x04,
1667 0x01, 0x00, 0x00, 0x1f, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x17, 0x00,
1668 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
1669 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
1670 };
1671 if (!ClientHelloMatches(TLS1_VERSION, kTLS1ClientHello,
1672 sizeof(kTLS1ClientHello))) {
1673 return false;
1674 }
1675
1676 static const uint8_t kTLS11ClientHello[] = {
1677 0x16, 0x03, 0x01, 0x00, 0x66, 0x01, 0x00, 0x00, 0x62, 0x03, 0x02, 0x00,
1678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1679 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1680 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xc0, 0x09,
1681 0xc0, 0x13, 0x00, 0x33, 0xc0, 0x0a, 0xc0, 0x14, 0x00, 0x39, 0xc0, 0x07,
1682 0xc0, 0x11, 0x00, 0x2f, 0x00, 0x35, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x04,
1683 0x01, 0x00, 0x00, 0x1f, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x17, 0x00,
1684 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
1685 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
1686 };
1687 if (!ClientHelloMatches(TLS1_1_VERSION, kTLS11ClientHello,
1688 sizeof(kTLS11ClientHello))) {
1689 return false;
1690 }
1691
1692 static const uint8_t kTLS12ClientHello[] = {
1693 0x16, 0x03, 0x01, 0x00, 0xa4, 0x01, 0x00, 0x00, 0xa0, 0x03, 0x03, 0x00,
1694 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1695 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xcc, 0xa9,
1697 0xcc, 0xa8, 0xcc, 0x14, 0xcc, 0x13, 0xc0, 0x2b, 0xc0, 0x2f, 0x00, 0x9e,
1698 0xc0, 0x2c, 0xc0, 0x30, 0x00, 0x9f, 0xc0, 0x09, 0xc0, 0x23, 0xc0, 0x13,
1699 0xc0, 0x27, 0x00, 0x33, 0x00, 0x67, 0xc0, 0x0a, 0xc0, 0x24, 0xc0, 0x14,
1700 0xc0, 0x28, 0x00, 0x39, 0x00, 0x6b, 0xc0, 0x07, 0xc0, 0x11, 0x00, 0x9c,
1701 0x00, 0x9d, 0x00, 0x2f, 0x00, 0x3c, 0x00, 0x35, 0x00, 0x3d, 0x00, 0x0a,
1702 0x00, 0x05, 0x00, 0x04, 0x01, 0x00, 0x00, 0x35, 0xff, 0x01, 0x00, 0x01,
1703 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00,
1704 0x12, 0x00, 0x10, 0x06, 0x01, 0x06, 0x03, 0x05, 0x01, 0x05, 0x03, 0x04,
1705 0x01, 0x04, 0x03, 0x02, 0x01, 0x02, 0x03, 0x00, 0x0b, 0x00, 0x02, 0x01,
1706 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00,
1707 0x18,
1708 };
1709 if (!ClientHelloMatches(TLS1_2_VERSION, kTLS12ClientHello,
1710 sizeof(kTLS12ClientHello))) {
1711 return false;
1712 }
1713
1714 // TODO(davidben): Add a change detector for TLS 1.3 once the spec and our
1715 // implementation has settled enough that it won't change.
1716
1717 return true;
1718}
1719
David Benjamina20e5352016-08-02 19:09:41 -04001720static ScopedSSL_SESSION g_last_session;
1721
1722static int SaveLastSession(SSL *ssl, SSL_SESSION *session) {
1723 // Save the most recent session.
1724 g_last_session.reset(session);
1725 return 1;
1726}
1727
1728static ScopedSSL_SESSION CreateClientSession(SSL_CTX *client_ctx,
1729 SSL_CTX *server_ctx) {
1730 g_last_session = nullptr;
1731 SSL_CTX_sess_set_new_cb(client_ctx, SaveLastSession);
1732
1733 // Connect client and server to get a session.
1734 ScopedSSL client, server;
1735 if (!ConnectClientAndServer(&client, &server, client_ctx, server_ctx,
1736 nullptr /* no session */)) {
1737 fprintf(stderr, "Failed to connect client and server.\n");
1738 return nullptr;
1739 }
1740
1741 // Run the read loop to account for post-handshake tickets in TLS 1.3.
1742 SSL_read(client.get(), nullptr, 0);
1743
1744 SSL_CTX_sess_set_new_cb(client_ctx, nullptr);
1745
1746 if (!g_last_session) {
1747 fprintf(stderr, "Client did not receive a session.\n");
1748 return nullptr;
1749 }
1750 return std::move(g_last_session);
1751}
1752
1753static bool ExpectSessionReused(SSL_CTX *client_ctx, SSL_CTX *server_ctx,
1754 SSL_SESSION *session,
1755 bool reused) {
1756 ScopedSSL client, server;
1757 if (!ConnectClientAndServer(&client, &server, client_ctx,
1758 server_ctx, session)) {
1759 fprintf(stderr, "Failed to connect client and server.\n");
1760 return false;
1761 }
1762
1763 if (SSL_session_reused(client.get()) != SSL_session_reused(server.get())) {
1764 fprintf(stderr, "Client and server were inconsistent.\n");
1765 return false;
1766 }
1767
1768 bool was_reused = !!SSL_session_reused(client.get());
1769 if (was_reused != reused) {
1770 fprintf(stderr, "Session was%s reused, but we expected the opposite.\n",
1771 was_reused ? "" : " not");
1772 return false;
1773 }
1774
1775 return true;
1776}
1777
1778static bool TestSessionIDContext() {
1779 ScopedX509 cert = GetTestCertificate();
1780 ScopedEVP_PKEY key = GetTestKey();
1781 if (!cert || !key) {
1782 return false;
1783 }
1784
1785 static const uint8_t kContext1[] = {1};
1786 static const uint8_t kContext2[] = {2};
1787
1788 for (uint16_t version : kVersions) {
1789 // TODO(davidben): Enable this when TLS 1.3 resumption is implemented.
1790 if (version == TLS1_3_VERSION) {
1791 continue;
1792 }
1793
1794 ScopedSSL_CTX server_ctx(SSL_CTX_new(TLS_method()));
1795 ScopedSSL_CTX client_ctx(SSL_CTX_new(TLS_method()));
1796 if (!server_ctx || !client_ctx ||
1797 !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
1798 !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()) ||
1799 !SSL_CTX_set_session_id_context(server_ctx.get(), kContext1,
1800 sizeof(kContext1))) {
1801 return false;
1802 }
1803
1804 SSL_CTX_set_min_version(client_ctx.get(), version);
1805 SSL_CTX_set_max_version(client_ctx.get(), version);
1806 SSL_CTX_set_session_cache_mode(client_ctx.get(), SSL_SESS_CACHE_BOTH);
1807
1808 SSL_CTX_set_min_version(server_ctx.get(), version);
1809 SSL_CTX_set_max_version(server_ctx.get(), version);
1810 SSL_CTX_set_session_cache_mode(server_ctx.get(), SSL_SESS_CACHE_BOTH);
1811
1812 ScopedSSL_SESSION session =
1813 CreateClientSession(client_ctx.get(), server_ctx.get());
1814 if (!session) {
1815 fprintf(stderr, "Error getting session (version = %04x).\n", version);
1816 return false;
1817 }
1818
1819 if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(), session.get(),
1820 true /* expect session reused */)) {
1821 fprintf(stderr, "Error resuming session (version = %04x).\n", version);
1822 return false;
1823 }
1824
1825 // Change the session ID context.
1826 if (!SSL_CTX_set_session_id_context(server_ctx.get(), kContext2,
1827 sizeof(kContext2))) {
1828 return false;
1829 }
1830
1831 if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(), session.get(),
1832 false /* expect session not reused */)) {
1833 fprintf(stderr,
1834 "Error connection with different context (version = %04x).\n",
1835 version);
1836 return false;
1837 }
1838 }
1839
1840 return true;
1841}
1842
David Benjamin1d128f32015-09-08 17:41:40 -04001843int main() {
David Benjamin7a1eefd2015-10-17 23:39:22 -04001844 CRYPTO_library_init();
David Benjaminbb0a17c2014-09-20 15:35:39 -04001845
Adam Langley10f97f32016-07-12 08:09:33 -07001846 if (!TestCipherRules() ||
1847 !TestSSL_SESSIONEncoding(kOpenSSLSession) ||
1848 !TestSSL_SESSIONEncoding(kCustomSession) ||
1849 !TestSSL_SESSIONEncoding(kBoringSSLSession) ||
1850 !TestBadSSL_SESSIONEncoding(kBadSessionExtraField) ||
1851 !TestBadSSL_SESSIONEncoding(kBadSessionVersion) ||
1852 !TestBadSSL_SESSIONEncoding(kBadSessionTrailingData) ||
David Benjamin10e664b2016-06-20 22:20:47 -04001853 // TODO(svaldez): Update this when TLS 1.3 is enabled by default.
Adam Langley10f97f32016-07-12 08:09:33 -07001854 !TestDefaultVersion(SSL3_VERSION, TLS1_2_VERSION, &TLS_method) ||
1855 !TestDefaultVersion(SSL3_VERSION, SSL3_VERSION, &SSLv3_method) ||
1856 !TestDefaultVersion(TLS1_VERSION, TLS1_VERSION, &TLSv1_method) ||
1857 !TestDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION, &TLSv1_1_method) ||
1858 !TestDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION, &TLSv1_2_method) ||
1859 !TestDefaultVersion(TLS1_1_VERSION, TLS1_2_VERSION, &DTLS_method) ||
1860 !TestDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION, &DTLSv1_method) ||
1861 !TestDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION, &DTLSv1_2_method) ||
1862 !TestCipherGetRFCName() ||
1863 !TestPaddingExtension() ||
1864 !TestClientCAList() ||
1865 !TestInternalSessionCache() ||
1866 !TestSequenceNumber(false /* TLS */) ||
1867 !TestSequenceNumber(true /* DTLS */) ||
1868 !TestOneSidedShutdown() ||
Steven Valdez87eab492016-06-27 16:34:59 -04001869 !TestSessionDuplication() ||
David Benjamin25490f22016-07-14 00:22:54 -04001870 !TestSetFD() ||
David Benjamin4501bd52016-08-01 13:39:41 -04001871 !TestSetBIO() ||
David Benjaminadd5e522016-07-14 00:33:24 -04001872 !TestGetPeerCertificate() ||
David Benjaminafc64de2016-07-19 17:12:41 +02001873 !TestRetainOnlySHA256OfCerts() ||
David Benjamina20e5352016-08-02 19:09:41 -04001874 !TestClientHello() ||
1875 !TestSessionIDContext()) {
Brian Smith83a82982015-04-09 16:21:10 -10001876 ERR_print_errors_fp(stderr);
David Benjaminbb0a17c2014-09-20 15:35:39 -04001877 return 1;
1878 }
1879
David Benjamin2e521212014-07-16 14:37:51 -04001880 printf("PASS\n");
1881 return 0;
1882}