blob: 647d6c87bd5e79ff14396f475f1240314a2d37f5 [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
Adam Langleyd2b5af52016-07-12 08:03:59 -070033#include "test/scoped_types.h"
Sigbjorn Vik2b23d242015-06-29 15:07:26 +020034#include "../crypto/test/test_util.h"
35
David Benjamin1d77e562015-03-22 17:22:08 -040036
37struct ExpectedCipher {
38 unsigned long id;
David Benjaminbb0a17c2014-09-20 15:35:39 -040039 int in_group_flag;
David Benjamin1d77e562015-03-22 17:22:08 -040040};
David Benjaminbb0a17c2014-09-20 15:35:39 -040041
David Benjamin1d77e562015-03-22 17:22:08 -040042struct CipherTest {
43 // The rule string to apply.
David Benjaminbb0a17c2014-09-20 15:35:39 -040044 const char *rule;
David Benjaminfb974e62015-12-16 19:34:22 -050045 // The list of expected ciphers, in order.
46 std::vector<ExpectedCipher> expected;
David Benjamin1d77e562015-03-22 17:22:08 -040047};
David Benjaminbb0a17c2014-09-20 15:35:39 -040048
David Benjaminfb974e62015-12-16 19:34:22 -050049static const CipherTest kCipherTests[] = {
50 // Selecting individual ciphers should work.
51 {
52 "ECDHE-ECDSA-CHACHA20-POLY1305:"
53 "ECDHE-RSA-CHACHA20-POLY1305:"
54 "ECDHE-ECDSA-AES128-GCM-SHA256:"
55 "ECDHE-RSA-AES128-GCM-SHA256",
56 {
57 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
58 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
59 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
60 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
61 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
62 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
63 },
64 },
65 // + reorders selected ciphers to the end, keeping their relative order.
66 {
67 "ECDHE-ECDSA-CHACHA20-POLY1305:"
68 "ECDHE-RSA-CHACHA20-POLY1305:"
69 "ECDHE-ECDSA-AES128-GCM-SHA256:"
70 "ECDHE-RSA-AES128-GCM-SHA256:"
71 "+aRSA",
72 {
73 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
74 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
75 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
76 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
77 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
78 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
79 },
80 },
81 // ! banishes ciphers from future selections.
82 {
83 "!aRSA:"
84 "ECDHE-ECDSA-CHACHA20-POLY1305:"
85 "ECDHE-RSA-CHACHA20-POLY1305:"
86 "ECDHE-ECDSA-AES128-GCM-SHA256:"
87 "ECDHE-RSA-AES128-GCM-SHA256",
88 {
89 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
90 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
91 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
92 },
93 },
94 // Multiple masks can be ANDed in a single rule.
95 {
96 "kRSA+AESGCM+AES128",
97 {
98 {TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0},
99 },
100 },
101 // - removes selected ciphers, but preserves their order for future
102 // selections. Select AES_128_GCM, but order the key exchanges RSA, DHE_RSA,
103 // ECDHE_RSA.
104 {
105 "ALL:-kECDHE:-kDHE:-kRSA:-ALL:"
106 "AESGCM+AES128+aRSA",
107 {
108 {TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0},
109 {TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, 0},
110 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
111 },
112 },
113 // Unknown selectors are no-ops.
114 {
115 "ECDHE-ECDSA-CHACHA20-POLY1305:"
116 "ECDHE-RSA-CHACHA20-POLY1305:"
117 "ECDHE-ECDSA-AES128-GCM-SHA256:"
118 "ECDHE-RSA-AES128-GCM-SHA256:"
119 "BOGUS1:-BOGUS2:+BOGUS3:!BOGUS4",
120 {
121 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
122 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
123 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
124 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
125 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
126 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
127 },
128 },
129 // Square brackets specify equi-preference groups.
130 {
131 "[ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]:"
132 "[ECDHE-RSA-CHACHA20-POLY1305]:"
133 "ECDHE-RSA-AES128-GCM-SHA256",
134 {
135 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 1},
136 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 1},
137 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
138 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 1},
139 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
140 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
141 },
142 },
143 // @STRENGTH performs a stable strength-sort of the selected ciphers and
144 // only the selected ciphers.
145 {
146 // To simplify things, banish all but {ECDHE_RSA,RSA} x
147 // {CHACHA20,AES_256_CBC,AES_128_CBC,RC4} x SHA1.
148 "!kEDH:!AESGCM:!3DES:!SHA256:!MD5:!SHA384:"
149 // Order some ciphers backwards by strength.
150 "ALL:-CHACHA20:-AES256:-AES128:-RC4:-ALL:"
151 // Select ECDHE ones and sort them by strength. Ties should resolve
152 // based on the order above.
153 "kECDHE:@STRENGTH:-ALL:"
154 // Now bring back everything uses RSA. ECDHE_RSA should be first, sorted
155 // by strength. Then RSA, backwards by strength.
156 "aRSA",
157 {
158 {TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, 0},
159 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
160 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
161 {TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA, 0},
162 {TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, 0},
163 {SSL3_CK_RSA_RC4_128_SHA, 0},
164 {TLS1_CK_RSA_WITH_AES_128_SHA, 0},
165 {TLS1_CK_RSA_WITH_AES_256_SHA, 0},
166 },
167 },
168 // Exact ciphers may not be used in multi-part rules; they are treated
169 // as unknown aliases.
170 {
171 "ECDHE-ECDSA-AES128-GCM-SHA256:"
172 "ECDHE-RSA-AES128-GCM-SHA256:"
173 "!ECDHE-RSA-AES128-GCM-SHA256+RSA:"
174 "!ECDSA+ECDHE-ECDSA-AES128-GCM-SHA256",
175 {
176 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
177 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
178 },
179 },
180 // SSLv3 matches everything that existed before TLS 1.2.
181 {
182 "AES128-SHA:AES128-SHA256:!SSLv3",
183 {
184 {TLS1_CK_RSA_WITH_AES_128_SHA256, 0},
185 },
186 },
187 // TLSv1.2 matches everything added in TLS 1.2.
188 {
189 "AES128-SHA:AES128-SHA256:!TLSv1.2",
190 {
191 {TLS1_CK_RSA_WITH_AES_128_SHA, 0},
192 },
193 },
194 // The two directives have no intersection.
195 {
196 "AES128-SHA:AES128-SHA256:!TLSv1.2+SSLv3",
197 {
198 {TLS1_CK_RSA_WITH_AES_128_SHA, 0},
199 {TLS1_CK_RSA_WITH_AES_128_SHA256, 0},
200 },
201 },
202 // The shared name of the CHACHA20_POLY1305 variants behaves like a cipher
203 // name and not an alias. It may not be used in a multipart rule. (That the
204 // shared name works is covered by the standard tests.)
205 {
206 "ECDHE-ECDSA-CHACHA20-POLY1305:"
207 "ECDHE-RSA-CHACHA20-POLY1305:"
208 "!ECDHE-RSA-CHACHA20-POLY1305+RSA:"
209 "!ECDSA+ECDHE-ECDSA-CHACHA20-POLY1305",
210 {
211 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
212 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
213 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
214 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
215 },
216 },
David Benjaminbb0a17c2014-09-20 15:35:39 -0400217};
218
219static const char *kBadRules[] = {
David Benjamin1d77e562015-03-22 17:22:08 -0400220 // Invalid brackets.
David Benjaminbb0a17c2014-09-20 15:35:39 -0400221 "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256",
222 "RSA]",
223 "[[RSA]]",
David Benjamin1d77e562015-03-22 17:22:08 -0400224 // Operators inside brackets.
David Benjaminbb0a17c2014-09-20 15:35:39 -0400225 "[+RSA]",
David Benjamin1d77e562015-03-22 17:22:08 -0400226 // Unknown directive.
David Benjaminbb0a17c2014-09-20 15:35:39 -0400227 "@BOGUS",
David Benjamin1d77e562015-03-22 17:22:08 -0400228 // Empty cipher lists error at SSL_CTX_set_cipher_list.
David Benjaminbb0a17c2014-09-20 15:35:39 -0400229 "",
230 "BOGUS",
David Benjamin32fbdf22015-04-07 01:14:06 -0400231 // COMPLEMENTOFDEFAULT is empty.
232 "COMPLEMENTOFDEFAULT",
David Benjamin1d77e562015-03-22 17:22:08 -0400233 // Invalid command.
David Benjaminbb0a17c2014-09-20 15:35:39 -0400234 "?BAR",
David Benjamin1d77e562015-03-22 17:22:08 -0400235 // Special operators are not allowed if groups are used.
David Benjamin37d92462014-09-20 17:54:24 -0400236 "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:+FOO",
237 "[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]:@STRENGTH",
David Benjaminbb0a17c2014-09-20 15:35:39 -0400240};
241
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700242static const char *kMustNotIncludeNull[] = {
243 "ALL",
244 "DEFAULT",
245 "ALL:!eNULL",
246 "ALL:!NULL",
David Benjamind6e9eec2015-11-18 09:48:55 -0500247 "MEDIUM",
248 "HIGH",
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700249 "FIPS",
250 "SHA",
251 "SHA1",
252 "RSA",
253 "SSLv3",
254 "TLSv1",
255 "TLSv1.2",
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700256};
257
Matt Braithwaite053931e2016-05-25 12:06:05 -0700258static const char *kMustNotIncludeCECPQ1[] = {
259 "ALL",
260 "DEFAULT",
261 "MEDIUM",
262 "HIGH",
263 "FIPS",
264 "SHA",
265 "SHA1",
266 "SHA256",
267 "SHA384",
268 "RSA",
269 "SSLv3",
270 "TLSv1",
271 "TLSv1.2",
272 "aRSA",
273 "RSA",
274 "aECDSA",
275 "ECDSA",
276 "AES",
277 "AES128",
278 "AES256",
279 "AESGCM",
280 "CHACHA20",
281};
282
David Benjamin1d77e562015-03-22 17:22:08 -0400283static void PrintCipherPreferenceList(ssl_cipher_preference_list_st *list) {
284 bool in_group = false;
285 for (size_t i = 0; i < sk_SSL_CIPHER_num(list->ciphers); i++) {
David Benjaminbb0a17c2014-09-20 15:35:39 -0400286 const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(list->ciphers, i);
287 if (!in_group && list->in_group_flags[i]) {
288 fprintf(stderr, "\t[\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400289 in_group = true;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400290 }
291 fprintf(stderr, "\t");
292 if (in_group) {
293 fprintf(stderr, " ");
294 }
295 fprintf(stderr, "%s\n", SSL_CIPHER_get_name(cipher));
296 if (in_group && !list->in_group_flags[i]) {
297 fprintf(stderr, "\t]\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400298 in_group = false;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400299 }
300 }
301}
302
David Benjaminfb974e62015-12-16 19:34:22 -0500303static bool TestCipherRule(const CipherTest &t) {
David Benjamin1d77e562015-03-22 17:22:08 -0400304 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
305 if (!ctx) {
306 return false;
David Benjamin65226252015-02-05 16:49:47 -0500307 }
308
David Benjaminfb974e62015-12-16 19:34:22 -0500309 if (!SSL_CTX_set_cipher_list(ctx.get(), t.rule)) {
310 fprintf(stderr, "Error testing cipher rule '%s'\n", t.rule);
David Benjamin1d77e562015-03-22 17:22:08 -0400311 return false;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400312 }
313
David Benjamin1d77e562015-03-22 17:22:08 -0400314 // Compare the two lists.
David Benjaminfb974e62015-12-16 19:34:22 -0500315 if (sk_SSL_CIPHER_num(ctx->cipher_list->ciphers) != t.expected.size()) {
316 fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t.rule);
317 PrintCipherPreferenceList(ctx->cipher_list);
318 return false;
319 }
320
321 for (size_t i = 0; i < t.expected.size(); i++) {
David Benjaminbb0a17c2014-09-20 15:35:39 -0400322 const SSL_CIPHER *cipher =
323 sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i);
David Benjaminfb974e62015-12-16 19:34:22 -0500324 if (t.expected[i].id != SSL_CIPHER_get_id(cipher) ||
325 t.expected[i].in_group_flag != ctx->cipher_list->in_group_flags[i]) {
326 fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t.rule);
David Benjamin1d77e562015-03-22 17:22:08 -0400327 PrintCipherPreferenceList(ctx->cipher_list);
328 return false;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400329 }
330 }
331
David Benjamin1d77e562015-03-22 17:22:08 -0400332 return true;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400333}
334
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700335static bool TestRuleDoesNotIncludeNull(const char *rule) {
336 ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_server_method()));
337 if (!ctx) {
338 return false;
339 }
340 if (!SSL_CTX_set_cipher_list(ctx.get(), rule)) {
341 fprintf(stderr, "Error: cipher rule '%s' failed\n", rule);
342 return false;
343 }
344 for (size_t i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) {
345 if (SSL_CIPHER_is_NULL(sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i))) {
346 fprintf(stderr, "Error: cipher rule '%s' includes NULL\n",rule);
347 return false;
348 }
349 }
350 return true;
351}
352
Matt Braithwaite053931e2016-05-25 12:06:05 -0700353static bool TestRuleDoesNotIncludeCECPQ1(const char *rule) {
354 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
355 if (!ctx) {
356 return false;
357 }
358 if (!SSL_CTX_set_cipher_list(ctx.get(), rule)) {
359 fprintf(stderr, "Error: cipher rule '%s' failed\n", rule);
360 return false;
361 }
362 for (size_t i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) {
363 if (SSL_CIPHER_is_CECPQ1(sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i))) {
364 fprintf(stderr, "Error: cipher rule '%s' includes CECPQ1\n",rule);
365 return false;
366 }
367 }
368 return true;
369}
370
David Benjamin1d77e562015-03-22 17:22:08 -0400371static bool TestCipherRules() {
David Benjaminfb974e62015-12-16 19:34:22 -0500372 for (const CipherTest &test : kCipherTests) {
373 if (!TestCipherRule(test)) {
David Benjamin1d77e562015-03-22 17:22:08 -0400374 return false;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400375 }
376 }
377
David Benjaminfb974e62015-12-16 19:34:22 -0500378 for (const char *rule : kBadRules) {
David Benjamin1d77e562015-03-22 17:22:08 -0400379 ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_server_method()));
380 if (!ctx) {
381 return false;
David Benjamin65226252015-02-05 16:49:47 -0500382 }
David Benjaminfb974e62015-12-16 19:34:22 -0500383 if (SSL_CTX_set_cipher_list(ctx.get(), rule)) {
384 fprintf(stderr, "Cipher rule '%s' unexpectedly succeeded\n", rule);
David Benjamin1d77e562015-03-22 17:22:08 -0400385 return false;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400386 }
387 ERR_clear_error();
David Benjaminbb0a17c2014-09-20 15:35:39 -0400388 }
389
David Benjaminfb974e62015-12-16 19:34:22 -0500390 for (const char *rule : kMustNotIncludeNull) {
391 if (!TestRuleDoesNotIncludeNull(rule)) {
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700392 return false;
393 }
394 }
395
Matt Braithwaite053931e2016-05-25 12:06:05 -0700396 for (const char *rule : kMustNotIncludeCECPQ1) {
397 if (!TestRuleDoesNotIncludeCECPQ1(rule)) {
398 return false;
399 }
400 }
401
David Benjamin1d77e562015-03-22 17:22:08 -0400402 return true;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400403}
David Benjamin2e521212014-07-16 14:37:51 -0400404
Adam Langley10f97f32016-07-12 08:09:33 -0700405// kOpenSSLSession is a serialized SSL_SESSION generated from openssl
406// s_client -sess_out.
407static const char kOpenSSLSession[] =
408 "MIIFpQIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
409 "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
410 "IWoJoQYCBFRDO46iBAICASyjggR6MIIEdjCCA16gAwIBAgIIK9dUvsPWSlUwDQYJ"
411 "KoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMx"
412 "JTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTQxMDA4"
413 "MTIwNzU3WhcNMTUwMTA2MDAwMDAwWjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwK"
414 "Q2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29v"
415 "Z2xlIEluYzEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEB"
416 "AQUAA4IBDwAwggEKAoIBAQCcKeLrplAC+Lofy8t/wDwtB6eu72CVp0cJ4V3lknN6"
417 "huH9ct6FFk70oRIh/VBNBBz900jYy+7111Jm1b8iqOTQ9aT5C7SEhNcQFJvqzH3e"
418 "MPkb6ZSWGm1yGF7MCQTGQXF20Sk/O16FSjAynU/b3oJmOctcycWYkY0ytS/k3LBu"
419 "Id45PJaoMqjB0WypqvNeJHC3q5JjCB4RP7Nfx5jjHSrCMhw8lUMW4EaDxjaR9KDh"
420 "PLgjsk+LDIySRSRDaCQGhEOWLJZVLzLo4N6/UlctCHEllpBUSvEOyFga52qroGjg"
421 "rf3WOQ925MFwzd6AK+Ich0gDRg8sQfdLH5OuP1cfLfU1AgMBAAGjggFBMIIBPTAd"
422 "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdv"
423 "b2dsZS5jb20waAYIKwYBBQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtp"
424 "Lmdvb2dsZS5jb20vR0lBRzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50"
425 "czEuZ29vZ2xlLmNvbS9vY3NwMB0GA1UdDgQWBBQ7a+CcxsZByOpc+xpYFcIbnUMZ"
426 "hTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEv"
427 "MBcGA1UdIAQQMA4wDAYKKwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRw"
428 "Oi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCa"
429 "OXCBdoqUy5bxyq+Wrh1zsyyCFim1PH5VU2+yvDSWrgDY8ibRGJmfff3r4Lud5kal"
430 "dKs9k8YlKD3ITG7P0YT/Rk8hLgfEuLcq5cc0xqmE42xJ+Eo2uzq9rYorc5emMCxf"
431 "5L0TJOXZqHQpOEcuptZQ4OjdYMfSxk5UzueUhA3ogZKRcRkdB3WeWRp+nYRhx4St"
432 "o2rt2A0MKmY9165GHUqMK9YaaXHDXqBu7Sefr1uSoAP9gyIJKeihMivsGqJ1TD6Z"
433 "cc6LMe+dN2P8cZEQHtD1y296ul4Mivqk3jatUVL8/hCwgch9A8O4PGZq9WqBfEWm"
434 "IyHh1dPtbg1lOXdYCWtjpAIEAKUDAgEUqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36S"
435 "YTcLEkXqKwOBfF9vE4KX0NxeLwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9B"
436 "sNHM362zZnY27GpTw+Kwd751CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yE"
437 "OTDKPNj3+inbMaVigtK4PLyPq+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdA"
438 "i4gv7Y5oliyn";
439
440// kCustomSession is a custom serialized SSL_SESSION generated by
441// filling in missing fields from |kOpenSSLSession|. This includes
442// providing |peer_sha256|, so |peer| is not serialized.
443static const char kCustomSession[] =
444 "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
445 "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
446 "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
447 "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
448 "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
449 "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
450 "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
451 "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF";
452
453// kBoringSSLSession is a serialized SSL_SESSION generated from bssl client.
454static const char kBoringSSLSession[] =
455 "MIIRwQIBAQICAwMEAsAvBCDdoGxGK26mR+8lM0uq6+k9xYuxPnwAjpcF9n0Yli9R"
456 "kQQwbyshfWhdi5XQ1++7n2L1qqrcVlmHBPpr6yknT/u4pUrpQB5FZ7vqvNn8MdHf"
457 "9rWgoQYCBFXgs7uiBAICHCCjggR6MIIEdjCCA16gAwIBAgIIf+yfD7Y6UicwDQYJ"
458 "KoZIhvcNAQELBQAwSTELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMx"
459 "JTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTUwODEy"
460 "MTQ1MzE1WhcNMTUxMTEwMDAwMDAwWjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwK"
461 "Q2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29v"
462 "Z2xlIEluYzEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEB"
463 "AQUAA4IBDwAwggEKAoIBAQC0MeG5YGQ0t+IeJeoneP/PrhEaieibeKYkbKVLNZpo"
464 "PLuBinvhkXZo3DC133NpCBpy6ZktBwamqyixAyuk/NU6OjgXqwwxfQ7di1AInLIU"
465 "792c7hFyNXSUCG7At8Ifi3YwBX9Ba6u/1d6rWTGZJrdCq3QU11RkKYyTq2KT5mce"
466 "Tv9iGKqSkSTlp8puy/9SZ/3DbU3U+BuqCFqeSlz7zjwFmk35acdCilpJlVDDN5C/"
467 "RCh8/UKc8PaL+cxlt531qoTENvYrflBno14YEZlCBZsPiFeUSILpKEj3Ccwhy0eL"
468 "EucWQ72YZU8mUzXBoXGn0zA0crFl5ci/2sTBBGZsylNBAgMBAAGjggFBMIIBPTAd"
469 "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdv"
470 "b2dsZS5jb20waAYIKwYBBQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtp"
471 "Lmdvb2dsZS5jb20vR0lBRzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50"
472 "czEuZ29vZ2xlLmNvbS9vY3NwMB0GA1UdDgQWBBS/bzHxcE73Q4j3slC4BLbMtLjG"
473 "GjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEv"
474 "MBcGA1UdIAQQMA4wDAYKKwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRw"
475 "Oi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQAb"
476 "qdWPZEHk0X7iKPCTHL6S3w6q1eR67goxZGFSM1lk1hjwyu7XcLJuvALVV9uY3ovE"
477 "kQZSHwT+pyOPWQhsSjO+1GyjvCvK/CAwiUmBX+bQRGaqHsRcio7xSbdVcajQ3bXd"
478 "X+s0WdbOpn6MStKAiBVloPlSxEI8pxY6x/BBCnTIk/+DMB17uZlOjG3vbAnkDkP+"
479 "n0OTucD9sHV7EVj9XUxi51nOfNBCN/s7lpUjDS/NJ4k3iwOtbCPswiot8vLO779a"
480 "f07vR03r349Iz/KTzk95rlFtX0IU+KYNxFNsanIXZ+C9FYGRXkwhHcvFb4qMUB1y"
481 "TTlM80jBMOwyjZXmjRAhpAIEAKUDAgEUqQUCAwGJwKqBpwSBpOgebbmn9NRUtMWH"
482 "+eJpqA5JLMFSMCChOsvKey3toBaCNGU7HfAEiiXNuuAdCBoK262BjQc2YYfqFzqH"
483 "zuppopXCvhohx7j/tnCNZIMgLYt/O9SXK2RYI5z8FhCCHvB4CbD5G0LGl5EFP27s"
484 "Jb6S3aTTYPkQe8yZSlxevg6NDwmTogLO9F7UUkaYmVcMQhzssEE2ZRYNwSOU6KjE"
485 "0Yj+8fAiBtbQriIEIN2L8ZlpaVrdN5KFNdvcmOxJu81P8q53X55xQyGTnGWwsgMC"
486 "ARezggvvMIIEdjCCA16gAwIBAgIIf+yfD7Y6UicwDQYJKoZIhvcNAQELBQAwSTEL"
487 "MAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2ds"
488 "ZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTUwODEyMTQ1MzE1WhcNMTUxMTEw"
489 "MDAwMDAwWjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG"
490 "A1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UE"
491 "AwwOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB"
492 "AQC0MeG5YGQ0t+IeJeoneP/PrhEaieibeKYkbKVLNZpoPLuBinvhkXZo3DC133Np"
493 "CBpy6ZktBwamqyixAyuk/NU6OjgXqwwxfQ7di1AInLIU792c7hFyNXSUCG7At8If"
494 "i3YwBX9Ba6u/1d6rWTGZJrdCq3QU11RkKYyTq2KT5mceTv9iGKqSkSTlp8puy/9S"
495 "Z/3DbU3U+BuqCFqeSlz7zjwFmk35acdCilpJlVDDN5C/RCh8/UKc8PaL+cxlt531"
496 "qoTENvYrflBno14YEZlCBZsPiFeUSILpKEj3Ccwhy0eLEucWQ72YZU8mUzXBoXGn"
497 "0zA0crFl5ci/2sTBBGZsylNBAgMBAAGjggFBMIIBPTAdBgNVHSUEFjAUBggrBgEF"
498 "BQcDAQYIKwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYB"
499 "BQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lB"
500 "RzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9v"
501 "Y3NwMB0GA1UdDgQWBBS/bzHxcE73Q4j3slC4BLbMtLjGGjAMBgNVHRMBAf8EAjAA"
502 "MB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMBcGA1UdIAQQMA4wDAYK"
503 "KwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vcGtpLmdvb2dsZS5j"
504 "b20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQAbqdWPZEHk0X7iKPCTHL6S"
505 "3w6q1eR67goxZGFSM1lk1hjwyu7XcLJuvALVV9uY3ovEkQZSHwT+pyOPWQhsSjO+"
506 "1GyjvCvK/CAwiUmBX+bQRGaqHsRcio7xSbdVcajQ3bXdX+s0WdbOpn6MStKAiBVl"
507 "oPlSxEI8pxY6x/BBCnTIk/+DMB17uZlOjG3vbAnkDkP+n0OTucD9sHV7EVj9XUxi"
508 "51nOfNBCN/s7lpUjDS/NJ4k3iwOtbCPswiot8vLO779af07vR03r349Iz/KTzk95"
509 "rlFtX0IU+KYNxFNsanIXZ+C9FYGRXkwhHcvFb4qMUB1yTTlM80jBMOwyjZXmjRAh"
510 "MIID8DCCAtigAwIBAgIDAjqDMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlVT"
511 "MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i"
512 "YWwgQ0EwHhcNMTMwNDA1MTUxNTU2WhcNMTYxMjMxMjM1OTU5WjBJMQswCQYDVQQG"
513 "EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy"
514 "bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB"
515 "AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP"
516 "VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv"
517 "h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE"
518 "ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ"
519 "EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC"
520 "DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB5zCB5DAfBgNVHSMEGDAWgBTAephojYn7"
521 "qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wDgYD"
522 "VR0PAQH/BAQDAgEGMC4GCCsGAQUFBwEBBCIwIDAeBggrBgEFBQcwAYYSaHR0cDov"
523 "L2cuc3ltY2QuY29tMBIGA1UdEwEB/wQIMAYBAf8CAQAwNQYDVR0fBC4wLDAqoCig"
524 "JoYkaHR0cDovL2cuc3ltY2IuY29tL2NybHMvZ3RnbG9iYWwuY3JsMBcGA1UdIAQQ"
525 "MA4wDAYKKwYBBAHWeQIFATANBgkqhkiG9w0BAQsFAAOCAQEAqvqpIM1qZ4PtXtR+"
526 "3h3Ef+AlBgDFJPupyC1tft6dgmUsgWM0Zj7pUsIItMsv91+ZOmqcUHqFBYx90SpI"
527 "hNMJbHzCzTWf84LuUt5oX+QAihcglvcpjZpNy6jehsgNb1aHA30DP9z6eX0hGfnI"
528 "Oi9RdozHQZJxjyXON/hKTAAj78Q1EK7gI4BzfE00LshukNYQHpmEcxpw8u1VDu4X"
529 "Bupn7jLrLN1nBz/2i8Jw3lsA5rsb0zYaImxssDVCbJAJPZPpZAkiDoUGn8JzIdPm"
530 "X4DkjYUiOnMDsWCOrmji9D6X52ASCWg23jrW4kOVWzeBkoEfu43XrVJkFleW2V40"
531 "fsg12DCCA30wggLmoAMCAQICAxK75jANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQG"
532 "EwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUg"
533 "Q2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTAyMDUyMTA0MDAwMFoXDTE4MDgyMTA0"
534 "MDAwMFowQjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xGzAZ"
535 "BgNVBAMTEkdlb1RydXN0IEdsb2JhbCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP"
536 "ADCCAQoCggEBANrMGGMw/fQXIxpWflvfPGw45HG3eJHUvKHYTPioQ7YD6U0hBwiI"
537 "2lgvZjkpvQV4i5046AW3an5xpObEYKaw74DkiSgPniXW7YPzraaRx5jJQhg1FJ2t"
538 "mEaSLk/K8YdDwRaVVy1Q74ktgHpXrfLuX2vSAI25FPgUFTXZwEaje3LIkb/JVSvN"
539 "0Jc+nCZkzN/Ogxlxyk7m1NV7qRnNVd7I7NJeOFPlXE+MLf5QIzb8ZubLjqQ5GQC3"
540 "lQI5kQsO/jgu0R0FmvZNPm8PBx2vLB6PYDni+jZTEznUXiYr2z2oFL0y6xgDKFIE"
541 "ceWrMz3hOLsHNoRinHnqFjD0X8Ar6HFr5PkCAwEAAaOB8DCB7TAfBgNVHSMEGDAW"
542 "gBRI5mj5K9KylddH2CMgEE8zmJCf1DAdBgNVHQ4EFgQUwHqYaI2J+6sFZAwRfap9"
543 "ZbjKzE4wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMw"
544 "MTAvoC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9zZWN1cmVjYS5j"
545 "cmwwTgYDVR0gBEcwRTBDBgRVHSAAMDswOQYIKwYBBQUHAgEWLWh0dHBzOi8vd3d3"
546 "Lmdlb3RydXN0LmNvbS9yZXNvdXJjZXMvcmVwb3NpdG9yeTANBgkqhkiG9w0BAQUF"
547 "AAOBgQB24RJuTksWEoYwBrKBCM/wCMfHcX5m7sLt1Dsf//DwyE7WQziwuTB9GNBV"
548 "g6JqyzYRnOhIZqNtf7gT1Ef+i1pcc/yu2RsyGTirlzQUqpbS66McFAhJtrvlke+D"
549 "NusdVm/K2rxzY5Dkf3s+Iss9B+1fOHSc4wNQTqGvmO5h8oQ/Eg==";
550
551// kBadSessionExtraField is a custom serialized SSL_SESSION generated by replacing
552// the final (optional) element of |kCustomSession| with tag number 30.
553static const char kBadSessionExtraField[] =
554 "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
555 "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
556 "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
557 "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
558 "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
559 "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
560 "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
561 "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBL4DBAEF";
562
563// kBadSessionVersion is a custom serialized SSL_SESSION generated by replacing
564// the version of |kCustomSession| with 2.
565static const char kBadSessionVersion[] =
566 "MIIBdgIBAgICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
567 "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
568 "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
569 "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
570 "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
571 "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
572 "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
573 "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF";
574
575// kBadSessionTrailingData is a custom serialized SSL_SESSION with trailing data
576// appended.
577static const char kBadSessionTrailingData[] =
578 "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
579 "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
580 "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
581 "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
582 "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
583 "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
584 "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
585 "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEFAAAA";
586
David Benjamin1d77e562015-03-22 17:22:08 -0400587static bool DecodeBase64(std::vector<uint8_t> *out, const char *in) {
David Benjamin751e8892014-10-19 00:59:36 -0400588 size_t len;
David Benjamin751e8892014-10-19 00:59:36 -0400589 if (!EVP_DecodedLength(&len, strlen(in))) {
590 fprintf(stderr, "EVP_DecodedLength failed\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400591 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400592 }
593
David Benjamin1d77e562015-03-22 17:22:08 -0400594 out->resize(len);
David Benjaminef14b2d2015-11-11 14:01:27 -0800595 if (!EVP_DecodeBase64(out->data(), &len, len, (const uint8_t *)in,
David Benjamin751e8892014-10-19 00:59:36 -0400596 strlen(in))) {
597 fprintf(stderr, "EVP_DecodeBase64 failed\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400598 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400599 }
David Benjamin1d77e562015-03-22 17:22:08 -0400600 out->resize(len);
601 return true;
David Benjamin751e8892014-10-19 00:59:36 -0400602}
603
David Benjamin1d77e562015-03-22 17:22:08 -0400604static bool TestSSL_SESSIONEncoding(const char *input_b64) {
David Benjamin751e8892014-10-19 00:59:36 -0400605 const uint8_t *cptr;
606 uint8_t *ptr;
David Benjamin751e8892014-10-19 00:59:36 -0400607
David Benjamin1d77e562015-03-22 17:22:08 -0400608 // Decode the input.
609 std::vector<uint8_t> input;
610 if (!DecodeBase64(&input, input_b64)) {
611 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400612 }
613
David Benjamin1d77e562015-03-22 17:22:08 -0400614 // Verify the SSL_SESSION decodes.
David Benjaminef14b2d2015-11-11 14:01:27 -0800615 ScopedSSL_SESSION session(SSL_SESSION_from_bytes(input.data(), input.size()));
David Benjaminfd67aa82015-06-15 19:41:48 -0400616 if (!session) {
617 fprintf(stderr, "SSL_SESSION_from_bytes failed\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400618 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400619 }
620
David Benjamin1d77e562015-03-22 17:22:08 -0400621 // Verify the SSL_SESSION encoding round-trips.
622 size_t encoded_len;
Adam Langley10f97f32016-07-12 08:09:33 -0700623 ScopedOpenSSLBytes encoded;
David Benjamin1d77e562015-03-22 17:22:08 -0400624 uint8_t *encoded_raw;
625 if (!SSL_SESSION_to_bytes(session.get(), &encoded_raw, &encoded_len)) {
David Benjamin3cac4502014-10-21 01:46:30 -0400626 fprintf(stderr, "SSL_SESSION_to_bytes failed\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400627 return false;
David Benjamin3cac4502014-10-21 01:46:30 -0400628 }
David Benjamin1d77e562015-03-22 17:22:08 -0400629 encoded.reset(encoded_raw);
630 if (encoded_len != input.size() ||
David Benjaminef14b2d2015-11-11 14:01:27 -0800631 memcmp(input.data(), encoded.get(), input.size()) != 0) {
David Benjamin3cac4502014-10-21 01:46:30 -0400632 fprintf(stderr, "SSL_SESSION_to_bytes did not round-trip\n");
Sigbjorn Vik2b23d242015-06-29 15:07:26 +0200633 hexdump(stderr, "Before: ", input.data(), input.size());
634 hexdump(stderr, "After: ", encoded_raw, encoded_len);
David Benjamin1d77e562015-03-22 17:22:08 -0400635 return false;
David Benjamin3cac4502014-10-21 01:46:30 -0400636 }
David Benjamin3cac4502014-10-21 01:46:30 -0400637
David Benjaminfd67aa82015-06-15 19:41:48 -0400638 // Verify the SSL_SESSION also decodes with the legacy API.
David Benjaminef14b2d2015-11-11 14:01:27 -0800639 cptr = input.data();
David Benjaminfd67aa82015-06-15 19:41:48 -0400640 session.reset(d2i_SSL_SESSION(NULL, &cptr, input.size()));
David Benjaminef14b2d2015-11-11 14:01:27 -0800641 if (!session || cptr != input.data() + input.size()) {
David Benjaminfd67aa82015-06-15 19:41:48 -0400642 fprintf(stderr, "d2i_SSL_SESSION failed\n");
643 return false;
644 }
645
David Benjamin1d77e562015-03-22 17:22:08 -0400646 // Verify the SSL_SESSION encoding round-trips via the legacy API.
647 int len = i2d_SSL_SESSION(session.get(), NULL);
648 if (len < 0 || (size_t)len != input.size()) {
David Benjamin751e8892014-10-19 00:59:36 -0400649 fprintf(stderr, "i2d_SSL_SESSION(NULL) returned invalid length\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400650 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400651 }
652
David Benjamin1d77e562015-03-22 17:22:08 -0400653 encoded.reset((uint8_t *)OPENSSL_malloc(input.size()));
654 if (!encoded) {
David Benjamin751e8892014-10-19 00:59:36 -0400655 fprintf(stderr, "malloc failed\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400656 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400657 }
David Benjamin1d77e562015-03-22 17:22:08 -0400658
659 ptr = encoded.get();
660 len = i2d_SSL_SESSION(session.get(), &ptr);
661 if (len < 0 || (size_t)len != input.size()) {
David Benjamin751e8892014-10-19 00:59:36 -0400662 fprintf(stderr, "i2d_SSL_SESSION returned invalid length\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400663 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400664 }
David Benjamin1d77e562015-03-22 17:22:08 -0400665 if (ptr != encoded.get() + input.size()) {
David Benjamin751e8892014-10-19 00:59:36 -0400666 fprintf(stderr, "i2d_SSL_SESSION did not advance ptr correctly\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400667 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400668 }
David Benjaminef14b2d2015-11-11 14:01:27 -0800669 if (memcmp(input.data(), encoded.get(), input.size()) != 0) {
David Benjamin751e8892014-10-19 00:59:36 -0400670 fprintf(stderr, "i2d_SSL_SESSION did not round-trip\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400671 return false;
David Benjamin751e8892014-10-19 00:59:36 -0400672 }
673
David Benjamin1d77e562015-03-22 17:22:08 -0400674 return true;
David Benjamin751e8892014-10-19 00:59:36 -0400675}
676
David Benjaminf297e022015-05-28 19:55:29 -0400677static bool TestBadSSL_SESSIONEncoding(const char *input_b64) {
678 std::vector<uint8_t> input;
679 if (!DecodeBase64(&input, input_b64)) {
680 return false;
681 }
682
683 // Verify that the SSL_SESSION fails to decode.
David Benjaminef14b2d2015-11-11 14:01:27 -0800684 ScopedSSL_SESSION session(SSL_SESSION_from_bytes(input.data(), input.size()));
David Benjaminf297e022015-05-28 19:55:29 -0400685 if (session) {
David Benjaminfd67aa82015-06-15 19:41:48 -0400686 fprintf(stderr, "SSL_SESSION_from_bytes unexpectedly succeeded\n");
David Benjaminf297e022015-05-28 19:55:29 -0400687 return false;
688 }
689 ERR_clear_error();
690 return true;
691}
692
David Benjamin10e664b2016-06-20 22:20:47 -0400693static bool TestDefaultVersion(uint16_t min_version, uint16_t max_version,
David Benjamin1d77e562015-03-22 17:22:08 -0400694 const SSL_METHOD *(*method)(void)) {
695 ScopedSSL_CTX ctx(SSL_CTX_new(method()));
696 if (!ctx) {
697 return false;
David Benjamin82c9e902014-12-12 15:55:27 -0500698 }
David Benjaminb6a0a512016-06-21 10:33:21 -0400699 if (ctx->min_version != min_version || ctx->max_version != max_version) {
700 fprintf(stderr, "Got min %04x, max %04x; wanted min %04x, max %04x\n",
701 ctx->min_version, ctx->max_version, min_version, max_version);
702 return false;
703 }
704 return true;
David Benjamin82c9e902014-12-12 15:55:27 -0500705}
706
David Benjamin1d77e562015-03-22 17:22:08 -0400707static bool CipherGetRFCName(std::string *out, uint16_t value) {
David Benjamin2bdb35c2015-02-21 11:03:06 -0500708 const SSL_CIPHER *cipher = SSL_get_cipher_by_value(value);
709 if (cipher == NULL) {
David Benjamin1d77e562015-03-22 17:22:08 -0400710 return false;
David Benjamin65226252015-02-05 16:49:47 -0500711 }
Adam Langley10f97f32016-07-12 08:09:33 -0700712 ScopedOpenSSLString rfc_name(SSL_CIPHER_get_rfc_name(cipher));
David Benjamin3fa65f02015-05-15 19:11:57 -0400713 if (!rfc_name) {
714 return false;
715 }
David Benjamin67be0482015-04-20 16:19:00 -0400716 out->assign(rfc_name.get());
David Benjamin1d77e562015-03-22 17:22:08 -0400717 return true;
David Benjamin65226252015-02-05 16:49:47 -0500718}
719
720typedef struct {
David Benjamin2bdb35c2015-02-21 11:03:06 -0500721 int id;
David Benjamin65226252015-02-05 16:49:47 -0500722 const char *rfc_name;
723} CIPHER_RFC_NAME_TEST;
724
725static const CIPHER_RFC_NAME_TEST kCipherRFCNameTests[] = {
David Benjamin2bdb35c2015-02-21 11:03:06 -0500726 { SSL3_CK_RSA_DES_192_CBC3_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA" },
727 { SSL3_CK_RSA_RC4_128_MD5, "TLS_RSA_WITH_RC4_MD5" },
728 { TLS1_CK_RSA_WITH_AES_128_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA" },
David Benjamin2bdb35c2015-02-21 11:03:06 -0500729 { TLS1_CK_DHE_RSA_WITH_AES_256_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA" },
730 { TLS1_CK_DHE_RSA_WITH_AES_256_SHA256,
731 "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256" },
David Benjamin2bdb35c2015-02-21 11:03:06 -0500732 { TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256,
733 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" },
734 { TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
735 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" },
736 { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
737 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" },
738 { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
739 "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" },
740 { TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
741 "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" },
742 { TLS1_CK_PSK_WITH_RC4_128_SHA, "TLS_PSK_WITH_RC4_SHA" },
Adam Langley85bc5602015-06-09 09:54:04 -0700743 { TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA,
744 "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA" },
David Benjamin13414b32015-12-09 23:02:39 -0500745 { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
746 "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" },
David Benjamin1d77e562015-03-22 17:22:08 -0400747 // These names are non-standard:
Brian Smith271777f2015-10-03 13:53:33 -1000748 { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD,
David Benjamin2bdb35c2015-02-21 11:03:06 -0500749 "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" },
Brian Smith271777f2015-10-03 13:53:33 -1000750 { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD,
David Benjamin2bdb35c2015-02-21 11:03:06 -0500751 "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" },
David Benjamin65226252015-02-05 16:49:47 -0500752};
753
David Benjamin1d77e562015-03-22 17:22:08 -0400754static bool TestCipherGetRFCName(void) {
755 for (size_t i = 0;
756 i < sizeof(kCipherRFCNameTests) / sizeof(kCipherRFCNameTests[0]); i++) {
David Benjamin65226252015-02-05 16:49:47 -0500757 const CIPHER_RFC_NAME_TEST *test = &kCipherRFCNameTests[i];
David Benjamin1d77e562015-03-22 17:22:08 -0400758 std::string rfc_name;
759 if (!CipherGetRFCName(&rfc_name, test->id & 0xffff)) {
760 fprintf(stderr, "SSL_CIPHER_get_rfc_name failed\n");
761 return false;
David Benjamin65226252015-02-05 16:49:47 -0500762 }
David Benjamin1d77e562015-03-22 17:22:08 -0400763 if (rfc_name != test->rfc_name) {
David Benjamin65226252015-02-05 16:49:47 -0500764 fprintf(stderr, "SSL_CIPHER_get_rfc_name: got '%s', wanted '%s'\n",
David Benjamin1d77e562015-03-22 17:22:08 -0400765 rfc_name.c_str(), test->rfc_name);
766 return false;
David Benjamin65226252015-02-05 16:49:47 -0500767 }
David Benjamin65226252015-02-05 16:49:47 -0500768 }
David Benjamin1d77e562015-03-22 17:22:08 -0400769 return true;
David Benjamin65226252015-02-05 16:49:47 -0500770}
771
David Benjamin422fe082015-07-21 22:03:43 -0400772// CreateSessionWithTicket returns a sample |SSL_SESSION| with the ticket
773// replaced for one of length |ticket_len| or nullptr on failure.
774static ScopedSSL_SESSION CreateSessionWithTicket(size_t ticket_len) {
775 std::vector<uint8_t> der;
776 if (!DecodeBase64(&der, kOpenSSLSession)) {
777 return nullptr;
778 }
David Benjaminef14b2d2015-11-11 14:01:27 -0800779 ScopedSSL_SESSION session(SSL_SESSION_from_bytes(der.data(), der.size()));
David Benjamin422fe082015-07-21 22:03:43 -0400780 if (!session) {
781 return nullptr;
782 }
783
784 // Swap out the ticket for a garbage one.
785 OPENSSL_free(session->tlsext_tick);
786 session->tlsext_tick = reinterpret_cast<uint8_t*>(OPENSSL_malloc(ticket_len));
787 if (session->tlsext_tick == nullptr) {
788 return nullptr;
789 }
790 memset(session->tlsext_tick, 'a', ticket_len);
791 session->tlsext_ticklen = ticket_len;
David Benjamin1269ddd2015-10-18 15:18:55 -0400792
793 // Fix up the timeout.
794 session->time = time(NULL);
David Benjamin422fe082015-07-21 22:03:43 -0400795 return session;
796}
797
798// GetClientHelloLen creates a client SSL connection with a ticket of length
799// |ticket_len| and records the ClientHello. It returns the length of the
800// ClientHello, not including the record header, on success and zero on error.
801static size_t GetClientHelloLen(size_t ticket_len) {
802 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
803 ScopedSSL_SESSION session = CreateSessionWithTicket(ticket_len);
804 if (!ctx || !session) {
805 return 0;
806 }
807 ScopedSSL ssl(SSL_new(ctx.get()));
808 ScopedBIO bio(BIO_new(BIO_s_mem()));
809 if (!ssl || !bio || !SSL_set_session(ssl.get(), session.get())) {
810 return 0;
811 }
812 // Do not configure a reading BIO, but record what's written to a memory BIO.
813 SSL_set_bio(ssl.get(), nullptr /* rbio */, BIO_up_ref(bio.get()));
814 int ret = SSL_connect(ssl.get());
815 if (ret > 0) {
816 // SSL_connect should fail without a BIO to write to.
817 return 0;
818 }
819 ERR_clear_error();
820
821 const uint8_t *unused;
822 size_t client_hello_len;
823 if (!BIO_mem_contents(bio.get(), &unused, &client_hello_len) ||
824 client_hello_len <= SSL3_RT_HEADER_LENGTH) {
825 return 0;
826 }
827 return client_hello_len - SSL3_RT_HEADER_LENGTH;
828}
829
830struct PaddingTest {
831 size_t input_len, padded_len;
832};
833
834static const PaddingTest kPaddingTests[] = {
835 // ClientHellos of length below 0x100 do not require padding.
836 {0xfe, 0xfe},
837 {0xff, 0xff},
838 // ClientHellos of length 0x100 through 0x1fb are padded up to 0x200.
839 {0x100, 0x200},
840 {0x123, 0x200},
841 {0x1fb, 0x200},
842 // ClientHellos of length 0x1fc through 0x1ff get padded beyond 0x200. The
843 // padding extension takes a minimum of four bytes plus one required content
844 // byte. (To work around yet more server bugs, we avoid empty final
845 // extensions.)
846 {0x1fc, 0x201},
847 {0x1fd, 0x202},
848 {0x1fe, 0x203},
849 {0x1ff, 0x204},
850 // Finally, larger ClientHellos need no padding.
851 {0x200, 0x200},
852 {0x201, 0x201},
853};
854
855static bool TestPaddingExtension() {
856 // Sample a baseline length.
857 size_t base_len = GetClientHelloLen(1);
858 if (base_len == 0) {
859 return false;
860 }
861
862 for (const PaddingTest &test : kPaddingTests) {
863 if (base_len > test.input_len) {
864 fprintf(stderr, "Baseline ClientHello too long.\n");
865 return false;
866 }
867
868 size_t padded_len = GetClientHelloLen(1 + test.input_len - base_len);
869 if (padded_len != test.padded_len) {
870 fprintf(stderr, "%u-byte ClientHello padded to %u bytes, not %u.\n",
871 static_cast<unsigned>(test.input_len),
872 static_cast<unsigned>(padded_len),
873 static_cast<unsigned>(test.padded_len));
874 return false;
875 }
876 }
877 return true;
878}
879
David Benjamin1d128f32015-09-08 17:41:40 -0400880// Test that |SSL_get_client_CA_list| echoes back the configured parameter even
881// before configuring as a server.
882static bool TestClientCAList() {
883 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
884 if (!ctx) {
885 return false;
886 }
887 ScopedSSL ssl(SSL_new(ctx.get()));
888 if (!ssl) {
889 return false;
890 }
891
892 STACK_OF(X509_NAME) *stack = sk_X509_NAME_new_null();
893 if (stack == nullptr) {
894 return false;
895 }
896 // |SSL_set_client_CA_list| takes ownership.
897 SSL_set_client_CA_list(ssl.get(), stack);
898
899 return SSL_get_client_CA_list(ssl.get()) == stack;
900}
901
David Benjamin0f653952015-10-18 14:28:01 -0400902static void AppendSession(SSL_SESSION *session, void *arg) {
903 std::vector<SSL_SESSION*> *out =
904 reinterpret_cast<std::vector<SSL_SESSION*>*>(arg);
905 out->push_back(session);
906}
907
908// ExpectCache returns true if |ctx|'s session cache consists of |expected|, in
909// order.
910static bool ExpectCache(SSL_CTX *ctx,
911 const std::vector<SSL_SESSION*> &expected) {
912 // Check the linked list.
913 SSL_SESSION *ptr = ctx->session_cache_head;
914 for (SSL_SESSION *session : expected) {
915 if (ptr != session) {
916 return false;
917 }
918 // TODO(davidben): This is an absurd way to denote the end of the list.
919 if (ptr->next ==
920 reinterpret_cast<SSL_SESSION *>(&ctx->session_cache_tail)) {
921 ptr = nullptr;
922 } else {
923 ptr = ptr->next;
924 }
925 }
926 if (ptr != nullptr) {
927 return false;
928 }
929
930 // Check the hash table.
931 std::vector<SSL_SESSION*> actual, expected_copy;
932 lh_SSL_SESSION_doall_arg(SSL_CTX_sessions(ctx), AppendSession, &actual);
933 expected_copy = expected;
934
935 std::sort(actual.begin(), actual.end());
936 std::sort(expected_copy.begin(), expected_copy.end());
937
938 return actual == expected_copy;
939}
940
941static ScopedSSL_SESSION CreateTestSession(uint32_t number) {
942 ScopedSSL_SESSION ret(SSL_SESSION_new());
943 if (!ret) {
944 return nullptr;
945 }
946
947 ret->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
948 memset(ret->session_id, 0, ret->session_id_length);
949 memcpy(ret->session_id, &number, sizeof(number));
950 return ret;
951}
952
David Benjamin0f653952015-10-18 14:28:01 -0400953// Test that the internal session cache behaves as expected.
954static bool TestInternalSessionCache() {
955 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
956 if (!ctx) {
957 return false;
958 }
959
960 // Prepare 10 test sessions.
David Benjamin4f6acaf2015-11-21 03:00:50 -0500961 std::vector<ScopedSSL_SESSION> sessions;
David Benjamin0f653952015-10-18 14:28:01 -0400962 for (int i = 0; i < 10; i++) {
963 ScopedSSL_SESSION session = CreateTestSession(i);
964 if (!session) {
965 return false;
966 }
David Benjamin4f6acaf2015-11-21 03:00:50 -0500967 sessions.push_back(std::move(session));
David Benjamin0f653952015-10-18 14:28:01 -0400968 }
969
970 SSL_CTX_sess_set_cache_size(ctx.get(), 5);
971
972 // Insert all the test sessions.
David Benjamin4f6acaf2015-11-21 03:00:50 -0500973 for (const auto &session : sessions) {
974 if (!SSL_CTX_add_session(ctx.get(), session.get())) {
David Benjamin0f653952015-10-18 14:28:01 -0400975 return false;
976 }
977 }
978
979 // Only the last five should be in the list.
David Benjamin4f6acaf2015-11-21 03:00:50 -0500980 std::vector<SSL_SESSION*> expected = {
981 sessions[9].get(),
982 sessions[8].get(),
983 sessions[7].get(),
984 sessions[6].get(),
985 sessions[5].get(),
986 };
David Benjamin0f653952015-10-18 14:28:01 -0400987 if (!ExpectCache(ctx.get(), expected)) {
988 return false;
989 }
990
991 // Inserting an element already in the cache should fail.
David Benjamin4f6acaf2015-11-21 03:00:50 -0500992 if (SSL_CTX_add_session(ctx.get(), sessions[7].get()) ||
David Benjamin0f653952015-10-18 14:28:01 -0400993 !ExpectCache(ctx.get(), expected)) {
994 return false;
995 }
996
997 // Although collisions should be impossible (256-bit session IDs), the cache
998 // must handle them gracefully.
999 ScopedSSL_SESSION collision(CreateTestSession(7));
1000 if (!collision || !SSL_CTX_add_session(ctx.get(), collision.get())) {
1001 return false;
1002 }
David Benjamin4f6acaf2015-11-21 03:00:50 -05001003 expected = {
1004 collision.get(),
1005 sessions[9].get(),
1006 sessions[8].get(),
1007 sessions[6].get(),
1008 sessions[5].get(),
1009 };
David Benjamin0f653952015-10-18 14:28:01 -04001010 if (!ExpectCache(ctx.get(), expected)) {
1011 return false;
1012 }
1013
1014 // Removing sessions behaves correctly.
David Benjamin4f6acaf2015-11-21 03:00:50 -05001015 if (!SSL_CTX_remove_session(ctx.get(), sessions[6].get())) {
David Benjamin0f653952015-10-18 14:28:01 -04001016 return false;
1017 }
David Benjamin4f6acaf2015-11-21 03:00:50 -05001018 expected = {
1019 collision.get(),
1020 sessions[9].get(),
1021 sessions[8].get(),
1022 sessions[5].get(),
1023 };
David Benjamin0f653952015-10-18 14:28:01 -04001024 if (!ExpectCache(ctx.get(), expected)) {
1025 return false;
1026 }
1027
1028 // Removing sessions requires an exact match.
David Benjamin4f6acaf2015-11-21 03:00:50 -05001029 if (SSL_CTX_remove_session(ctx.get(), sessions[0].get()) ||
1030 SSL_CTX_remove_session(ctx.get(), sessions[7].get()) ||
David Benjamin0f653952015-10-18 14:28:01 -04001031 !ExpectCache(ctx.get(), expected)) {
1032 return false;
1033 }
1034
1035 return true;
1036}
1037
David Benjaminde942382016-02-11 12:02:01 -05001038static uint16_t EpochFromSequence(uint64_t seq) {
1039 return static_cast<uint16_t>(seq >> 48);
1040}
1041
1042static ScopedX509 GetTestCertificate() {
1043 static const char kCertPEM[] =
1044 "-----BEGIN CERTIFICATE-----\n"
1045 "MIICWDCCAcGgAwIBAgIJAPuwTC6rEJsMMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV\n"
1046 "BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX\n"
1047 "aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDIzMjA1MDQwWhcNMTcwNDIyMjA1MDQwWjBF\n"
1048 "MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50\n"
1049 "ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n"
1050 "gQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92kWdGMdAQhLci\n"
1051 "HnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiFKKAnHmUcrgfV\n"
1052 "W28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQABo1AwTjAdBgNV\n"
1053 "HQ4EFgQUi3XVrMsIvg4fZbf6Vr5sp3Xaha8wHwYDVR0jBBgwFoAUi3XVrMsIvg4f\n"
1054 "Zbf6Vr5sp3Xaha8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQA76Hht\n"
1055 "ldY9avcTGSwbwoiuIqv0jTL1fHFnzy3RHMLDh+Lpvolc5DSrSJHCP5WuK0eeJXhr\n"
1056 "T5oQpHL9z/cCDLAKCKRa4uV0fhEdOWBqyR9p8y5jJtye72t6CuFUV5iqcpF4BH4f\n"
1057 "j2VNHwsSrJwkD4QUGlUtH7vwnQmyCFxZMmWAJg==\n"
1058 "-----END CERTIFICATE-----\n";
Steven Valdezd8eea142016-02-24 14:00:22 -05001059 ScopedBIO bio(BIO_new_mem_buf(kCertPEM, strlen(kCertPEM)));
David Benjaminde942382016-02-11 12:02:01 -05001060 return ScopedX509(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
1061}
1062
1063static ScopedEVP_PKEY GetTestKey() {
1064 static const char kKeyPEM[] =
1065 "-----BEGIN RSA PRIVATE KEY-----\n"
1066 "MIICXgIBAAKBgQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92\n"
1067 "kWdGMdAQhLciHnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiF\n"
1068 "KKAnHmUcrgfVW28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQAB\n"
1069 "AoGBAIBy09Fd4DOq/Ijp8HeKuCMKTHqTW1xGHshLQ6jwVV2vWZIn9aIgmDsvkjCe\n"
1070 "i6ssZvnbjVcwzSoByhjN8ZCf/i15HECWDFFh6gt0P5z0MnChwzZmvatV/FXCT0j+\n"
1071 "WmGNB/gkehKjGXLLcjTb6dRYVJSCZhVuOLLcbWIV10gggJQBAkEA8S8sGe4ezyyZ\n"
1072 "m4e9r95g6s43kPqtj5rewTsUxt+2n4eVodD+ZUlCULWVNAFLkYRTBCASlSrm9Xhj\n"
1073 "QpmWAHJUkQJBAOVzQdFUaewLtdOJoPCtpYoY1zd22eae8TQEmpGOR11L6kbxLQsk\n"
1074 "aMly/DOnOaa82tqAGTdqDEZgSNmCeKKknmECQAvpnY8GUOVAubGR6c+W90iBuQLj\n"
1075 "LtFp/9ihd2w/PoDwrHZaoUYVcT4VSfJQog/k7kjE4MYXYWL8eEKg3WTWQNECQQDk\n"
1076 "104Wi91Umd1PzF0ijd2jXOERJU1wEKe6XLkYYNHWQAe5l4J4MWj9OdxFXAxIuuR/\n"
1077 "tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd\n"
1078 "moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==\n"
1079 "-----END RSA PRIVATE KEY-----\n";
Steven Valdezd8eea142016-02-24 14:00:22 -05001080 ScopedBIO bio(BIO_new_mem_buf(kKeyPEM, strlen(kKeyPEM)));
David Benjaminde942382016-02-11 12:02:01 -05001081 return ScopedEVP_PKEY(
1082 PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
1083}
1084
David Benjamin686bb192016-05-10 15:15:41 -04001085static bool ConnectClientAndServer(ScopedSSL *out_client, ScopedSSL *out_server,
1086 SSL_CTX *client_ctx, SSL_CTX *server_ctx) {
1087 ScopedSSL client(SSL_new(client_ctx)), server(SSL_new(server_ctx));
David Benjaminde942382016-02-11 12:02:01 -05001088 if (!client || !server) {
1089 return false;
1090 }
1091 SSL_set_connect_state(client.get());
1092 SSL_set_accept_state(server.get());
1093
1094 BIO *bio1, *bio2;
1095 if (!BIO_new_bio_pair(&bio1, 0, &bio2, 0)) {
1096 return false;
1097 }
1098 // SSL_set_bio takes ownership.
1099 SSL_set_bio(client.get(), bio1, bio1);
1100 SSL_set_bio(server.get(), bio2, bio2);
1101
1102 // Drive both their handshakes to completion.
1103 for (;;) {
1104 int client_ret = SSL_do_handshake(client.get());
1105 int client_err = SSL_get_error(client.get(), client_ret);
1106 if (client_err != SSL_ERROR_NONE &&
1107 client_err != SSL_ERROR_WANT_READ &&
1108 client_err != SSL_ERROR_WANT_WRITE) {
1109 fprintf(stderr, "Client error: %d\n", client_err);
1110 return false;
1111 }
1112
1113 int server_ret = SSL_do_handshake(server.get());
1114 int server_err = SSL_get_error(server.get(), server_ret);
1115 if (server_err != SSL_ERROR_NONE &&
1116 server_err != SSL_ERROR_WANT_READ &&
1117 server_err != SSL_ERROR_WANT_WRITE) {
1118 fprintf(stderr, "Server error: %d\n", server_err);
1119 return false;
1120 }
1121
1122 if (client_ret == 1 && server_ret == 1) {
1123 break;
1124 }
1125 }
1126
David Benjamin686bb192016-05-10 15:15:41 -04001127 *out_client = std::move(client);
1128 *out_server = std::move(server);
1129 return true;
1130}
1131
1132static bool TestSequenceNumber(bool dtls) {
1133 ScopedSSL_CTX client_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
1134 ScopedSSL_CTX server_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
1135 if (!client_ctx || !server_ctx) {
1136 return false;
1137 }
1138
1139 ScopedX509 cert = GetTestCertificate();
1140 ScopedEVP_PKEY key = GetTestKey();
1141 if (!cert || !key ||
1142 !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
1143 !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
1144 return false;
1145 }
1146
1147 ScopedSSL client, server;
1148 if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
1149 server_ctx.get())) {
1150 return false;
1151 }
1152
David Benjaminde942382016-02-11 12:02:01 -05001153 uint64_t client_read_seq = SSL_get_read_sequence(client.get());
1154 uint64_t client_write_seq = SSL_get_write_sequence(client.get());
1155 uint64_t server_read_seq = SSL_get_read_sequence(server.get());
1156 uint64_t server_write_seq = SSL_get_write_sequence(server.get());
1157
1158 if (dtls) {
1159 // Both client and server must be at epoch 1.
1160 if (EpochFromSequence(client_read_seq) != 1 ||
1161 EpochFromSequence(client_write_seq) != 1 ||
1162 EpochFromSequence(server_read_seq) != 1 ||
1163 EpochFromSequence(server_write_seq) != 1) {
1164 fprintf(stderr, "Bad epochs.\n");
1165 return false;
1166 }
1167
1168 // The next record to be written should exceed the largest received.
1169 if (client_write_seq <= server_read_seq ||
1170 server_write_seq <= client_read_seq) {
1171 fprintf(stderr, "Inconsistent sequence numbers.\n");
1172 return false;
1173 }
1174 } else {
1175 // The next record to be written should equal the next to be received.
1176 if (client_write_seq != server_read_seq ||
1177 server_write_seq != client_write_seq) {
1178 fprintf(stderr, "Inconsistent sequence numbers.\n");
1179 return false;
1180 }
1181 }
1182
1183 // Send a record from client to server.
1184 uint8_t byte = 0;
1185 if (SSL_write(client.get(), &byte, 1) != 1 ||
1186 SSL_read(server.get(), &byte, 1) != 1) {
1187 fprintf(stderr, "Could not send byte.\n");
1188 return false;
1189 }
1190
1191 // The client write and server read sequence numbers should have incremented.
1192 if (client_write_seq + 1 != SSL_get_write_sequence(client.get()) ||
1193 server_read_seq + 1 != SSL_get_read_sequence(server.get())) {
1194 fprintf(stderr, "Sequence numbers did not increment.\n");\
1195 return false;
1196 }
1197
1198 return true;
1199}
1200
David Benjamin686bb192016-05-10 15:15:41 -04001201static bool TestOneSidedShutdown() {
1202 ScopedSSL_CTX client_ctx(SSL_CTX_new(TLS_method()));
1203 ScopedSSL_CTX server_ctx(SSL_CTX_new(TLS_method()));
1204 if (!client_ctx || !server_ctx) {
1205 return false;
1206 }
1207
1208 ScopedX509 cert = GetTestCertificate();
1209 ScopedEVP_PKEY key = GetTestKey();
1210 if (!cert || !key ||
1211 !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
1212 !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
1213 return false;
1214 }
1215
1216 ScopedSSL client, server;
1217 if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
1218 server_ctx.get())) {
1219 return false;
1220 }
1221
1222 // Shut down half the connection. SSL_shutdown will return 0 to signal only
1223 // one side has shut down.
1224 if (SSL_shutdown(client.get()) != 0) {
1225 fprintf(stderr, "Could not shutdown.\n");
1226 return false;
1227 }
1228
1229 // Reading from the server should consume the EOF.
1230 uint8_t byte;
1231 if (SSL_read(server.get(), &byte, 1) != 0 ||
1232 SSL_get_error(server.get(), 0) != SSL_ERROR_ZERO_RETURN) {
1233 fprintf(stderr, "Connection was not shut down cleanly.\n");
1234 return false;
1235 }
1236
1237 // However, the server may continue to write data and then shut down the
1238 // connection.
1239 byte = 42;
1240 if (SSL_write(server.get(), &byte, 1) != 1 ||
1241 SSL_read(client.get(), &byte, 1) != 1 ||
1242 byte != 42) {
1243 fprintf(stderr, "Could not send byte.\n");
1244 return false;
1245 }
1246
1247 // The server may then shutdown the connection.
1248 if (SSL_shutdown(server.get()) != 1 ||
1249 SSL_shutdown(client.get()) != 1) {
1250 fprintf(stderr, "Could not complete shutdown.\n");
1251 return false;
1252 }
1253
1254 return true;
1255}
1256
David Benjamin5c0fb882016-06-14 14:03:51 -04001257static bool ExpectFDs(const SSL *ssl, int rfd, int wfd) {
1258 if (SSL_get_rfd(ssl) != rfd || SSL_get_wfd(ssl) != wfd) {
1259 fprintf(stderr, "Got fds %d and %d, wanted %d and %d.\n", SSL_get_rfd(ssl),
1260 SSL_get_wfd(ssl), rfd, wfd);
1261 return false;
1262 }
1263
1264 // The wrapper BIOs are always equal when fds are equal, even if set
1265 // individually.
1266 if (rfd == wfd && SSL_get_rbio(ssl) != SSL_get_wbio(ssl)) {
1267 fprintf(stderr, "rbio and wbio did not match.\n");
1268 return false;
1269 }
1270
1271 return true;
1272}
1273
1274static bool TestSetFD() {
1275 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
1276 if (!ctx) {
1277 return false;
1278 }
1279
1280 // Test setting different read and write FDs.
1281 ScopedSSL ssl(SSL_new(ctx.get()));
1282 if (!ssl ||
1283 !SSL_set_rfd(ssl.get(), 1) ||
1284 !SSL_set_wfd(ssl.get(), 2) ||
1285 !ExpectFDs(ssl.get(), 1, 2)) {
1286 return false;
1287 }
1288
1289 // Test setting the same FD.
1290 ssl.reset(SSL_new(ctx.get()));
1291 if (!ssl ||
1292 !SSL_set_fd(ssl.get(), 1) ||
1293 !ExpectFDs(ssl.get(), 1, 1)) {
1294 return false;
1295 }
1296
1297 // Test setting the same FD one side at a time.
1298 ssl.reset(SSL_new(ctx.get()));
1299 if (!ssl ||
1300 !SSL_set_rfd(ssl.get(), 1) ||
1301 !SSL_set_wfd(ssl.get(), 1) ||
1302 !ExpectFDs(ssl.get(), 1, 1)) {
1303 return false;
1304 }
1305
1306 // Test setting the same FD in the other order.
1307 ssl.reset(SSL_new(ctx.get()));
1308 if (!ssl ||
1309 !SSL_set_wfd(ssl.get(), 1) ||
1310 !SSL_set_rfd(ssl.get(), 1) ||
1311 !ExpectFDs(ssl.get(), 1, 1)) {
1312 return false;
1313 }
1314
David Benjamin5c0fb882016-06-14 14:03:51 -04001315 // Test changing the read FD partway through.
1316 ssl.reset(SSL_new(ctx.get()));
1317 if (!ssl ||
1318 !SSL_set_fd(ssl.get(), 1) ||
1319 !SSL_set_rfd(ssl.get(), 2) ||
1320 !ExpectFDs(ssl.get(), 2, 1)) {
1321 return false;
1322 }
David Benjamin5c0fb882016-06-14 14:03:51 -04001323
1324 // Test changing the write FD partway through.
1325 ssl.reset(SSL_new(ctx.get()));
1326 if (!ssl ||
1327 !SSL_set_fd(ssl.get(), 1) ||
1328 !SSL_set_wfd(ssl.get(), 2) ||
1329 !ExpectFDs(ssl.get(), 1, 2)) {
1330 return false;
1331 }
1332
1333 // Test a no-op change to the read FD partway through.
1334 ssl.reset(SSL_new(ctx.get()));
1335 if (!ssl ||
1336 !SSL_set_fd(ssl.get(), 1) ||
1337 !SSL_set_rfd(ssl.get(), 1) ||
1338 !ExpectFDs(ssl.get(), 1, 1)) {
1339 return false;
1340 }
1341
1342 // Test a no-op change to the write FD partway through.
1343 ssl.reset(SSL_new(ctx.get()));
1344 if (!ssl ||
1345 !SSL_set_fd(ssl.get(), 1) ||
1346 !SSL_set_wfd(ssl.get(), 1) ||
1347 !ExpectFDs(ssl.get(), 1, 1)) {
1348 return false;
1349 }
1350
1351 // ASan builds will implicitly test that the internal |BIO| reference-counting
1352 // is correct.
1353
1354 return true;
1355}
1356
David Benjamin25490f22016-07-14 00:22:54 -04001357static uint16_t kVersions[] = {
1358 SSL3_VERSION, TLS1_VERSION, TLS1_1_VERSION, TLS1_2_VERSION, TLS1_3_VERSION,
1359};
1360
1361static int VerifySucceed(X509_STORE_CTX *store_ctx, void *arg) { return 1; }
1362
1363static bool TestRetainOnlySHA256OfCerts() {
1364 ScopedX509 cert = GetTestCertificate();
1365 ScopedEVP_PKEY key = GetTestKey();
1366 if (!cert || !key) {
1367 return false;
1368 }
1369
1370 uint8_t *cert_der = NULL;
1371 int cert_der_len = i2d_X509(cert.get(), &cert_der);
1372 if (cert_der_len < 0) {
1373 return false;
1374 }
1375 ScopedOpenSSLBytes free_cert_der(cert_der);
1376
1377 uint8_t cert_sha256[SHA256_DIGEST_LENGTH];
1378 SHA256(cert_der, cert_der_len, cert_sha256);
1379
1380 for (uint16_t version : kVersions) {
1381 // Configure both client and server to accept any certificate, but the
1382 // server must retain only the SHA-256 of the peer.
1383 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
1384 if (!ctx ||
1385 !SSL_CTX_use_certificate(ctx.get(), cert.get()) ||
1386 !SSL_CTX_use_PrivateKey(ctx.get(), key.get())) {
1387 return false;
1388 }
1389 SSL_CTX_set_min_version(ctx.get(), version);
1390 SSL_CTX_set_max_version(ctx.get(), version);
1391 SSL_CTX_set_verify(
1392 ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
1393 SSL_CTX_set_cert_verify_callback(ctx.get(), VerifySucceed, NULL);
1394 SSL_CTX_set_retain_only_sha256_of_client_certs(ctx.get(), 1);
1395
1396 ScopedSSL client, server;
1397 if (!ConnectClientAndServer(&client, &server, ctx.get(), ctx.get())) {
1398 return false;
1399 }
1400
1401 // The peer certificate has been dropped.
1402 ScopedX509 peer(SSL_get_peer_certificate(server.get()));
1403 if (peer) {
1404 fprintf(stderr, "%x: Peer certificate was retained.\n", version);
1405 return false;
1406 }
1407
1408 SSL_SESSION *session = SSL_get_session(server.get());
1409 if (!session->peer_sha256_valid) {
1410 fprintf(stderr, "%x: peer_sha256_valid was not set.\n", version);
1411 return false;
1412 }
1413
1414 if (memcmp(cert_sha256, session->peer_sha256, SHA256_DIGEST_LENGTH) != 0) {
1415 fprintf(stderr, "%x: peer_sha256 did not match.\n", version);
1416 return false;
1417 }
1418 }
1419
1420 return true;
1421}
1422
David Benjamin1d128f32015-09-08 17:41:40 -04001423int main() {
David Benjamin7a1eefd2015-10-17 23:39:22 -04001424 CRYPTO_library_init();
David Benjaminbb0a17c2014-09-20 15:35:39 -04001425
Adam Langley10f97f32016-07-12 08:09:33 -07001426 if (!TestCipherRules() ||
1427 !TestSSL_SESSIONEncoding(kOpenSSLSession) ||
1428 !TestSSL_SESSIONEncoding(kCustomSession) ||
1429 !TestSSL_SESSIONEncoding(kBoringSSLSession) ||
1430 !TestBadSSL_SESSIONEncoding(kBadSessionExtraField) ||
1431 !TestBadSSL_SESSIONEncoding(kBadSessionVersion) ||
1432 !TestBadSSL_SESSIONEncoding(kBadSessionTrailingData) ||
David Benjamin10e664b2016-06-20 22:20:47 -04001433 // TODO(svaldez): Update this when TLS 1.3 is enabled by default.
Adam Langley10f97f32016-07-12 08:09:33 -07001434 !TestDefaultVersion(SSL3_VERSION, TLS1_2_VERSION, &TLS_method) ||
1435 !TestDefaultVersion(SSL3_VERSION, SSL3_VERSION, &SSLv3_method) ||
1436 !TestDefaultVersion(TLS1_VERSION, TLS1_VERSION, &TLSv1_method) ||
1437 !TestDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION, &TLSv1_1_method) ||
1438 !TestDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION, &TLSv1_2_method) ||
1439 !TestDefaultVersion(TLS1_1_VERSION, TLS1_2_VERSION, &DTLS_method) ||
1440 !TestDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION, &DTLSv1_method) ||
1441 !TestDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION, &DTLSv1_2_method) ||
1442 !TestCipherGetRFCName() ||
1443 !TestPaddingExtension() ||
1444 !TestClientCAList() ||
1445 !TestInternalSessionCache() ||
1446 !TestSequenceNumber(false /* TLS */) ||
1447 !TestSequenceNumber(true /* DTLS */) ||
1448 !TestOneSidedShutdown() ||
David Benjamin25490f22016-07-14 00:22:54 -04001449 !TestSetFD() ||
1450 !TestRetainOnlySHA256OfCerts()) {
Brian Smith83a82982015-04-09 16:21:10 -10001451 ERR_print_errors_fp(stderr);
David Benjaminbb0a17c2014-09-20 15:35:39 -04001452 return 1;
1453 }
1454
David Benjamin2e521212014-07-16 14:37:51 -04001455 printf("PASS\n");
1456 return 0;
1457}