blob: 92fad05d3b00723fcd5417f9ac8cc653c6d5ddf4 [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 Benjaminbb0a17c2014-09-20 15:35:39 -040029#include <openssl/ssl.h>
David Benjaminde942382016-02-11 12:02:01 -050030#include <openssl/x509.h>
David Benjaminbb0a17c2014-09-20 15:35:39 -040031
David Benjamin1d77e562015-03-22 17:22:08 -040032#include "test/scoped_types.h"
Sigbjorn Vik2b23d242015-06-29 15:07:26 +020033#include "../crypto/test/test_util.h"
34
David Benjamin1d77e562015-03-22 17:22:08 -040035
Adam Langley09feb0f2016-07-11 14:07:19 -070036// kOpenSSLSession is a serialized SSL_SESSION generated from openssl
37// s_client -sess_out.
38static const char kOpenSSLSession[] =
39 "MIIFpQIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
40 "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
41 "IWoJoQYCBFRDO46iBAICASyjggR6MIIEdjCCA16gAwIBAgIIK9dUvsPWSlUwDQYJ"
42 "KoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMx"
43 "JTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTQxMDA4"
44 "MTIwNzU3WhcNMTUwMTA2MDAwMDAwWjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwK"
45 "Q2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29v"
46 "Z2xlIEluYzEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEB"
47 "AQUAA4IBDwAwggEKAoIBAQCcKeLrplAC+Lofy8t/wDwtB6eu72CVp0cJ4V3lknN6"
48 "huH9ct6FFk70oRIh/VBNBBz900jYy+7111Jm1b8iqOTQ9aT5C7SEhNcQFJvqzH3e"
49 "MPkb6ZSWGm1yGF7MCQTGQXF20Sk/O16FSjAynU/b3oJmOctcycWYkY0ytS/k3LBu"
50 "Id45PJaoMqjB0WypqvNeJHC3q5JjCB4RP7Nfx5jjHSrCMhw8lUMW4EaDxjaR9KDh"
51 "PLgjsk+LDIySRSRDaCQGhEOWLJZVLzLo4N6/UlctCHEllpBUSvEOyFga52qroGjg"
52 "rf3WOQ925MFwzd6AK+Ich0gDRg8sQfdLH5OuP1cfLfU1AgMBAAGjggFBMIIBPTAd"
53 "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdv"
54 "b2dsZS5jb20waAYIKwYBBQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtp"
55 "Lmdvb2dsZS5jb20vR0lBRzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50"
56 "czEuZ29vZ2xlLmNvbS9vY3NwMB0GA1UdDgQWBBQ7a+CcxsZByOpc+xpYFcIbnUMZ"
57 "hTAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEv"
58 "MBcGA1UdIAQQMA4wDAYKKwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRw"
59 "Oi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCa"
60 "OXCBdoqUy5bxyq+Wrh1zsyyCFim1PH5VU2+yvDSWrgDY8ibRGJmfff3r4Lud5kal"
61 "dKs9k8YlKD3ITG7P0YT/Rk8hLgfEuLcq5cc0xqmE42xJ+Eo2uzq9rYorc5emMCxf"
62 "5L0TJOXZqHQpOEcuptZQ4OjdYMfSxk5UzueUhA3ogZKRcRkdB3WeWRp+nYRhx4St"
63 "o2rt2A0MKmY9165GHUqMK9YaaXHDXqBu7Sefr1uSoAP9gyIJKeihMivsGqJ1TD6Z"
64 "cc6LMe+dN2P8cZEQHtD1y296ul4Mivqk3jatUVL8/hCwgch9A8O4PGZq9WqBfEWm"
65 "IyHh1dPtbg1lOXdYCWtjpAIEAKUDAgEUqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36S"
66 "YTcLEkXqKwOBfF9vE4KX0NxeLwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9B"
67 "sNHM362zZnY27GpTw+Kwd751CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yE"
68 "OTDKPNj3+inbMaVigtK4PLyPq+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdA"
69 "i4gv7Y5oliyn";
70
71// kCustomSession is a custom serialized SSL_SESSION generated by
72// filling in missing fields from |kOpenSSLSession|. This includes
73// providing |peer_sha256|, so |peer| is not serialized.
74static const char kCustomSession[] =
75 "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
76 "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
77 "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
78 "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
79 "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
80 "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
81 "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
82 "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF";
83
84// kBoringSSLSession is a serialized SSL_SESSION generated from bssl client.
85static const char kBoringSSLSession[] =
86 "MIIRwQIBAQICAwMEAsAvBCDdoGxGK26mR+8lM0uq6+k9xYuxPnwAjpcF9n0Yli9R"
87 "kQQwbyshfWhdi5XQ1++7n2L1qqrcVlmHBPpr6yknT/u4pUrpQB5FZ7vqvNn8MdHf"
88 "9rWgoQYCBFXgs7uiBAICHCCjggR6MIIEdjCCA16gAwIBAgIIf+yfD7Y6UicwDQYJ"
89 "KoZIhvcNAQELBQAwSTELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMx"
90 "JTAjBgNVBAMTHEdvb2dsZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTUwODEy"
91 "MTQ1MzE1WhcNMTUxMTEwMDAwMDAwWjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwK"
92 "Q2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29v"
93 "Z2xlIEluYzEXMBUGA1UEAwwOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEB"
94 "AQUAA4IBDwAwggEKAoIBAQC0MeG5YGQ0t+IeJeoneP/PrhEaieibeKYkbKVLNZpo"
95 "PLuBinvhkXZo3DC133NpCBpy6ZktBwamqyixAyuk/NU6OjgXqwwxfQ7di1AInLIU"
96 "792c7hFyNXSUCG7At8Ifi3YwBX9Ba6u/1d6rWTGZJrdCq3QU11RkKYyTq2KT5mce"
97 "Tv9iGKqSkSTlp8puy/9SZ/3DbU3U+BuqCFqeSlz7zjwFmk35acdCilpJlVDDN5C/"
98 "RCh8/UKc8PaL+cxlt531qoTENvYrflBno14YEZlCBZsPiFeUSILpKEj3Ccwhy0eL"
99 "EucWQ72YZU8mUzXBoXGn0zA0crFl5ci/2sTBBGZsylNBAgMBAAGjggFBMIIBPTAd"
100 "BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdv"
101 "b2dsZS5jb20waAYIKwYBBQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtp"
102 "Lmdvb2dsZS5jb20vR0lBRzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50"
103 "czEuZ29vZ2xlLmNvbS9vY3NwMB0GA1UdDgQWBBS/bzHxcE73Q4j3slC4BLbMtLjG"
104 "GjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEv"
105 "MBcGA1UdIAQQMA4wDAYKKwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRw"
106 "Oi8vcGtpLmdvb2dsZS5jb20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQAb"
107 "qdWPZEHk0X7iKPCTHL6S3w6q1eR67goxZGFSM1lk1hjwyu7XcLJuvALVV9uY3ovE"
108 "kQZSHwT+pyOPWQhsSjO+1GyjvCvK/CAwiUmBX+bQRGaqHsRcio7xSbdVcajQ3bXd"
109 "X+s0WdbOpn6MStKAiBVloPlSxEI8pxY6x/BBCnTIk/+DMB17uZlOjG3vbAnkDkP+"
110 "n0OTucD9sHV7EVj9XUxi51nOfNBCN/s7lpUjDS/NJ4k3iwOtbCPswiot8vLO779a"
111 "f07vR03r349Iz/KTzk95rlFtX0IU+KYNxFNsanIXZ+C9FYGRXkwhHcvFb4qMUB1y"
112 "TTlM80jBMOwyjZXmjRAhpAIEAKUDAgEUqQUCAwGJwKqBpwSBpOgebbmn9NRUtMWH"
113 "+eJpqA5JLMFSMCChOsvKey3toBaCNGU7HfAEiiXNuuAdCBoK262BjQc2YYfqFzqH"
114 "zuppopXCvhohx7j/tnCNZIMgLYt/O9SXK2RYI5z8FhCCHvB4CbD5G0LGl5EFP27s"
115 "Jb6S3aTTYPkQe8yZSlxevg6NDwmTogLO9F7UUkaYmVcMQhzssEE2ZRYNwSOU6KjE"
116 "0Yj+8fAiBtbQriIEIN2L8ZlpaVrdN5KFNdvcmOxJu81P8q53X55xQyGTnGWwsgMC"
117 "ARezggvvMIIEdjCCA16gAwIBAgIIf+yfD7Y6UicwDQYJKoZIhvcNAQELBQAwSTEL"
118 "MAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2ds"
119 "ZSBJbnRlcm5ldCBBdXRob3JpdHkgRzIwHhcNMTUwODEyMTQ1MzE1WhcNMTUxMTEw"
120 "MDAwMDAwWjBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG"
121 "A1UEBwwNTW91bnRhaW4gVmlldzETMBEGA1UECgwKR29vZ2xlIEluYzEXMBUGA1UE"
122 "AwwOd3d3Lmdvb2dsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB"
123 "AQC0MeG5YGQ0t+IeJeoneP/PrhEaieibeKYkbKVLNZpoPLuBinvhkXZo3DC133Np"
124 "CBpy6ZktBwamqyixAyuk/NU6OjgXqwwxfQ7di1AInLIU792c7hFyNXSUCG7At8If"
125 "i3YwBX9Ba6u/1d6rWTGZJrdCq3QU11RkKYyTq2KT5mceTv9iGKqSkSTlp8puy/9S"
126 "Z/3DbU3U+BuqCFqeSlz7zjwFmk35acdCilpJlVDDN5C/RCh8/UKc8PaL+cxlt531"
127 "qoTENvYrflBno14YEZlCBZsPiFeUSILpKEj3Ccwhy0eLEucWQ72YZU8mUzXBoXGn"
128 "0zA0crFl5ci/2sTBBGZsylNBAgMBAAGjggFBMIIBPTAdBgNVHSUEFjAUBggrBgEF"
129 "BQcDAQYIKwYBBQUHAwIwGQYDVR0RBBIwEIIOd3d3Lmdvb2dsZS5jb20waAYIKwYB"
130 "BQUHAQEEXDBaMCsGCCsGAQUFBzAChh9odHRwOi8vcGtpLmdvb2dsZS5jb20vR0lB"
131 "RzIuY3J0MCsGCCsGAQUFBzABhh9odHRwOi8vY2xpZW50czEuZ29vZ2xlLmNvbS9v"
132 "Y3NwMB0GA1UdDgQWBBS/bzHxcE73Q4j3slC4BLbMtLjGGjAMBgNVHRMBAf8EAjAA"
133 "MB8GA1UdIwQYMBaAFErdBhYbvPZotXb1gba7Yhq6WoEvMBcGA1UdIAQQMA4wDAYK"
134 "KwYBBAHWeQIFATAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vcGtpLmdvb2dsZS5j"
135 "b20vR0lBRzIuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQAbqdWPZEHk0X7iKPCTHL6S"
136 "3w6q1eR67goxZGFSM1lk1hjwyu7XcLJuvALVV9uY3ovEkQZSHwT+pyOPWQhsSjO+"
137 "1GyjvCvK/CAwiUmBX+bQRGaqHsRcio7xSbdVcajQ3bXdX+s0WdbOpn6MStKAiBVl"
138 "oPlSxEI8pxY6x/BBCnTIk/+DMB17uZlOjG3vbAnkDkP+n0OTucD9sHV7EVj9XUxi"
139 "51nOfNBCN/s7lpUjDS/NJ4k3iwOtbCPswiot8vLO779af07vR03r349Iz/KTzk95"
140 "rlFtX0IU+KYNxFNsanIXZ+C9FYGRXkwhHcvFb4qMUB1yTTlM80jBMOwyjZXmjRAh"
141 "MIID8DCCAtigAwIBAgIDAjqDMA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlVT"
142 "MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i"
143 "YWwgQ0EwHhcNMTMwNDA1MTUxNTU2WhcNMTYxMjMxMjM1OTU5WjBJMQswCQYDVQQG"
144 "EwJVUzETMBEGA1UEChMKR29vZ2xlIEluYzElMCMGA1UEAxMcR29vZ2xlIEludGVy"
145 "bmV0IEF1dGhvcml0eSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB"
146 "AJwqBHdc2FCROgajguDYUEi8iT/xGXAaiEZ+4I/F8YnOIe5a/mENtzJEiaB0C1NP"
147 "VaTOgmKV7utZX8bhBYASxF6UP7xbSDj0U/ck5vuR6RXEz/RTDfRK/J9U3n2+oGtv"
148 "h8DQUB8oMANA2ghzUWx//zo8pzcGjr1LEQTrfSTe5vn8MXH7lNVg8y5Kr0LSy+rE"
149 "ahqyzFPdFUuLH8gZYR/Nnag+YyuENWllhMgZxUYi+FOVvuOAShDGKuy6lyARxzmZ"
150 "EASg8GF6lSWMTlJ14rbtCMoU/M4iarNOz0YDl5cDfsCx3nuvRTPPuj5xt970JSXC"
151 "DTWJnZ37DhF5iR43xa+OcmkCAwEAAaOB5zCB5DAfBgNVHSMEGDAWgBTAephojYn7"
152 "qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUSt0GFhu89mi1dvWBtrtiGrpagS8wDgYD"
153 "VR0PAQH/BAQDAgEGMC4GCCsGAQUFBwEBBCIwIDAeBggrBgEFBQcwAYYSaHR0cDov"
154 "L2cuc3ltY2QuY29tMBIGA1UdEwEB/wQIMAYBAf8CAQAwNQYDVR0fBC4wLDAqoCig"
155 "JoYkaHR0cDovL2cuc3ltY2IuY29tL2NybHMvZ3RnbG9iYWwuY3JsMBcGA1UdIAQQ"
156 "MA4wDAYKKwYBBAHWeQIFATANBgkqhkiG9w0BAQsFAAOCAQEAqvqpIM1qZ4PtXtR+"
157 "3h3Ef+AlBgDFJPupyC1tft6dgmUsgWM0Zj7pUsIItMsv91+ZOmqcUHqFBYx90SpI"
158 "hNMJbHzCzTWf84LuUt5oX+QAihcglvcpjZpNy6jehsgNb1aHA30DP9z6eX0hGfnI"
159 "Oi9RdozHQZJxjyXON/hKTAAj78Q1EK7gI4BzfE00LshukNYQHpmEcxpw8u1VDu4X"
160 "Bupn7jLrLN1nBz/2i8Jw3lsA5rsb0zYaImxssDVCbJAJPZPpZAkiDoUGn8JzIdPm"
161 "X4DkjYUiOnMDsWCOrmji9D6X52ASCWg23jrW4kOVWzeBkoEfu43XrVJkFleW2V40"
162 "fsg12DCCA30wggLmoAMCAQICAxK75jANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQG"
163 "EwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUg"
164 "Q2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTAyMDUyMTA0MDAwMFoXDTE4MDgyMTA0"
165 "MDAwMFowQjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xGzAZ"
166 "BgNVBAMTEkdlb1RydXN0IEdsb2JhbCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP"
167 "ADCCAQoCggEBANrMGGMw/fQXIxpWflvfPGw45HG3eJHUvKHYTPioQ7YD6U0hBwiI"
168 "2lgvZjkpvQV4i5046AW3an5xpObEYKaw74DkiSgPniXW7YPzraaRx5jJQhg1FJ2t"
169 "mEaSLk/K8YdDwRaVVy1Q74ktgHpXrfLuX2vSAI25FPgUFTXZwEaje3LIkb/JVSvN"
170 "0Jc+nCZkzN/Ogxlxyk7m1NV7qRnNVd7I7NJeOFPlXE+MLf5QIzb8ZubLjqQ5GQC3"
171 "lQI5kQsO/jgu0R0FmvZNPm8PBx2vLB6PYDni+jZTEznUXiYr2z2oFL0y6xgDKFIE"
172 "ceWrMz3hOLsHNoRinHnqFjD0X8Ar6HFr5PkCAwEAAaOB8DCB7TAfBgNVHSMEGDAW"
173 "gBRI5mj5K9KylddH2CMgEE8zmJCf1DAdBgNVHQ4EFgQUwHqYaI2J+6sFZAwRfap9"
174 "ZbjKzE4wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwOgYDVR0fBDMw"
175 "MTAvoC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9zZWN1cmVjYS5j"
176 "cmwwTgYDVR0gBEcwRTBDBgRVHSAAMDswOQYIKwYBBQUHAgEWLWh0dHBzOi8vd3d3"
177 "Lmdlb3RydXN0LmNvbS9yZXNvdXJjZXMvcmVwb3NpdG9yeTANBgkqhkiG9w0BAQUF"
178 "AAOBgQB24RJuTksWEoYwBrKBCM/wCMfHcX5m7sLt1Dsf//DwyE7WQziwuTB9GNBV"
179 "g6JqyzYRnOhIZqNtf7gT1Ef+i1pcc/yu2RsyGTirlzQUqpbS66McFAhJtrvlke+D"
180 "NusdVm/K2rxzY5Dkf3s+Iss9B+1fOHSc4wNQTqGvmO5h8oQ/Eg==";
181
182// kBadSessionExtraField is a custom serialized SSL_SESSION generated by replacing
183// the final (optional) element of |kCustomSession| with tag number 30.
184static const char kBadSessionExtraField[] =
185 "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
186 "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
187 "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
188 "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
189 "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
190 "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
191 "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
192 "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBL4DBAEF";
193
194// kBadSessionVersion is a custom serialized SSL_SESSION generated by replacing
195// the version of |kCustomSession| with 2.
196static const char kBadSessionVersion[] =
197 "MIIBdgIBAgICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
198 "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
199 "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
200 "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
201 "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
202 "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
203 "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
204 "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEF";
205
206// kBadSessionTrailingData is a custom serialized SSL_SESSION with trailing data
207// appended.
208static const char kBadSessionTrailingData[] =
209 "MIIBdgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
210 "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
211 "IWoJoQYCBFRDO46iBAICASykAwQBAqUDAgEUphAEDnd3dy5nb29nbGUuY29tqAcE"
212 "BXdvcmxkqQUCAwGJwKqBpwSBpBwUQvoeOk0Kg36SYTcLEkXqKwOBfF9vE4KX0Nxe"
213 "LwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9BsNHM362zZnY27GpTw+Kwd751"
214 "CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yEOTDKPNj3+inbMaVigtK4PLyP"
215 "q+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdAi4gv7Y5oliynrSIEIAYGBgYG"
216 "BgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGrgMEAQevAwQBBLADBAEFAAAA";
217
218namespace bssl {
219
David Benjamin1d77e562015-03-22 17:22:08 -0400220struct ExpectedCipher {
221 unsigned long id;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400222 int in_group_flag;
David Benjamin1d77e562015-03-22 17:22:08 -0400223};
David Benjaminbb0a17c2014-09-20 15:35:39 -0400224
David Benjamin1d77e562015-03-22 17:22:08 -0400225struct CipherTest {
226 // The rule string to apply.
David Benjaminbb0a17c2014-09-20 15:35:39 -0400227 const char *rule;
David Benjaminfb974e62015-12-16 19:34:22 -0500228 // The list of expected ciphers, in order.
229 std::vector<ExpectedCipher> expected;
David Benjamin1d77e562015-03-22 17:22:08 -0400230};
David Benjaminbb0a17c2014-09-20 15:35:39 -0400231
David Benjaminfb974e62015-12-16 19:34:22 -0500232static const CipherTest kCipherTests[] = {
233 // Selecting individual ciphers should work.
234 {
235 "ECDHE-ECDSA-CHACHA20-POLY1305:"
236 "ECDHE-RSA-CHACHA20-POLY1305:"
237 "ECDHE-ECDSA-AES128-GCM-SHA256:"
238 "ECDHE-RSA-AES128-GCM-SHA256",
239 {
240 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
241 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
242 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
243 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
244 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
245 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
246 },
247 },
248 // + reorders selected ciphers to the end, keeping their relative order.
249 {
250 "ECDHE-ECDSA-CHACHA20-POLY1305:"
251 "ECDHE-RSA-CHACHA20-POLY1305:"
252 "ECDHE-ECDSA-AES128-GCM-SHA256:"
253 "ECDHE-RSA-AES128-GCM-SHA256:"
254 "+aRSA",
255 {
256 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
257 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
258 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
259 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
260 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
261 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
262 },
263 },
264 // ! banishes ciphers from future selections.
265 {
266 "!aRSA:"
267 "ECDHE-ECDSA-CHACHA20-POLY1305:"
268 "ECDHE-RSA-CHACHA20-POLY1305:"
269 "ECDHE-ECDSA-AES128-GCM-SHA256:"
270 "ECDHE-RSA-AES128-GCM-SHA256",
271 {
272 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
273 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
274 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
275 },
276 },
277 // Multiple masks can be ANDed in a single rule.
278 {
279 "kRSA+AESGCM+AES128",
280 {
281 {TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0},
282 },
283 },
284 // - removes selected ciphers, but preserves their order for future
285 // selections. Select AES_128_GCM, but order the key exchanges RSA, DHE_RSA,
286 // ECDHE_RSA.
287 {
288 "ALL:-kECDHE:-kDHE:-kRSA:-ALL:"
289 "AESGCM+AES128+aRSA",
290 {
291 {TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0},
292 {TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, 0},
293 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
294 },
295 },
296 // Unknown selectors are no-ops.
297 {
298 "ECDHE-ECDSA-CHACHA20-POLY1305:"
299 "ECDHE-RSA-CHACHA20-POLY1305:"
300 "ECDHE-ECDSA-AES128-GCM-SHA256:"
301 "ECDHE-RSA-AES128-GCM-SHA256:"
302 "BOGUS1:-BOGUS2:+BOGUS3:!BOGUS4",
303 {
304 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
305 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
306 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
307 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
308 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
309 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
310 },
311 },
312 // Square brackets specify equi-preference groups.
313 {
314 "[ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]:"
315 "[ECDHE-RSA-CHACHA20-POLY1305]:"
316 "ECDHE-RSA-AES128-GCM-SHA256",
317 {
318 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 1},
319 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 1},
320 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
321 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 1},
322 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
323 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
324 },
325 },
326 // @STRENGTH performs a stable strength-sort of the selected ciphers and
327 // only the selected ciphers.
328 {
329 // To simplify things, banish all but {ECDHE_RSA,RSA} x
330 // {CHACHA20,AES_256_CBC,AES_128_CBC,RC4} x SHA1.
331 "!kEDH:!AESGCM:!3DES:!SHA256:!MD5:!SHA384:"
332 // Order some ciphers backwards by strength.
333 "ALL:-CHACHA20:-AES256:-AES128:-RC4:-ALL:"
334 // Select ECDHE ones and sort them by strength. Ties should resolve
335 // based on the order above.
336 "kECDHE:@STRENGTH:-ALL:"
337 // Now bring back everything uses RSA. ECDHE_RSA should be first, sorted
338 // by strength. Then RSA, backwards by strength.
339 "aRSA",
340 {
341 {TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, 0},
342 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
343 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
344 {TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA, 0},
345 {TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, 0},
346 {SSL3_CK_RSA_RC4_128_SHA, 0},
347 {TLS1_CK_RSA_WITH_AES_128_SHA, 0},
348 {TLS1_CK_RSA_WITH_AES_256_SHA, 0},
349 },
350 },
351 // Exact ciphers may not be used in multi-part rules; they are treated
352 // as unknown aliases.
353 {
354 "ECDHE-ECDSA-AES128-GCM-SHA256:"
355 "ECDHE-RSA-AES128-GCM-SHA256:"
356 "!ECDHE-RSA-AES128-GCM-SHA256+RSA:"
357 "!ECDSA+ECDHE-ECDSA-AES128-GCM-SHA256",
358 {
359 {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
360 {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
361 },
362 },
363 // SSLv3 matches everything that existed before TLS 1.2.
364 {
365 "AES128-SHA:AES128-SHA256:!SSLv3",
366 {
367 {TLS1_CK_RSA_WITH_AES_128_SHA256, 0},
368 },
369 },
370 // TLSv1.2 matches everything added in TLS 1.2.
371 {
372 "AES128-SHA:AES128-SHA256:!TLSv1.2",
373 {
374 {TLS1_CK_RSA_WITH_AES_128_SHA, 0},
375 },
376 },
377 // The two directives have no intersection.
378 {
379 "AES128-SHA:AES128-SHA256:!TLSv1.2+SSLv3",
380 {
381 {TLS1_CK_RSA_WITH_AES_128_SHA, 0},
382 {TLS1_CK_RSA_WITH_AES_128_SHA256, 0},
383 },
384 },
385 // The shared name of the CHACHA20_POLY1305 variants behaves like a cipher
386 // name and not an alias. It may not be used in a multipart rule. (That the
387 // shared name works is covered by the standard tests.)
388 {
389 "ECDHE-ECDSA-CHACHA20-POLY1305:"
390 "ECDHE-RSA-CHACHA20-POLY1305:"
391 "!ECDHE-RSA-CHACHA20-POLY1305+RSA:"
392 "!ECDSA+ECDHE-ECDSA-CHACHA20-POLY1305",
393 {
394 {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
395 {TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0},
396 {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
397 {TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0},
398 },
399 },
David Benjaminbb0a17c2014-09-20 15:35:39 -0400400};
401
402static const char *kBadRules[] = {
David Benjamin1d77e562015-03-22 17:22:08 -0400403 // Invalid brackets.
David Benjaminbb0a17c2014-09-20 15:35:39 -0400404 "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256",
405 "RSA]",
406 "[[RSA]]",
David Benjamin1d77e562015-03-22 17:22:08 -0400407 // Operators inside brackets.
David Benjaminbb0a17c2014-09-20 15:35:39 -0400408 "[+RSA]",
David Benjamin1d77e562015-03-22 17:22:08 -0400409 // Unknown directive.
David Benjaminbb0a17c2014-09-20 15:35:39 -0400410 "@BOGUS",
David Benjamin1d77e562015-03-22 17:22:08 -0400411 // Empty cipher lists error at SSL_CTX_set_cipher_list.
David Benjaminbb0a17c2014-09-20 15:35:39 -0400412 "",
413 "BOGUS",
David Benjamin32fbdf22015-04-07 01:14:06 -0400414 // COMPLEMENTOFDEFAULT is empty.
415 "COMPLEMENTOFDEFAULT",
David Benjamin1d77e562015-03-22 17:22:08 -0400416 // Invalid command.
David Benjaminbb0a17c2014-09-20 15:35:39 -0400417 "?BAR",
David Benjamin1d77e562015-03-22 17:22:08 -0400418 // Special operators are not allowed if groups are used.
David Benjamin37d92462014-09-20 17:54:24 -0400419 "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:+FOO",
420 "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:!FOO",
421 "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:-FOO",
422 "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:@STRENGTH",
David Benjaminbb0a17c2014-09-20 15:35:39 -0400423};
424
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700425static const char *kMustNotIncludeNull[] = {
426 "ALL",
427 "DEFAULT",
428 "ALL:!eNULL",
429 "ALL:!NULL",
David Benjamind6e9eec2015-11-18 09:48:55 -0500430 "MEDIUM",
431 "HIGH",
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700432 "FIPS",
433 "SHA",
434 "SHA1",
435 "RSA",
436 "SSLv3",
437 "TLSv1",
438 "TLSv1.2",
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700439};
440
Matt Braithwaite053931e2016-05-25 12:06:05 -0700441static const char *kMustNotIncludeCECPQ1[] = {
442 "ALL",
443 "DEFAULT",
444 "MEDIUM",
445 "HIGH",
446 "FIPS",
447 "SHA",
448 "SHA1",
449 "SHA256",
450 "SHA384",
451 "RSA",
452 "SSLv3",
453 "TLSv1",
454 "TLSv1.2",
455 "aRSA",
456 "RSA",
457 "aECDSA",
458 "ECDSA",
459 "AES",
460 "AES128",
461 "AES256",
462 "AESGCM",
463 "CHACHA20",
464};
465
David Benjamin1d77e562015-03-22 17:22:08 -0400466static void PrintCipherPreferenceList(ssl_cipher_preference_list_st *list) {
467 bool in_group = false;
468 for (size_t i = 0; i < sk_SSL_CIPHER_num(list->ciphers); i++) {
David Benjaminbb0a17c2014-09-20 15:35:39 -0400469 const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(list->ciphers, i);
470 if (!in_group && list->in_group_flags[i]) {
471 fprintf(stderr, "\t[\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400472 in_group = true;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400473 }
474 fprintf(stderr, "\t");
475 if (in_group) {
476 fprintf(stderr, " ");
477 }
478 fprintf(stderr, "%s\n", SSL_CIPHER_get_name(cipher));
479 if (in_group && !list->in_group_flags[i]) {
480 fprintf(stderr, "\t]\n");
David Benjamin1d77e562015-03-22 17:22:08 -0400481 in_group = false;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400482 }
483 }
484}
485
David Benjaminfb974e62015-12-16 19:34:22 -0500486static bool TestCipherRule(const CipherTest &t) {
David Benjamin1d77e562015-03-22 17:22:08 -0400487 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
488 if (!ctx) {
489 return false;
David Benjamin65226252015-02-05 16:49:47 -0500490 }
491
David Benjaminfb974e62015-12-16 19:34:22 -0500492 if (!SSL_CTX_set_cipher_list(ctx.get(), t.rule)) {
493 fprintf(stderr, "Error testing cipher rule '%s'\n", t.rule);
David Benjamin1d77e562015-03-22 17:22:08 -0400494 return false;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400495 }
496
David Benjamin1d77e562015-03-22 17:22:08 -0400497 // Compare the two lists.
David Benjaminfb974e62015-12-16 19:34:22 -0500498 if (sk_SSL_CIPHER_num(ctx->cipher_list->ciphers) != t.expected.size()) {
499 fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t.rule);
500 PrintCipherPreferenceList(ctx->cipher_list);
501 return false;
502 }
503
504 for (size_t i = 0; i < t.expected.size(); i++) {
David Benjaminbb0a17c2014-09-20 15:35:39 -0400505 const SSL_CIPHER *cipher =
506 sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i);
David Benjaminfb974e62015-12-16 19:34:22 -0500507 if (t.expected[i].id != SSL_CIPHER_get_id(cipher) ||
508 t.expected[i].in_group_flag != ctx->cipher_list->in_group_flags[i]) {
509 fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t.rule);
David Benjamin1d77e562015-03-22 17:22:08 -0400510 PrintCipherPreferenceList(ctx->cipher_list);
511 return false;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400512 }
513 }
514
David Benjamin1d77e562015-03-22 17:22:08 -0400515 return true;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400516}
517
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700518static bool TestRuleDoesNotIncludeNull(const char *rule) {
519 ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_server_method()));
520 if (!ctx) {
521 return false;
522 }
523 if (!SSL_CTX_set_cipher_list(ctx.get(), rule)) {
524 fprintf(stderr, "Error: cipher rule '%s' failed\n", rule);
525 return false;
526 }
527 for (size_t i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) {
528 if (SSL_CIPHER_is_NULL(sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i))) {
529 fprintf(stderr, "Error: cipher rule '%s' includes NULL\n",rule);
530 return false;
531 }
532 }
533 return true;
534}
535
Matt Braithwaite053931e2016-05-25 12:06:05 -0700536static bool TestRuleDoesNotIncludeCECPQ1(const char *rule) {
537 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
538 if (!ctx) {
539 return false;
540 }
541 if (!SSL_CTX_set_cipher_list(ctx.get(), rule)) {
542 fprintf(stderr, "Error: cipher rule '%s' failed\n", rule);
543 return false;
544 }
545 for (size_t i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) {
546 if (SSL_CIPHER_is_CECPQ1(sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i))) {
547 fprintf(stderr, "Error: cipher rule '%s' includes CECPQ1\n",rule);
548 return false;
549 }
550 }
551 return true;
552}
553
David Benjamin1d77e562015-03-22 17:22:08 -0400554static bool TestCipherRules() {
David Benjaminfb974e62015-12-16 19:34:22 -0500555 for (const CipherTest &test : kCipherTests) {
556 if (!TestCipherRule(test)) {
David Benjamin1d77e562015-03-22 17:22:08 -0400557 return false;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400558 }
559 }
560
David Benjaminfb974e62015-12-16 19:34:22 -0500561 for (const char *rule : kBadRules) {
David Benjamin1d77e562015-03-22 17:22:08 -0400562 ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_server_method()));
563 if (!ctx) {
564 return false;
David Benjamin65226252015-02-05 16:49:47 -0500565 }
David Benjaminfb974e62015-12-16 19:34:22 -0500566 if (SSL_CTX_set_cipher_list(ctx.get(), rule)) {
567 fprintf(stderr, "Cipher rule '%s' unexpectedly succeeded\n", rule);
David Benjamin1d77e562015-03-22 17:22:08 -0400568 return false;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400569 }
570 ERR_clear_error();
David Benjaminbb0a17c2014-09-20 15:35:39 -0400571 }
572
David Benjaminfb974e62015-12-16 19:34:22 -0500573 for (const char *rule : kMustNotIncludeNull) {
574 if (!TestRuleDoesNotIncludeNull(rule)) {
Matt Braithwaiteaf096752015-09-02 19:48:16 -0700575 return false;
576 }
577 }
578
Matt Braithwaite053931e2016-05-25 12:06:05 -0700579 for (const char *rule : kMustNotIncludeCECPQ1) {
580 if (!TestRuleDoesNotIncludeCECPQ1(rule)) {
581 return false;
582 }
583 }
584
David Benjamin1d77e562015-03-22 17:22:08 -0400585 return true;
David Benjaminbb0a17c2014-09-20 15:35:39 -0400586}
David Benjamin2e521212014-07-16 14:37:51 -0400587
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 Langley09feb0f2016-07-11 14:07:19 -0700624 ScopedBytes 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 Langley09feb0f2016-07-11 14:07:19 -0700713 ScopedString rfc_name(SSL_CIPHER_get_rfc_name(cipher));
David Benjamin3fa65f02015-05-15 19:11:57 -0400714 if (!rfc_name) {
715 return false;
716 }
David Benjamin67be0482015-04-20 16:19:00 -0400717 out->assign(rfc_name.get());
David Benjamin1d77e562015-03-22 17:22:08 -0400718 return true;
David Benjamin65226252015-02-05 16:49:47 -0500719}
720
721typedef struct {
David Benjamin2bdb35c2015-02-21 11:03:06 -0500722 int id;
David Benjamin65226252015-02-05 16:49:47 -0500723 const char *rfc_name;
724} CIPHER_RFC_NAME_TEST;
725
726static const CIPHER_RFC_NAME_TEST kCipherRFCNameTests[] = {
David Benjamin2bdb35c2015-02-21 11:03:06 -0500727 { SSL3_CK_RSA_DES_192_CBC3_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA" },
728 { SSL3_CK_RSA_RC4_128_MD5, "TLS_RSA_WITH_RC4_MD5" },
729 { TLS1_CK_RSA_WITH_AES_128_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA" },
David Benjamin2bdb35c2015-02-21 11:03:06 -0500730 { TLS1_CK_DHE_RSA_WITH_AES_256_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA" },
731 { TLS1_CK_DHE_RSA_WITH_AES_256_SHA256,
732 "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256" },
David Benjamin2bdb35c2015-02-21 11:03:06 -0500733 { TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256,
734 "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" },
735 { TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
736 "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" },
737 { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
738 "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" },
739 { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
740 "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" },
741 { TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
742 "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" },
743 { TLS1_CK_PSK_WITH_RC4_128_SHA, "TLS_PSK_WITH_RC4_SHA" },
Adam Langley85bc5602015-06-09 09:54:04 -0700744 { TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA,
745 "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA" },
David Benjamin13414b32015-12-09 23:02:39 -0500746 { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
747 "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" },
David Benjamin1d77e562015-03-22 17:22:08 -0400748 // These names are non-standard:
Brian Smith271777f2015-10-03 13:53:33 -1000749 { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD,
David Benjamin2bdb35c2015-02-21 11:03:06 -0500750 "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" },
Brian Smith271777f2015-10-03 13:53:33 -1000751 { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD,
David Benjamin2bdb35c2015-02-21 11:03:06 -0500752 "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" },
David Benjamin65226252015-02-05 16:49:47 -0500753};
754
David Benjamin1d77e562015-03-22 17:22:08 -0400755static bool TestCipherGetRFCName(void) {
756 for (size_t i = 0;
757 i < sizeof(kCipherRFCNameTests) / sizeof(kCipherRFCNameTests[0]); i++) {
David Benjamin65226252015-02-05 16:49:47 -0500758 const CIPHER_RFC_NAME_TEST *test = &kCipherRFCNameTests[i];
David Benjamin1d77e562015-03-22 17:22:08 -0400759 std::string rfc_name;
760 if (!CipherGetRFCName(&rfc_name, test->id & 0xffff)) {
761 fprintf(stderr, "SSL_CIPHER_get_rfc_name failed\n");
762 return false;
David Benjamin65226252015-02-05 16:49:47 -0500763 }
David Benjamin1d77e562015-03-22 17:22:08 -0400764 if (rfc_name != test->rfc_name) {
David Benjamin65226252015-02-05 16:49:47 -0500765 fprintf(stderr, "SSL_CIPHER_get_rfc_name: got '%s', wanted '%s'\n",
David Benjamin1d77e562015-03-22 17:22:08 -0400766 rfc_name.c_str(), test->rfc_name);
767 return false;
David Benjamin65226252015-02-05 16:49:47 -0500768 }
David Benjamin65226252015-02-05 16:49:47 -0500769 }
David Benjamin1d77e562015-03-22 17:22:08 -0400770 return true;
David Benjamin65226252015-02-05 16:49:47 -0500771}
772
David Benjamin422fe082015-07-21 22:03:43 -0400773// CreateSessionWithTicket returns a sample |SSL_SESSION| with the ticket
774// replaced for one of length |ticket_len| or nullptr on failure.
775static ScopedSSL_SESSION CreateSessionWithTicket(size_t ticket_len) {
776 std::vector<uint8_t> der;
777 if (!DecodeBase64(&der, kOpenSSLSession)) {
778 return nullptr;
779 }
David Benjaminef14b2d2015-11-11 14:01:27 -0800780 ScopedSSL_SESSION session(SSL_SESSION_from_bytes(der.data(), der.size()));
David Benjamin422fe082015-07-21 22:03:43 -0400781 if (!session) {
782 return nullptr;
783 }
784
785 // Swap out the ticket for a garbage one.
786 OPENSSL_free(session->tlsext_tick);
787 session->tlsext_tick = reinterpret_cast<uint8_t*>(OPENSSL_malloc(ticket_len));
788 if (session->tlsext_tick == nullptr) {
789 return nullptr;
790 }
791 memset(session->tlsext_tick, 'a', ticket_len);
792 session->tlsext_ticklen = ticket_len;
David Benjamin1269ddd2015-10-18 15:18:55 -0400793
794 // Fix up the timeout.
795 session->time = time(NULL);
David Benjamin422fe082015-07-21 22:03:43 -0400796 return session;
797}
798
799// GetClientHelloLen creates a client SSL connection with a ticket of length
800// |ticket_len| and records the ClientHello. It returns the length of the
801// ClientHello, not including the record header, on success and zero on error.
802static size_t GetClientHelloLen(size_t ticket_len) {
803 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
804 ScopedSSL_SESSION session = CreateSessionWithTicket(ticket_len);
805 if (!ctx || !session) {
806 return 0;
807 }
808 ScopedSSL ssl(SSL_new(ctx.get()));
809 ScopedBIO bio(BIO_new(BIO_s_mem()));
810 if (!ssl || !bio || !SSL_set_session(ssl.get(), session.get())) {
811 return 0;
812 }
813 // Do not configure a reading BIO, but record what's written to a memory BIO.
814 SSL_set_bio(ssl.get(), nullptr /* rbio */, BIO_up_ref(bio.get()));
815 int ret = SSL_connect(ssl.get());
816 if (ret > 0) {
817 // SSL_connect should fail without a BIO to write to.
818 return 0;
819 }
820 ERR_clear_error();
821
822 const uint8_t *unused;
823 size_t client_hello_len;
824 if (!BIO_mem_contents(bio.get(), &unused, &client_hello_len) ||
825 client_hello_len <= SSL3_RT_HEADER_LENGTH) {
826 return 0;
827 }
828 return client_hello_len - SSL3_RT_HEADER_LENGTH;
829}
830
831struct PaddingTest {
832 size_t input_len, padded_len;
833};
834
835static const PaddingTest kPaddingTests[] = {
836 // ClientHellos of length below 0x100 do not require padding.
837 {0xfe, 0xfe},
838 {0xff, 0xff},
839 // ClientHellos of length 0x100 through 0x1fb are padded up to 0x200.
840 {0x100, 0x200},
841 {0x123, 0x200},
842 {0x1fb, 0x200},
843 // ClientHellos of length 0x1fc through 0x1ff get padded beyond 0x200. The
844 // padding extension takes a minimum of four bytes plus one required content
845 // byte. (To work around yet more server bugs, we avoid empty final
846 // extensions.)
847 {0x1fc, 0x201},
848 {0x1fd, 0x202},
849 {0x1fe, 0x203},
850 {0x1ff, 0x204},
851 // Finally, larger ClientHellos need no padding.
852 {0x200, 0x200},
853 {0x201, 0x201},
854};
855
856static bool TestPaddingExtension() {
857 // Sample a baseline length.
858 size_t base_len = GetClientHelloLen(1);
859 if (base_len == 0) {
860 return false;
861 }
862
863 for (const PaddingTest &test : kPaddingTests) {
864 if (base_len > test.input_len) {
865 fprintf(stderr, "Baseline ClientHello too long.\n");
866 return false;
867 }
868
869 size_t padded_len = GetClientHelloLen(1 + test.input_len - base_len);
870 if (padded_len != test.padded_len) {
871 fprintf(stderr, "%u-byte ClientHello padded to %u bytes, not %u.\n",
872 static_cast<unsigned>(test.input_len),
873 static_cast<unsigned>(padded_len),
874 static_cast<unsigned>(test.padded_len));
875 return false;
876 }
877 }
878 return true;
879}
880
David Benjamin1d128f32015-09-08 17:41:40 -0400881// Test that |SSL_get_client_CA_list| echoes back the configured parameter even
882// before configuring as a server.
883static bool TestClientCAList() {
884 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
885 if (!ctx) {
886 return false;
887 }
888 ScopedSSL ssl(SSL_new(ctx.get()));
889 if (!ssl) {
890 return false;
891 }
892
893 STACK_OF(X509_NAME) *stack = sk_X509_NAME_new_null();
894 if (stack == nullptr) {
895 return false;
896 }
897 // |SSL_set_client_CA_list| takes ownership.
898 SSL_set_client_CA_list(ssl.get(), stack);
899
900 return SSL_get_client_CA_list(ssl.get()) == stack;
901}
902
David Benjamin0f653952015-10-18 14:28:01 -0400903static void AppendSession(SSL_SESSION *session, void *arg) {
904 std::vector<SSL_SESSION*> *out =
905 reinterpret_cast<std::vector<SSL_SESSION*>*>(arg);
906 out->push_back(session);
907}
908
909// ExpectCache returns true if |ctx|'s session cache consists of |expected|, in
910// order.
911static bool ExpectCache(SSL_CTX *ctx,
912 const std::vector<SSL_SESSION*> &expected) {
913 // Check the linked list.
914 SSL_SESSION *ptr = ctx->session_cache_head;
915 for (SSL_SESSION *session : expected) {
916 if (ptr != session) {
917 return false;
918 }
919 // TODO(davidben): This is an absurd way to denote the end of the list.
920 if (ptr->next ==
921 reinterpret_cast<SSL_SESSION *>(&ctx->session_cache_tail)) {
922 ptr = nullptr;
923 } else {
924 ptr = ptr->next;
925 }
926 }
927 if (ptr != nullptr) {
928 return false;
929 }
930
931 // Check the hash table.
932 std::vector<SSL_SESSION*> actual, expected_copy;
933 lh_SSL_SESSION_doall_arg(SSL_CTX_sessions(ctx), AppendSession, &actual);
934 expected_copy = expected;
935
936 std::sort(actual.begin(), actual.end());
937 std::sort(expected_copy.begin(), expected_copy.end());
938
939 return actual == expected_copy;
940}
941
942static ScopedSSL_SESSION CreateTestSession(uint32_t number) {
943 ScopedSSL_SESSION ret(SSL_SESSION_new());
944 if (!ret) {
945 return nullptr;
946 }
947
948 ret->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
949 memset(ret->session_id, 0, ret->session_id_length);
950 memcpy(ret->session_id, &number, sizeof(number));
951 return ret;
952}
953
David Benjamin0f653952015-10-18 14:28:01 -0400954// Test that the internal session cache behaves as expected.
955static bool TestInternalSessionCache() {
956 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
957 if (!ctx) {
958 return false;
959 }
960
961 // Prepare 10 test sessions.
David Benjamin4f6acaf2015-11-21 03:00:50 -0500962 std::vector<ScopedSSL_SESSION> sessions;
David Benjamin0f653952015-10-18 14:28:01 -0400963 for (int i = 0; i < 10; i++) {
964 ScopedSSL_SESSION session = CreateTestSession(i);
965 if (!session) {
966 return false;
967 }
David Benjamin4f6acaf2015-11-21 03:00:50 -0500968 sessions.push_back(std::move(session));
David Benjamin0f653952015-10-18 14:28:01 -0400969 }
970
971 SSL_CTX_sess_set_cache_size(ctx.get(), 5);
972
973 // Insert all the test sessions.
David Benjamin4f6acaf2015-11-21 03:00:50 -0500974 for (const auto &session : sessions) {
975 if (!SSL_CTX_add_session(ctx.get(), session.get())) {
David Benjamin0f653952015-10-18 14:28:01 -0400976 return false;
977 }
978 }
979
980 // Only the last five should be in the list.
David Benjamin4f6acaf2015-11-21 03:00:50 -0500981 std::vector<SSL_SESSION*> expected = {
982 sessions[9].get(),
983 sessions[8].get(),
984 sessions[7].get(),
985 sessions[6].get(),
986 sessions[5].get(),
987 };
David Benjamin0f653952015-10-18 14:28:01 -0400988 if (!ExpectCache(ctx.get(), expected)) {
989 return false;
990 }
991
992 // Inserting an element already in the cache should fail.
David Benjamin4f6acaf2015-11-21 03:00:50 -0500993 if (SSL_CTX_add_session(ctx.get(), sessions[7].get()) ||
David Benjamin0f653952015-10-18 14:28:01 -0400994 !ExpectCache(ctx.get(), expected)) {
995 return false;
996 }
997
998 // Although collisions should be impossible (256-bit session IDs), the cache
999 // must handle them gracefully.
1000 ScopedSSL_SESSION collision(CreateTestSession(7));
1001 if (!collision || !SSL_CTX_add_session(ctx.get(), collision.get())) {
1002 return false;
1003 }
David Benjamin4f6acaf2015-11-21 03:00:50 -05001004 expected = {
1005 collision.get(),
1006 sessions[9].get(),
1007 sessions[8].get(),
1008 sessions[6].get(),
1009 sessions[5].get(),
1010 };
David Benjamin0f653952015-10-18 14:28:01 -04001011 if (!ExpectCache(ctx.get(), expected)) {
1012 return false;
1013 }
1014
1015 // Removing sessions behaves correctly.
David Benjamin4f6acaf2015-11-21 03:00:50 -05001016 if (!SSL_CTX_remove_session(ctx.get(), sessions[6].get())) {
David Benjamin0f653952015-10-18 14:28:01 -04001017 return false;
1018 }
David Benjamin4f6acaf2015-11-21 03:00:50 -05001019 expected = {
1020 collision.get(),
1021 sessions[9].get(),
1022 sessions[8].get(),
1023 sessions[5].get(),
1024 };
David Benjamin0f653952015-10-18 14:28:01 -04001025 if (!ExpectCache(ctx.get(), expected)) {
1026 return false;
1027 }
1028
1029 // Removing sessions requires an exact match.
David Benjamin4f6acaf2015-11-21 03:00:50 -05001030 if (SSL_CTX_remove_session(ctx.get(), sessions[0].get()) ||
1031 SSL_CTX_remove_session(ctx.get(), sessions[7].get()) ||
David Benjamin0f653952015-10-18 14:28:01 -04001032 !ExpectCache(ctx.get(), expected)) {
1033 return false;
1034 }
1035
1036 return true;
1037}
1038
David Benjaminde942382016-02-11 12:02:01 -05001039static uint16_t EpochFromSequence(uint64_t seq) {
1040 return static_cast<uint16_t>(seq >> 48);
1041}
1042
1043static ScopedX509 GetTestCertificate() {
1044 static const char kCertPEM[] =
1045 "-----BEGIN CERTIFICATE-----\n"
1046 "MIICWDCCAcGgAwIBAgIJAPuwTC6rEJsMMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV\n"
1047 "BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX\n"
1048 "aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDIzMjA1MDQwWhcNMTcwNDIyMjA1MDQwWjBF\n"
1049 "MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50\n"
1050 "ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n"
1051 "gQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92kWdGMdAQhLci\n"
1052 "HnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiFKKAnHmUcrgfV\n"
1053 "W28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQABo1AwTjAdBgNV\n"
1054 "HQ4EFgQUi3XVrMsIvg4fZbf6Vr5sp3Xaha8wHwYDVR0jBBgwFoAUi3XVrMsIvg4f\n"
1055 "Zbf6Vr5sp3Xaha8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQA76Hht\n"
1056 "ldY9avcTGSwbwoiuIqv0jTL1fHFnzy3RHMLDh+Lpvolc5DSrSJHCP5WuK0eeJXhr\n"
1057 "T5oQpHL9z/cCDLAKCKRa4uV0fhEdOWBqyR9p8y5jJtye72t6CuFUV5iqcpF4BH4f\n"
1058 "j2VNHwsSrJwkD4QUGlUtH7vwnQmyCFxZMmWAJg==\n"
1059 "-----END CERTIFICATE-----\n";
Steven Valdezd8eea142016-02-24 14:00:22 -05001060 ScopedBIO bio(BIO_new_mem_buf(kCertPEM, strlen(kCertPEM)));
David Benjaminde942382016-02-11 12:02:01 -05001061 return ScopedX509(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
1062}
1063
1064static ScopedEVP_PKEY GetTestKey() {
1065 static const char kKeyPEM[] =
1066 "-----BEGIN RSA PRIVATE KEY-----\n"
1067 "MIICXgIBAAKBgQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92\n"
1068 "kWdGMdAQhLciHnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiF\n"
1069 "KKAnHmUcrgfVW28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQAB\n"
1070 "AoGBAIBy09Fd4DOq/Ijp8HeKuCMKTHqTW1xGHshLQ6jwVV2vWZIn9aIgmDsvkjCe\n"
1071 "i6ssZvnbjVcwzSoByhjN8ZCf/i15HECWDFFh6gt0P5z0MnChwzZmvatV/FXCT0j+\n"
1072 "WmGNB/gkehKjGXLLcjTb6dRYVJSCZhVuOLLcbWIV10gggJQBAkEA8S8sGe4ezyyZ\n"
1073 "m4e9r95g6s43kPqtj5rewTsUxt+2n4eVodD+ZUlCULWVNAFLkYRTBCASlSrm9Xhj\n"
1074 "QpmWAHJUkQJBAOVzQdFUaewLtdOJoPCtpYoY1zd22eae8TQEmpGOR11L6kbxLQsk\n"
1075 "aMly/DOnOaa82tqAGTdqDEZgSNmCeKKknmECQAvpnY8GUOVAubGR6c+W90iBuQLj\n"
1076 "LtFp/9ihd2w/PoDwrHZaoUYVcT4VSfJQog/k7kjE4MYXYWL8eEKg3WTWQNECQQDk\n"
1077 "104Wi91Umd1PzF0ijd2jXOERJU1wEKe6XLkYYNHWQAe5l4J4MWj9OdxFXAxIuuR/\n"
1078 "tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd\n"
1079 "moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==\n"
1080 "-----END RSA PRIVATE KEY-----\n";
Steven Valdezd8eea142016-02-24 14:00:22 -05001081 ScopedBIO bio(BIO_new_mem_buf(kKeyPEM, strlen(kKeyPEM)));
David Benjaminde942382016-02-11 12:02:01 -05001082 return ScopedEVP_PKEY(
1083 PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
1084}
1085
David Benjamin686bb192016-05-10 15:15:41 -04001086static bool ConnectClientAndServer(ScopedSSL *out_client, ScopedSSL *out_server,
1087 SSL_CTX *client_ctx, SSL_CTX *server_ctx) {
1088 ScopedSSL client(SSL_new(client_ctx)), server(SSL_new(server_ctx));
David Benjaminde942382016-02-11 12:02:01 -05001089 if (!client || !server) {
1090 return false;
1091 }
1092 SSL_set_connect_state(client.get());
1093 SSL_set_accept_state(server.get());
1094
1095 BIO *bio1, *bio2;
1096 if (!BIO_new_bio_pair(&bio1, 0, &bio2, 0)) {
1097 return false;
1098 }
1099 // SSL_set_bio takes ownership.
1100 SSL_set_bio(client.get(), bio1, bio1);
1101 SSL_set_bio(server.get(), bio2, bio2);
1102
1103 // Drive both their handshakes to completion.
1104 for (;;) {
1105 int client_ret = SSL_do_handshake(client.get());
1106 int client_err = SSL_get_error(client.get(), client_ret);
1107 if (client_err != SSL_ERROR_NONE &&
1108 client_err != SSL_ERROR_WANT_READ &&
1109 client_err != SSL_ERROR_WANT_WRITE) {
1110 fprintf(stderr, "Client error: %d\n", client_err);
1111 return false;
1112 }
1113
1114 int server_ret = SSL_do_handshake(server.get());
1115 int server_err = SSL_get_error(server.get(), server_ret);
1116 if (server_err != SSL_ERROR_NONE &&
1117 server_err != SSL_ERROR_WANT_READ &&
1118 server_err != SSL_ERROR_WANT_WRITE) {
1119 fprintf(stderr, "Server error: %d\n", server_err);
1120 return false;
1121 }
1122
1123 if (client_ret == 1 && server_ret == 1) {
1124 break;
1125 }
1126 }
1127
David Benjamin686bb192016-05-10 15:15:41 -04001128 *out_client = std::move(client);
1129 *out_server = std::move(server);
1130 return true;
1131}
1132
1133static bool TestSequenceNumber(bool dtls) {
1134 ScopedSSL_CTX client_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
1135 ScopedSSL_CTX server_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
1136 if (!client_ctx || !server_ctx) {
1137 return false;
1138 }
1139
1140 ScopedX509 cert = GetTestCertificate();
1141 ScopedEVP_PKEY key = GetTestKey();
1142 if (!cert || !key ||
1143 !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
1144 !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
1145 return false;
1146 }
1147
1148 ScopedSSL client, server;
1149 if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
1150 server_ctx.get())) {
1151 return false;
1152 }
1153
David Benjaminde942382016-02-11 12:02:01 -05001154 uint64_t client_read_seq = SSL_get_read_sequence(client.get());
1155 uint64_t client_write_seq = SSL_get_write_sequence(client.get());
1156 uint64_t server_read_seq = SSL_get_read_sequence(server.get());
1157 uint64_t server_write_seq = SSL_get_write_sequence(server.get());
1158
1159 if (dtls) {
1160 // Both client and server must be at epoch 1.
1161 if (EpochFromSequence(client_read_seq) != 1 ||
1162 EpochFromSequence(client_write_seq) != 1 ||
1163 EpochFromSequence(server_read_seq) != 1 ||
1164 EpochFromSequence(server_write_seq) != 1) {
1165 fprintf(stderr, "Bad epochs.\n");
1166 return false;
1167 }
1168
1169 // The next record to be written should exceed the largest received.
1170 if (client_write_seq <= server_read_seq ||
1171 server_write_seq <= client_read_seq) {
1172 fprintf(stderr, "Inconsistent sequence numbers.\n");
1173 return false;
1174 }
1175 } else {
1176 // The next record to be written should equal the next to be received.
1177 if (client_write_seq != server_read_seq ||
1178 server_write_seq != client_write_seq) {
1179 fprintf(stderr, "Inconsistent sequence numbers.\n");
1180 return false;
1181 }
1182 }
1183
1184 // Send a record from client to server.
1185 uint8_t byte = 0;
1186 if (SSL_write(client.get(), &byte, 1) != 1 ||
1187 SSL_read(server.get(), &byte, 1) != 1) {
1188 fprintf(stderr, "Could not send byte.\n");
1189 return false;
1190 }
1191
1192 // The client write and server read sequence numbers should have incremented.
1193 if (client_write_seq + 1 != SSL_get_write_sequence(client.get()) ||
1194 server_read_seq + 1 != SSL_get_read_sequence(server.get())) {
1195 fprintf(stderr, "Sequence numbers did not increment.\n");\
1196 return false;
1197 }
1198
1199 return true;
1200}
1201
David Benjamin686bb192016-05-10 15:15:41 -04001202static bool TestOneSidedShutdown() {
1203 ScopedSSL_CTX client_ctx(SSL_CTX_new(TLS_method()));
1204 ScopedSSL_CTX server_ctx(SSL_CTX_new(TLS_method()));
1205 if (!client_ctx || !server_ctx) {
1206 return false;
1207 }
1208
1209 ScopedX509 cert = GetTestCertificate();
1210 ScopedEVP_PKEY key = GetTestKey();
1211 if (!cert || !key ||
1212 !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
1213 !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
1214 return false;
1215 }
1216
1217 ScopedSSL client, server;
1218 if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
1219 server_ctx.get())) {
1220 return false;
1221 }
1222
1223 // Shut down half the connection. SSL_shutdown will return 0 to signal only
1224 // one side has shut down.
1225 if (SSL_shutdown(client.get()) != 0) {
1226 fprintf(stderr, "Could not shutdown.\n");
1227 return false;
1228 }
1229
1230 // Reading from the server should consume the EOF.
1231 uint8_t byte;
1232 if (SSL_read(server.get(), &byte, 1) != 0 ||
1233 SSL_get_error(server.get(), 0) != SSL_ERROR_ZERO_RETURN) {
1234 fprintf(stderr, "Connection was not shut down cleanly.\n");
1235 return false;
1236 }
1237
1238 // However, the server may continue to write data and then shut down the
1239 // connection.
1240 byte = 42;
1241 if (SSL_write(server.get(), &byte, 1) != 1 ||
1242 SSL_read(client.get(), &byte, 1) != 1 ||
1243 byte != 42) {
1244 fprintf(stderr, "Could not send byte.\n");
1245 return false;
1246 }
1247
1248 // The server may then shutdown the connection.
1249 if (SSL_shutdown(server.get()) != 1 ||
1250 SSL_shutdown(client.get()) != 1) {
1251 fprintf(stderr, "Could not complete shutdown.\n");
1252 return false;
1253 }
1254
1255 return true;
1256}
1257
David Benjamin5c0fb882016-06-14 14:03:51 -04001258static bool ExpectFDs(const SSL *ssl, int rfd, int wfd) {
1259 if (SSL_get_rfd(ssl) != rfd || SSL_get_wfd(ssl) != wfd) {
1260 fprintf(stderr, "Got fds %d and %d, wanted %d and %d.\n", SSL_get_rfd(ssl),
1261 SSL_get_wfd(ssl), rfd, wfd);
1262 return false;
1263 }
1264
1265 // The wrapper BIOs are always equal when fds are equal, even if set
1266 // individually.
1267 if (rfd == wfd && SSL_get_rbio(ssl) != SSL_get_wbio(ssl)) {
1268 fprintf(stderr, "rbio and wbio did not match.\n");
1269 return false;
1270 }
1271
1272 return true;
1273}
1274
1275static bool TestSetFD() {
1276 ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
1277 if (!ctx) {
1278 return false;
1279 }
1280
1281 // Test setting different read and write FDs.
1282 ScopedSSL ssl(SSL_new(ctx.get()));
1283 if (!ssl ||
1284 !SSL_set_rfd(ssl.get(), 1) ||
1285 !SSL_set_wfd(ssl.get(), 2) ||
1286 !ExpectFDs(ssl.get(), 1, 2)) {
1287 return false;
1288 }
1289
1290 // Test setting the same FD.
1291 ssl.reset(SSL_new(ctx.get()));
1292 if (!ssl ||
1293 !SSL_set_fd(ssl.get(), 1) ||
1294 !ExpectFDs(ssl.get(), 1, 1)) {
1295 return false;
1296 }
1297
1298 // Test setting the same FD one side at a time.
1299 ssl.reset(SSL_new(ctx.get()));
1300 if (!ssl ||
1301 !SSL_set_rfd(ssl.get(), 1) ||
1302 !SSL_set_wfd(ssl.get(), 1) ||
1303 !ExpectFDs(ssl.get(), 1, 1)) {
1304 return false;
1305 }
1306
1307 // Test setting the same FD in the other order.
1308 ssl.reset(SSL_new(ctx.get()));
1309 if (!ssl ||
1310 !SSL_set_wfd(ssl.get(), 1) ||
1311 !SSL_set_rfd(ssl.get(), 1) ||
1312 !ExpectFDs(ssl.get(), 1, 1)) {
1313 return false;
1314 }
1315
David Benjamin5c0fb882016-06-14 14:03:51 -04001316 // Test changing the read FD partway through.
1317 ssl.reset(SSL_new(ctx.get()));
1318 if (!ssl ||
1319 !SSL_set_fd(ssl.get(), 1) ||
1320 !SSL_set_rfd(ssl.get(), 2) ||
1321 !ExpectFDs(ssl.get(), 2, 1)) {
1322 return false;
1323 }
David Benjamin5c0fb882016-06-14 14:03:51 -04001324
1325 // Test changing the write FD partway through.
1326 ssl.reset(SSL_new(ctx.get()));
1327 if (!ssl ||
1328 !SSL_set_fd(ssl.get(), 1) ||
1329 !SSL_set_wfd(ssl.get(), 2) ||
1330 !ExpectFDs(ssl.get(), 1, 2)) {
1331 return false;
1332 }
1333
1334 // Test a no-op change to the read FD partway through.
1335 ssl.reset(SSL_new(ctx.get()));
1336 if (!ssl ||
1337 !SSL_set_fd(ssl.get(), 1) ||
1338 !SSL_set_rfd(ssl.get(), 1) ||
1339 !ExpectFDs(ssl.get(), 1, 1)) {
1340 return false;
1341 }
1342
1343 // Test a no-op change to the write FD partway through.
1344 ssl.reset(SSL_new(ctx.get()));
1345 if (!ssl ||
1346 !SSL_set_fd(ssl.get(), 1) ||
1347 !SSL_set_wfd(ssl.get(), 1) ||
1348 !ExpectFDs(ssl.get(), 1, 1)) {
1349 return false;
1350 }
1351
1352 // ASan builds will implicitly test that the internal |BIO| reference-counting
1353 // is correct.
1354
1355 return true;
1356}
1357
Adam Langley09feb0f2016-07-11 14:07:19 -07001358} // namespace bssl
1359
David Benjamin1d128f32015-09-08 17:41:40 -04001360int main() {
David Benjamin7a1eefd2015-10-17 23:39:22 -04001361 CRYPTO_library_init();
David Benjaminbb0a17c2014-09-20 15:35:39 -04001362
Adam Langley09feb0f2016-07-11 14:07:19 -07001363 if (!bssl::TestCipherRules() ||
1364 !bssl::TestSSL_SESSIONEncoding(kOpenSSLSession) ||
1365 !bssl::TestSSL_SESSIONEncoding(kCustomSession) ||
1366 !bssl::TestSSL_SESSIONEncoding(kBoringSSLSession) ||
1367 !bssl::TestBadSSL_SESSIONEncoding(kBadSessionExtraField) ||
1368 !bssl::TestBadSSL_SESSIONEncoding(kBadSessionVersion) ||
1369 !bssl::TestBadSSL_SESSIONEncoding(kBadSessionTrailingData) ||
David Benjamin10e664b2016-06-20 22:20:47 -04001370 // TODO(svaldez): Update this when TLS 1.3 is enabled by default.
Adam Langley09feb0f2016-07-11 14:07:19 -07001371 !bssl::TestDefaultVersion(SSL3_VERSION, TLS1_2_VERSION, &TLS_method) ||
1372 !bssl::TestDefaultVersion(SSL3_VERSION, SSL3_VERSION, &SSLv3_method) ||
1373 !bssl::TestDefaultVersion(TLS1_VERSION, TLS1_VERSION, &TLSv1_method) ||
1374 !bssl::TestDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION,
1375 &TLSv1_1_method) ||
1376 !bssl::TestDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION,
1377 &TLSv1_2_method) ||
1378 !bssl::TestDefaultVersion(TLS1_1_VERSION, TLS1_2_VERSION, &DTLS_method) ||
1379 !bssl::TestDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION,
1380 &DTLSv1_method) ||
1381 !bssl::TestDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION,
1382 &DTLSv1_2_method) ||
1383 !bssl::TestCipherGetRFCName() ||
1384 !bssl::TestPaddingExtension() ||
1385 !bssl::TestClientCAList() ||
1386 !bssl::TestInternalSessionCache() ||
1387 !bssl::TestSequenceNumber(false /* TLS */) ||
1388 !bssl::TestSequenceNumber(true /* DTLS */) ||
1389 !bssl::TestOneSidedShutdown() ||
1390 !bssl::TestSetFD()) {
Brian Smith83a82982015-04-09 16:21:10 -10001391 ERR_print_errors_fp(stderr);
David Benjaminbb0a17c2014-09-20 15:35:39 -04001392 return 1;
1393 }
1394
David Benjamin2e521212014-07-16 14:37:51 -04001395 printf("PASS\n");
1396 return 0;
1397}