blob: 3533225afe27b6c500db85bced58b67f76412ff0 [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.]
56 */
57/* ====================================================================
58 * Copyright 2005 Nokia. All rights reserved.
59 *
60 * The portions of the attached software ("Contribution") is developed by
61 * Nokia Corporation and is licensed pursuant to the OpenSSL open source
62 * license.
63 *
64 * The Contribution, originally written by Mika Kousa and Pasi Eronen of
65 * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
66 * support (see RFC 4279) to OpenSSL.
67 *
68 * No patent licenses or other rights except those expressly stated in
69 * the OpenSSL open source license shall be deemed granted or received
70 * expressly, by implication, estoppel, or otherwise.
71 *
72 * No assurances are provided by Nokia that the Contribution does not
73 * infringe the patent or other intellectual property rights of any third
74 * party or that the license provides you with all the necessary rights
75 * to make use of the Contribution.
76 *
77 * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
78 * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
79 * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
80 * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
81 * OTHERWISE. */
82
David Benjamin9e4e01e2015-09-15 01:48:04 -040083#include <openssl/ssl.h>
84
David Benjamin83fd6b62014-10-19 04:33:38 -040085#include <limits.h>
David Benjamin89abaea2014-10-19 13:50:18 -040086#include <string.h>
Adam Langley95c29f32014-06-20 12:00:00 -070087
Steven Valdez84b5c002016-08-25 16:30:58 -040088#include <openssl/buf.h>
David Benjamin83fd6b62014-10-19 04:33:38 -040089#include <openssl/bytestring.h>
Adam Langley95c29f32014-06-20 12:00:00 -070090#include <openssl/err.h>
Brian Smith054e6822015-03-27 21:12:01 -100091#include <openssl/mem.h>
Adam Langley95c29f32014-06-20 12:00:00 -070092#include <openssl/x509.h>
93
David Benjamin17cf2cb2016-12-13 01:07:13 -050094#include "../crypto/internal.h"
David Benjamin2ee94aa2015-04-07 22:38:30 -040095#include "internal.h"
Adam Langley95c29f32014-06-20 12:00:00 -070096
Adam Langley95c29f32014-06-20 12:00:00 -070097
David Benjamin83fd6b62014-10-19 04:33:38 -040098/* An SSL_SESSION is serialized as the following ASN.1 structure:
99 *
100 * SSLSession ::= SEQUENCE {
David Benjamin7bb88bb2016-11-01 13:59:01 -0400101 * version INTEGER (1), -- session structure version
David Benjamin83fd6b62014-10-19 04:33:38 -0400102 * sslVersion INTEGER, -- protocol version number
103 * cipher OCTET STRING, -- two bytes long
104 * sessionID OCTET STRING,
105 * masterKey OCTET STRING,
David Benjamin5b7b09c2016-11-03 20:32:10 -0400106 * time [1] INTEGER, -- seconds since UNIX epoch
107 * timeout [2] INTEGER, -- in seconds
David Benjamin83fd6b62014-10-19 04:33:38 -0400108 * peer [3] Certificate OPTIONAL,
109 * sessionIDContext [4] OCTET STRING OPTIONAL,
110 * verifyResult [5] INTEGER OPTIONAL, -- one of X509_V_* codes
111 * hostName [6] OCTET STRING OPTIONAL,
112 * -- from server_name extension
David Benjamin83fd6b62014-10-19 04:33:38 -0400113 * pskIdentity [8] OCTET STRING OPTIONAL,
114 * ticketLifetimeHint [9] INTEGER OPTIONAL, -- client-only
115 * ticket [10] OCTET STRING OPTIONAL, -- client-only
116 * peerSHA256 [13] OCTET STRING OPTIONAL,
117 * originalHandshakeHash [14] OCTET STRING OPTIONAL,
118 * signedCertTimestampList [15] OCTET STRING OPTIONAL,
119 * -- contents of SCT extension
120 * ocspResponse [16] OCTET STRING OPTIONAL,
David Benjamin26416e92015-08-22 16:04:17 -0400121 * -- stapled OCSP response from the server
Adam Langley75712922014-10-10 16:23:43 -0700122 * extendedMasterSecret [17] BOOLEAN OPTIONAL,
David Benjamin4882a6c2016-12-11 02:48:12 -0500123 * groupID [18] INTEGER OPTIONAL,
124 * -- For historical reasons, for legacy DHE or
125 * -- static RSA ciphers, this field contains
126 * -- another value to be discarded.
David Benjamin26416e92015-08-22 16:04:17 -0400127 * certChain [19] SEQUENCE OF Certificate OPTIONAL,
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400128 * ticketAgeAdd [21] OCTET STRING OPTIONAL,
Adam Langley364f7a62016-12-12 10:51:00 -0800129 * isServer [22] BOOLEAN DEFAULT TRUE,
David Benjaminf1050fd2016-12-13 20:05:36 -0500130 * peerSignatureAlgorithm [23] INTEGER OPTIONAL,
Steven Valdez08b65f42016-12-07 15:29:45 -0500131 * ticketMaxEarlyData [24] INTEGER OPTIONAL,
David Benjamin17b30832017-01-28 14:00:32 -0500132 * authTimeout [25] INTEGER OPTIONAL, -- defaults to timeout
Steven Valdez27a9e6a2017-02-14 13:20:40 -0500133 * earlyALPN [26] OCTET STRING OPTIONAL,
David Benjamin83fd6b62014-10-19 04:33:38 -0400134 * }
135 *
David Benjamin688d8df2014-11-02 23:06:42 -0500136 * Note: historically this serialization has included other optional
David Benjamin17b30832017-01-28 14:00:32 -0500137 * fields. Their presence is currently treated as a parse error:
David Benjamin688d8df2014-11-02 23:06:42 -0500138 *
139 * keyArg [0] IMPLICIT OCTET STRING OPTIONAL,
140 * pskIdentityHint [7] OCTET STRING OPTIONAL,
141 * compressionMethod [11] OCTET STRING OPTIONAL,
Steven Valdez5b986082016-09-01 12:29:49 -0400142 * srpUsername [12] OCTET STRING OPTIONAL,
143 * ticketFlags [20] INTEGER OPTIONAL,
Adam Langleyc0fc7a12016-12-09 15:05:34 -0800144 */
David Benjamin83fd6b62014-10-19 04:33:38 -0400145
Adam Langley96c2a282015-06-02 14:16:44 -0700146static const unsigned kVersion = 1;
David Benjamin7f393f72015-10-17 12:36:12 -0400147
David Benjamin83fd6b62014-10-19 04:33:38 -0400148static const int kTimeTag =
149 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1;
150static const int kTimeoutTag =
151 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 2;
152static const int kPeerTag =
153 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3;
David Benjamin7f393f72015-10-17 12:36:12 -0400154static const int kSessionIDContextTag =
David Benjamin83fd6b62014-10-19 04:33:38 -0400155 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 4;
156static const int kVerifyResultTag =
157 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 5;
158static const int kHostNameTag =
159 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 6;
David Benjamin83fd6b62014-10-19 04:33:38 -0400160static const int kPSKIdentityTag =
161 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 8;
162static const int kTicketLifetimeHintTag =
163 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 9;
164static const int kTicketTag =
165 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 10;
166static const int kPeerSHA256Tag =
167 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 13;
168static const int kOriginalHandshakeHashTag =
169 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 14;
170static const int kSignedCertTimestampListTag =
171 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 15;
172static const int kOCSPResponseTag =
173 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 16;
Adam Langley75712922014-10-10 16:23:43 -0700174static const int kExtendedMasterSecretTag =
175 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 17;
David Benjamin4882a6c2016-12-11 02:48:12 -0500176static const int kGroupIDTag =
Sigbjorn Vik2b23d242015-06-29 15:07:26 +0200177 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 18;
David Benjamin26416e92015-08-22 16:04:17 -0400178static const int kCertChainTag =
179 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 19;
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400180static const int kTicketAgeAddTag =
181 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 21;
Adam Langley364f7a62016-12-12 10:51:00 -0800182static const int kIsServerTag =
183 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 22;
David Benjaminf1050fd2016-12-13 20:05:36 -0500184static const int kPeerSignatureAlgorithmTag =
185 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 23;
Steven Valdez08b65f42016-12-07 15:29:45 -0500186static const int kTicketMaxEarlyDataTag =
187 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 24;
David Benjamin17b30832017-01-28 14:00:32 -0500188static const int kAuthTimeoutTag =
189 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 25;
Steven Valdez27a9e6a2017-02-14 13:20:40 -0500190static const int kEarlyALPNTag =
191 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 26;
David Benjamin26416e92015-08-22 16:04:17 -0400192
David Benjamin14e2b502015-09-13 14:48:12 -0400193static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
David Benjamin3cac4502014-10-21 01:46:30 -0400194 size_t *out_len, int for_ticket) {
David Benjamin89abaea2014-10-19 13:50:18 -0400195 CBB cbb, session, child, child2;
Adam Langley95c29f32014-06-20 12:00:00 -0700196
David Benjaminf3a8b122014-12-25 23:11:49 -0500197 if (in == NULL || in->cipher == NULL) {
David Benjamin89abaea2014-10-19 13:50:18 -0400198 return 0;
199 }
Adam Langley95c29f32014-06-20 12:00:00 -0700200
David Benjamina8653202015-06-28 01:26:10 -0400201 CBB_zero(&cbb);
202 if (!CBB_init(&cbb, 0) ||
203 !CBB_add_asn1(&cbb, &session, CBS_ASN1_SEQUENCE) ||
David Benjamin7f393f72015-10-17 12:36:12 -0400204 !CBB_add_asn1_uint64(&session, kVersion) ||
David Benjamin89abaea2014-10-19 13:50:18 -0400205 !CBB_add_asn1_uint64(&session, in->ssl_version) ||
206 !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
David Benjaminf3a8b122014-12-25 23:11:49 -0500207 !CBB_add_u16(&child, (uint16_t)(in->cipher->id & 0xffff)) ||
David Benjamin89abaea2014-10-19 13:50:18 -0400208 !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
David Benjamin3cac4502014-10-21 01:46:30 -0400209 /* The session ID is irrelevant for a session ticket. */
210 !CBB_add_bytes(&child, in->session_id,
211 for_ticket ? 0 : in->session_id_length) ||
David Benjamin89abaea2014-10-19 13:50:18 -0400212 !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
213 !CBB_add_bytes(&child, in->master_key, in->master_key_length)) {
David Benjamin3570d732015-06-29 00:28:17 -0400214 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin89abaea2014-10-19 13:50:18 -0400215 goto err;
216 }
Adam Langley95c29f32014-06-20 12:00:00 -0700217
David Benjamin5b7b09c2016-11-03 20:32:10 -0400218 if (in->time < 0) {
219 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
220 goto err;
David Benjamin89abaea2014-10-19 13:50:18 -0400221 }
Adam Langley95c29f32014-06-20 12:00:00 -0700222
David Benjamin5b7b09c2016-11-03 20:32:10 -0400223 if (!CBB_add_asn1(&session, &child, kTimeTag) ||
224 !CBB_add_asn1_uint64(&child, in->time)) {
225 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
226 goto err;
227 }
David Benjamin0f31ac72016-11-02 23:05:14 -0400228
David Benjamin5b7b09c2016-11-03 20:32:10 -0400229 if (in->timeout < 0) {
230 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
231 goto err;
232 }
233
234 if (!CBB_add_asn1(&session, &child, kTimeoutTag) ||
235 !CBB_add_asn1_uint64(&child, in->timeout)) {
236 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
237 goto err;
David Benjamin89abaea2014-10-19 13:50:18 -0400238 }
Adam Langley95c29f32014-06-20 12:00:00 -0700239
Adam Langleyc0fc7a12016-12-09 15:05:34 -0800240 /* The peer certificate is only serialized if the SHA-256 isn't
241 * serialized instead. */
Adam Langley68e71242016-12-12 11:06:16 -0800242 if (sk_CRYPTO_BUFFER_num(in->certs) > 0 && !in->peer_sha256_valid) {
243 const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs, 0);
244 if (!CBB_add_asn1(&session, &child, kPeerTag) ||
245 !CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer),
246 CRYPTO_BUFFER_len(buffer))) {
David Benjamin3570d732015-06-29 00:28:17 -0400247 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin89abaea2014-10-19 13:50:18 -0400248 goto err;
249 }
David Benjamin89abaea2014-10-19 13:50:18 -0400250 }
Adam Langley95c29f32014-06-20 12:00:00 -0700251
David Benjamin89abaea2014-10-19 13:50:18 -0400252 /* Although it is OPTIONAL and usually empty, OpenSSL has
253 * historically always encoded the sid_ctx. */
254 if (!CBB_add_asn1(&session, &child, kSessionIDContextTag) ||
255 !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
256 !CBB_add_bytes(&child2, in->sid_ctx, in->sid_ctx_length)) {
David Benjamin3570d732015-06-29 00:28:17 -0400257 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin89abaea2014-10-19 13:50:18 -0400258 goto err;
259 }
Adam Langley95c29f32014-06-20 12:00:00 -0700260
David Benjamin89abaea2014-10-19 13:50:18 -0400261 if (in->verify_result != X509_V_OK) {
262 if (!CBB_add_asn1(&session, &child, kVerifyResultTag) ||
263 !CBB_add_asn1_uint64(&child, in->verify_result)) {
David Benjamin3570d732015-06-29 00:28:17 -0400264 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin89abaea2014-10-19 13:50:18 -0400265 goto err;
266 }
267 }
Adam Langley95c29f32014-06-20 12:00:00 -0700268
David Benjamin89abaea2014-10-19 13:50:18 -0400269 if (in->tlsext_hostname) {
270 if (!CBB_add_asn1(&session, &child, kHostNameTag) ||
271 !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
272 !CBB_add_bytes(&child2, (const uint8_t *)in->tlsext_hostname,
273 strlen(in->tlsext_hostname))) {
David Benjamin3570d732015-06-29 00:28:17 -0400274 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin89abaea2014-10-19 13:50:18 -0400275 goto err;
276 }
277 }
Adam Langley95c29f32014-06-20 12:00:00 -0700278
David Benjamin89abaea2014-10-19 13:50:18 -0400279 if (in->psk_identity) {
280 if (!CBB_add_asn1(&session, &child, kPSKIdentityTag) ||
281 !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
282 !CBB_add_bytes(&child2, (const uint8_t *)in->psk_identity,
283 strlen(in->psk_identity))) {
David Benjamin3570d732015-06-29 00:28:17 -0400284 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin89abaea2014-10-19 13:50:18 -0400285 goto err;
286 }
287 }
Adam Langley95c29f32014-06-20 12:00:00 -0700288
Martin Kreichgauerbaafa4a2016-08-09 10:18:40 -0700289 if (in->tlsext_tick_lifetime_hint > 0) {
David Benjamin89abaea2014-10-19 13:50:18 -0400290 if (!CBB_add_asn1(&session, &child, kTicketLifetimeHintTag) ||
Martin Kreichgauerbaafa4a2016-08-09 10:18:40 -0700291 !CBB_add_asn1_uint64(&child, in->tlsext_tick_lifetime_hint)) {
David Benjamin3570d732015-06-29 00:28:17 -0400292 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin89abaea2014-10-19 13:50:18 -0400293 goto err;
294 }
295 }
Adam Langley95c29f32014-06-20 12:00:00 -0700296
David Benjamin95d31822015-06-15 19:53:32 -0400297 if (in->tlsext_tick && !for_ticket) {
David Benjamin89abaea2014-10-19 13:50:18 -0400298 if (!CBB_add_asn1(&session, &child, kTicketTag) ||
299 !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
300 !CBB_add_bytes(&child2, in->tlsext_tick, in->tlsext_ticklen)) {
David Benjamin3570d732015-06-29 00:28:17 -0400301 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin89abaea2014-10-19 13:50:18 -0400302 goto err;
303 }
304 }
Adam Langley75872532014-06-20 12:00:00 -0700305
David Benjamin89abaea2014-10-19 13:50:18 -0400306 if (in->peer_sha256_valid) {
307 if (!CBB_add_asn1(&session, &child, kPeerSHA256Tag) ||
308 !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
309 !CBB_add_bytes(&child2, in->peer_sha256, sizeof(in->peer_sha256))) {
David Benjamin3570d732015-06-29 00:28:17 -0400310 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin89abaea2014-10-19 13:50:18 -0400311 goto err;
312 }
313 }
Adam Langley1258b6a2014-06-20 12:00:00 -0700314
David Benjamin89abaea2014-10-19 13:50:18 -0400315 if (in->original_handshake_hash_len > 0) {
316 if (!CBB_add_asn1(&session, &child, kOriginalHandshakeHashTag) ||
317 !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
318 !CBB_add_bytes(&child2, in->original_handshake_hash,
319 in->original_handshake_hash_len)) {
David Benjamin3570d732015-06-29 00:28:17 -0400320 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin89abaea2014-10-19 13:50:18 -0400321 goto err;
322 }
323 }
Adam Langley95c29f32014-06-20 12:00:00 -0700324
David Benjamin89abaea2014-10-19 13:50:18 -0400325 if (in->tlsext_signed_cert_timestamp_list_length > 0) {
326 if (!CBB_add_asn1(&session, &child, kSignedCertTimestampListTag) ||
327 !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
328 !CBB_add_bytes(&child2, in->tlsext_signed_cert_timestamp_list,
329 in->tlsext_signed_cert_timestamp_list_length)) {
David Benjamin3570d732015-06-29 00:28:17 -0400330 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin89abaea2014-10-19 13:50:18 -0400331 goto err;
332 }
333 }
HÃ¥vard Molland9169c962014-08-14 14:42:37 +0200334
David Benjamin89abaea2014-10-19 13:50:18 -0400335 if (in->ocsp_response_length > 0) {
336 if (!CBB_add_asn1(&session, &child, kOCSPResponseTag) ||
337 !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
338 !CBB_add_bytes(&child2, in->ocsp_response, in->ocsp_response_length)) {
David Benjamin3570d732015-06-29 00:28:17 -0400339 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin89abaea2014-10-19 13:50:18 -0400340 goto err;
341 }
342 }
David Benjamin6c7aed02014-08-27 16:42:38 -0400343
Adam Langley75712922014-10-10 16:23:43 -0700344 if (in->extended_master_secret) {
345 if (!CBB_add_asn1(&session, &child, kExtendedMasterSecretTag) ||
346 !CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
347 !CBB_add_u8(&child2, 0xff)) {
David Benjamin3570d732015-06-29 00:28:17 -0400348 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
Adam Langley75712922014-10-10 16:23:43 -0700349 goto err;
350 }
351 }
352
David Benjamin4882a6c2016-12-11 02:48:12 -0500353 if (in->group_id > 0 &&
354 (!CBB_add_asn1(&session, &child, kGroupIDTag) ||
355 !CBB_add_asn1_uint64(&child, in->group_id))) {
Sigbjorn Vik2b23d242015-06-29 15:07:26 +0200356 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
357 goto err;
358 }
359
David Benjamin26416e92015-08-22 16:04:17 -0400360 /* The certificate chain is only serialized if the leaf's SHA-256 isn't
361 * serialized instead. */
Adam Langley68e71242016-12-12 11:06:16 -0800362 if (in->certs != NULL &&
363 !in->peer_sha256_valid &&
364 sk_CRYPTO_BUFFER_num(in->certs) >= 2) {
David Benjamin26416e92015-08-22 16:04:17 -0400365 if (!CBB_add_asn1(&session, &child, kCertChainTag)) {
366 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
367 goto err;
368 }
Adam Langley68e71242016-12-12 11:06:16 -0800369 for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(in->certs); i++) {
370 const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs, i);
371 if (!CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer),
372 CRYPTO_BUFFER_len(buffer))) {
373 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin26416e92015-08-22 16:04:17 -0400374 goto err;
375 }
376 }
377 }
378
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400379 if (in->ticket_age_add_valid) {
380 if (!CBB_add_asn1(&session, &child, kTicketAgeAddTag) ||
381 !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
382 !CBB_add_u32(&child2, in->ticket_age_add)) {
383 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
384 goto err;
385 }
386 }
387
Adam Langley364f7a62016-12-12 10:51:00 -0800388 if (!in->is_server) {
389 if (!CBB_add_asn1(&session, &child, kIsServerTag) ||
390 !CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
391 !CBB_add_u8(&child2, 0x00)) {
392 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
393 goto err;
394 }
395 }
396
David Benjaminf1050fd2016-12-13 20:05:36 -0500397 if (in->peer_signature_algorithm != 0 &&
398 (!CBB_add_asn1(&session, &child, kPeerSignatureAlgorithmTag) ||
399 !CBB_add_asn1_uint64(&child, in->peer_signature_algorithm))) {
400 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
401 goto err;
402 }
403
Steven Valdez08b65f42016-12-07 15:29:45 -0500404 if (in->ticket_max_early_data != 0 &&
405 (!CBB_add_asn1(&session, &child, kTicketMaxEarlyDataTag) ||
406 !CBB_add_asn1_uint64(&child, in->ticket_max_early_data))) {
407 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
408 goto err;
409 }
410
David Benjamin17b30832017-01-28 14:00:32 -0500411 if (in->timeout != in->auth_timeout &&
412 (!CBB_add_asn1(&session, &child, kAuthTimeoutTag) ||
413 !CBB_add_asn1_uint64(&child, in->auth_timeout))) {
414 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
415 goto err;
416 }
417
Steven Valdez27a9e6a2017-02-14 13:20:40 -0500418 if (in->early_alpn) {
419 if (!CBB_add_asn1(&session, &child, kEarlyALPNTag) ||
420 !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
421 !CBB_add_bytes(&child2, (const uint8_t *)in->early_alpn,
422 in->early_alpn_len)) {
423 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
424 goto err;
425 }
426 }
427
David Benjamin3cac4502014-10-21 01:46:30 -0400428 if (!CBB_finish(&cbb, out_data, out_len)) {
David Benjamin3570d732015-06-29 00:28:17 -0400429 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin89abaea2014-10-19 13:50:18 -0400430 goto err;
431 }
David Benjamin3cac4502014-10-21 01:46:30 -0400432 return 1;
433
434 err:
435 CBB_cleanup(&cbb);
436 return 0;
437}
438
David Benjamin14e2b502015-09-13 14:48:12 -0400439int SSL_SESSION_to_bytes(const SSL_SESSION *in, uint8_t **out_data,
440 size_t *out_len) {
Steven Valdez84b5c002016-08-25 16:30:58 -0400441 if (in->not_resumable) {
442 /* If the caller has an unresumable session, e.g. if |SSL_get_session| were
443 * called on a TLS 1.3 or False Started connection, serialize with a
444 * placeholder value so it is not accidentally deserialized into a resumable
445 * one. */
446 static const char kNotResumableSession[] = "NOT RESUMABLE";
447
448 *out_len = strlen(kNotResumableSession);
449 *out_data = BUF_memdup(kNotResumableSession, *out_len);
450 if (*out_data == NULL) {
451 return 0;
452 }
453
454 return 1;
455 }
456
David Benjamin3cac4502014-10-21 01:46:30 -0400457 return SSL_SESSION_to_bytes_full(in, out_data, out_len, 0);
458}
459
David Benjamin14e2b502015-09-13 14:48:12 -0400460int SSL_SESSION_to_bytes_for_ticket(const SSL_SESSION *in, uint8_t **out_data,
David Benjamin3cac4502014-10-21 01:46:30 -0400461 size_t *out_len) {
462 return SSL_SESSION_to_bytes_full(in, out_data, out_len, 1);
463}
464
465int i2d_SSL_SESSION(SSL_SESSION *in, uint8_t **pp) {
466 uint8_t *out;
467 size_t len;
468
469 if (!SSL_SESSION_to_bytes(in, &out, &len)) {
470 return -1;
471 }
Adam Langley95c29f32014-06-20 12:00:00 -0700472
David Benjamin89abaea2014-10-19 13:50:18 -0400473 if (len > INT_MAX) {
474 OPENSSL_free(out);
David Benjamin3570d732015-06-29 00:28:17 -0400475 OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
David Benjamin89abaea2014-10-19 13:50:18 -0400476 return -1;
477 }
Adam Langley95c29f32014-06-20 12:00:00 -0700478
David Benjamin89abaea2014-10-19 13:50:18 -0400479 if (pp) {
David Benjamin17cf2cb2016-12-13 01:07:13 -0500480 OPENSSL_memcpy(*pp, out, len);
David Benjamin89abaea2014-10-19 13:50:18 -0400481 *pp += len;
482 }
483 OPENSSL_free(out);
Adam Langley95c29f32014-06-20 12:00:00 -0700484
David Benjamin89abaea2014-10-19 13:50:18 -0400485 return len;
David Benjamin89abaea2014-10-19 13:50:18 -0400486}
Adam Langley95c29f32014-06-20 12:00:00 -0700487
David Benjaminfd67aa82015-06-15 19:41:48 -0400488/* SSL_SESSION_parse_string gets an optional ASN.1 OCTET STRING
David Benjamin83fd6b62014-10-19 04:33:38 -0400489 * explicitly tagged with |tag| from |cbs| and saves it in |*out|. On
490 * entry, if |*out| is not NULL, it frees the existing contents. If
491 * the element was not found, it sets |*out| to NULL. It returns one
492 * on success, whether or not the element was found, and zero on
493 * decode error. */
David Benjaminfd67aa82015-06-15 19:41:48 -0400494static int SSL_SESSION_parse_string(CBS *cbs, char **out, unsigned tag) {
David Benjamin83fd6b62014-10-19 04:33:38 -0400495 CBS value;
496 int present;
497 if (!CBS_get_optional_asn1_octet_string(cbs, &value, &present, tag)) {
David Benjamin3570d732015-06-29 00:28:17 -0400498 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
David Benjamin83fd6b62014-10-19 04:33:38 -0400499 return 0;
500 }
501 if (present) {
502 if (CBS_contains_zero_byte(&value)) {
David Benjamin3570d732015-06-29 00:28:17 -0400503 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
David Benjamin83fd6b62014-10-19 04:33:38 -0400504 return 0;
505 }
506 if (!CBS_strdup(&value, out)) {
David Benjamin3570d732015-06-29 00:28:17 -0400507 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin83fd6b62014-10-19 04:33:38 -0400508 return 0;
509 }
David Benjamin2755a3e2015-04-22 16:17:58 -0400510 } else {
David Benjamin83fd6b62014-10-19 04:33:38 -0400511 OPENSSL_free(*out);
512 *out = NULL;
513 }
514 return 1;
515}
Adam Langley95c29f32014-06-20 12:00:00 -0700516
David Benjaminfd67aa82015-06-15 19:41:48 -0400517/* SSL_SESSION_parse_string gets an optional ASN.1 OCTET STRING
David Benjamin83fd6b62014-10-19 04:33:38 -0400518 * explicitly tagged with |tag| from |cbs| and stows it in |*out_ptr|
519 * and |*out_len|. If |*out_ptr| is not NULL, it frees the existing
520 * contents. On entry, if the element was not found, it sets
521 * |*out_ptr| to NULL. It returns one on success, whether or not the
522 * element was found, and zero on decode error. */
David Benjaminfd67aa82015-06-15 19:41:48 -0400523static int SSL_SESSION_parse_octet_string(CBS *cbs, uint8_t **out_ptr,
David Benjamin8be79a32015-08-23 01:37:36 -0400524 size_t *out_len, unsigned tag) {
David Benjamin83fd6b62014-10-19 04:33:38 -0400525 CBS value;
526 if (!CBS_get_optional_asn1_octet_string(cbs, &value, NULL, tag)) {
David Benjamin3570d732015-06-29 00:28:17 -0400527 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
David Benjamin83fd6b62014-10-19 04:33:38 -0400528 return 0;
529 }
530 if (!CBS_stow(&value, out_ptr, out_len)) {
David Benjamin3570d732015-06-29 00:28:17 -0400531 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin83fd6b62014-10-19 04:33:38 -0400532 return 0;
533 }
534 return 1;
535}
Adam Langley95c29f32014-06-20 12:00:00 -0700536
David Benjamin8be79a32015-08-23 01:37:36 -0400537/* SSL_SESSION_parse_bounded_octet_string parses an optional ASN.1 OCTET STRING
538 * explicitly tagged with |tag| of size at most |max_out|. */
539static int SSL_SESSION_parse_bounded_octet_string(
David Benjamin30c4c302016-12-07 22:35:24 -0500540 CBS *cbs, uint8_t *out, uint8_t *out_len, uint8_t max_out, unsigned tag) {
David Benjamin8be79a32015-08-23 01:37:36 -0400541 CBS value;
542 if (!CBS_get_optional_asn1_octet_string(cbs, &value, NULL, tag) ||
543 CBS_len(&value) > max_out) {
544 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
545 return 0;
546 }
David Benjamin17cf2cb2016-12-13 01:07:13 -0500547 OPENSSL_memcpy(out, CBS_data(&value), CBS_len(&value));
David Benjamin30c4c302016-12-07 22:35:24 -0500548 *out_len = (uint8_t)CBS_len(&value);
David Benjamin8be79a32015-08-23 01:37:36 -0400549 return 1;
550}
Adam Langley95c29f32014-06-20 12:00:00 -0700551
David Benjamin8be79a32015-08-23 01:37:36 -0400552static int SSL_SESSION_parse_long(CBS *cbs, long *out, unsigned tag,
553 long default_value) {
554 uint64_t value;
555 if (!CBS_get_optional_asn1_uint64(cbs, &value, tag,
556 (uint64_t)default_value) ||
557 value > LONG_MAX) {
558 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
559 return 0;
560 }
561 *out = (long)value;
562 return 1;
563}
564
565static int SSL_SESSION_parse_u32(CBS *cbs, uint32_t *out, unsigned tag,
566 uint32_t default_value) {
567 uint64_t value;
568 if (!CBS_get_optional_asn1_uint64(cbs, &value, tag,
569 (uint64_t)default_value) ||
570 value > 0xffffffff) {
571 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
572 return 0;
573 }
574 *out = (uint32_t)value;
575 return 1;
576}
577
David Benjaminf1050fd2016-12-13 20:05:36 -0500578static int SSL_SESSION_parse_u16(CBS *cbs, uint16_t *out, unsigned tag,
579 uint16_t default_value) {
580 uint64_t value;
581 if (!CBS_get_optional_asn1_uint64(cbs, &value, tag,
582 (uint64_t)default_value) ||
583 value > 0xffff) {
584 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
585 return 0;
586 }
587 *out = (uint16_t)value;
588 return 1;
589}
590
Adam Langley46db7af2017-02-01 15:49:37 -0800591SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
592 CRYPTO_BUFFER_POOL *pool) {
593 SSL_SESSION *ret = ssl_session_new(x509_method);
David Benjaminfd67aa82015-06-15 19:41:48 -0400594 if (ret == NULL) {
595 goto err;
David Benjamin83fd6b62014-10-19 04:33:38 -0400596 }
Adam Langley95c29f32014-06-20 12:00:00 -0700597
David Benjamin8be79a32015-08-23 01:37:36 -0400598 CBS session;
599 uint64_t version, ssl_version;
David Benjaminfd67aa82015-06-15 19:41:48 -0400600 if (!CBS_get_asn1(cbs, &session, CBS_ASN1_SEQUENCE) ||
David Benjamin83fd6b62014-10-19 04:33:38 -0400601 !CBS_get_asn1_uint64(&session, &version) ||
David Benjamin7f393f72015-10-17 12:36:12 -0400602 version != kVersion ||
David Benjamin8be79a32015-08-23 01:37:36 -0400603 !CBS_get_asn1_uint64(&session, &ssl_version)) {
David Benjamin3570d732015-06-29 00:28:17 -0400604 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
David Benjamin83fd6b62014-10-19 04:33:38 -0400605 goto err;
606 }
David Benjamin83fd6b62014-10-19 04:33:38 -0400607 ret->ssl_version = ssl_version;
Adam Langley95c29f32014-06-20 12:00:00 -0700608
David Benjamin8be79a32015-08-23 01:37:36 -0400609 CBS cipher;
David Benjaminf3a8b122014-12-25 23:11:49 -0500610 uint16_t cipher_value;
David Benjamin8be79a32015-08-23 01:37:36 -0400611 if (!CBS_get_asn1(&session, &cipher, CBS_ASN1_OCTETSTRING) ||
612 !CBS_get_u16(&cipher, &cipher_value) ||
613 CBS_len(&cipher) != 0) {
614 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
David Benjamin83fd6b62014-10-19 04:33:38 -0400615 goto err;
616 }
David Benjamina1c90a52015-05-30 17:03:14 -0400617 ret->cipher = SSL_get_cipher_by_value(cipher_value);
David Benjamin83fd6b62014-10-19 04:33:38 -0400618 if (ret->cipher == NULL) {
David Benjamin3570d732015-06-29 00:28:17 -0400619 OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_CIPHER);
David Benjamin83fd6b62014-10-19 04:33:38 -0400620 goto err;
621 }
Adam Langley95c29f32014-06-20 12:00:00 -0700622
David Benjamin8be79a32015-08-23 01:37:36 -0400623 CBS session_id, master_key;
624 if (!CBS_get_asn1(&session, &session_id, CBS_ASN1_OCTETSTRING) ||
625 CBS_len(&session_id) > SSL3_MAX_SSL_SESSION_ID_LENGTH ||
626 !CBS_get_asn1(&session, &master_key, CBS_ASN1_OCTETSTRING) ||
627 CBS_len(&master_key) > SSL_MAX_MASTER_KEY_LENGTH) {
David Benjamin3570d732015-06-29 00:28:17 -0400628 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
David Benjamin83fd6b62014-10-19 04:33:38 -0400629 goto err;
630 }
David Benjamin17cf2cb2016-12-13 01:07:13 -0500631 OPENSSL_memcpy(ret->session_id, CBS_data(&session_id), CBS_len(&session_id));
David Benjamin83fd6b62014-10-19 04:33:38 -0400632 ret->session_id_length = CBS_len(&session_id);
David Benjamin17cf2cb2016-12-13 01:07:13 -0500633 OPENSSL_memcpy(ret->master_key, CBS_data(&master_key), CBS_len(&master_key));
David Benjamin83fd6b62014-10-19 04:33:38 -0400634 ret->master_key_length = CBS_len(&master_key);
Adam Langley95c29f32014-06-20 12:00:00 -0700635
David Benjamin5b7b09c2016-11-03 20:32:10 -0400636 CBS child;
637 uint64_t time, timeout;
638 if (!CBS_get_asn1(&session, &child, kTimeTag) ||
639 !CBS_get_asn1_uint64(&child, &time) ||
640 time > LONG_MAX ||
641 !CBS_get_asn1(&session, &child, kTimeoutTag) ||
642 !CBS_get_asn1_uint64(&child, &timeout) ||
643 timeout > LONG_MAX) {
David Benjamin3570d732015-06-29 00:28:17 -0400644 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
David Benjamin83fd6b62014-10-19 04:33:38 -0400645 goto err;
646 }
Adam Langley95c29f32014-06-20 12:00:00 -0700647
David Benjamin5b7b09c2016-11-03 20:32:10 -0400648 ret->time = (long)time;
649 ret->timeout = (long)timeout;
650
David Benjamin8be79a32015-08-23 01:37:36 -0400651 CBS peer;
652 int has_peer;
Adam Langley68e71242016-12-12 11:06:16 -0800653 if (!CBS_get_optional_asn1(&session, &peer, &has_peer, kPeerTag) ||
654 (has_peer && CBS_len(&peer) == 0)) {
David Benjamin8be79a32015-08-23 01:37:36 -0400655 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
656 goto err;
657 }
Adam Langley68e71242016-12-12 11:06:16 -0800658 /* |peer| is processed with the certificate chain. */
Adam Langley95c29f32014-06-20 12:00:00 -0700659
David Benjamin8be79a32015-08-23 01:37:36 -0400660 if (!SSL_SESSION_parse_bounded_octet_string(
661 &session, ret->sid_ctx, &ret->sid_ctx_length, sizeof(ret->sid_ctx),
662 kSessionIDContextTag) ||
663 !SSL_SESSION_parse_long(&session, &ret->verify_result, kVerifyResultTag,
664 X509_V_OK) ||
665 !SSL_SESSION_parse_string(&session, &ret->tlsext_hostname,
666 kHostNameTag) ||
667 !SSL_SESSION_parse_string(&session, &ret->psk_identity,
668 kPSKIdentityTag) ||
Martin Kreichgauerbaafa4a2016-08-09 10:18:40 -0700669 !SSL_SESSION_parse_u32(&session, &ret->tlsext_tick_lifetime_hint,
David Benjamin8be79a32015-08-23 01:37:36 -0400670 kTicketLifetimeHintTag, 0) ||
671 !SSL_SESSION_parse_octet_string(&session, &ret->tlsext_tick,
672 &ret->tlsext_ticklen, kTicketTag)) {
David Benjamin83fd6b62014-10-19 04:33:38 -0400673 goto err;
674 }
Adam Langley95c29f32014-06-20 12:00:00 -0700675
David Benjamin8be79a32015-08-23 01:37:36 -0400676 if (CBS_peek_asn1_tag(&session, kPeerSHA256Tag)) {
David Benjamin5b7b09c2016-11-03 20:32:10 -0400677 CBS peer_sha256;
David Benjamin8be79a32015-08-23 01:37:36 -0400678 if (!CBS_get_asn1(&session, &child, kPeerSHA256Tag) ||
679 !CBS_get_asn1(&child, &peer_sha256, CBS_ASN1_OCTETSTRING) ||
680 CBS_len(&peer_sha256) != sizeof(ret->peer_sha256) ||
681 CBS_len(&child) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400682 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
David Benjamin83fd6b62014-10-19 04:33:38 -0400683 goto err;
684 }
David Benjamin17cf2cb2016-12-13 01:07:13 -0500685 OPENSSL_memcpy(ret->peer_sha256, CBS_data(&peer_sha256),
686 sizeof(ret->peer_sha256));
David Benjamin83fd6b62014-10-19 04:33:38 -0400687 ret->peer_sha256_valid = 1;
688 } else {
689 ret->peer_sha256_valid = 0;
690 }
Adam Langley95c29f32014-06-20 12:00:00 -0700691
David Benjamin8be79a32015-08-23 01:37:36 -0400692 if (!SSL_SESSION_parse_bounded_octet_string(
693 &session, ret->original_handshake_hash,
694 &ret->original_handshake_hash_len,
695 sizeof(ret->original_handshake_hash), kOriginalHandshakeHashTag) ||
696 !SSL_SESSION_parse_octet_string(
697 &session, &ret->tlsext_signed_cert_timestamp_list,
698 &ret->tlsext_signed_cert_timestamp_list_length,
699 kSignedCertTimestampListTag) ||
700 !SSL_SESSION_parse_octet_string(
701 &session, &ret->ocsp_response, &ret->ocsp_response_length,
702 kOCSPResponseTag)) {
703 goto err;
704 }
705
706 int extended_master_secret;
707 if (!CBS_get_optional_asn1_bool(&session, &extended_master_secret,
708 kExtendedMasterSecretTag,
709 0 /* default to false */)) {
David Benjamin3570d732015-06-29 00:28:17 -0400710 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
David Benjamin83fd6b62014-10-19 04:33:38 -0400711 goto err;
712 }
David Benjamin8be79a32015-08-23 01:37:36 -0400713 ret->extended_master_secret = !!extended_master_secret;
714
David Benjamin4882a6c2016-12-11 02:48:12 -0500715 uint32_t value;
716 if (!SSL_SESSION_parse_u32(&session, &value, kGroupIDTag, 0)) {
David Benjamin26416e92015-08-22 16:04:17 -0400717 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
718 goto err;
719 }
720
David Benjamin4882a6c2016-12-11 02:48:12 -0500721 /* Historically, the group_id field was used for key-exchange-specific
722 * information. Discard all but the group ID. */
723 if (ret->cipher->algorithm_mkey & (SSL_kRSA | SSL_kDHE)) {
724 value = 0;
725 }
726
727 if (value > 0xffff) {
728 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
729 goto err;
730 }
731 ret->group_id = (uint16_t)value;
732
David Benjamin26416e92015-08-22 16:04:17 -0400733 CBS cert_chain;
Adam Langley68e71242016-12-12 11:06:16 -0800734 CBS_init(&cert_chain, NULL, 0);
David Benjamin26416e92015-08-22 16:04:17 -0400735 int has_cert_chain;
736 if (!CBS_get_optional_asn1(&session, &cert_chain, &has_cert_chain,
Adam Langley68e71242016-12-12 11:06:16 -0800737 kCertChainTag) ||
738 (has_cert_chain && CBS_len(&cert_chain) == 0)) {
David Benjamin26416e92015-08-22 16:04:17 -0400739 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
740 goto err;
741 }
Adam Langley68e71242016-12-12 11:06:16 -0800742 if (has_cert_chain && !has_peer) {
743 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
744 goto err;
Adam Langley364f7a62016-12-12 10:51:00 -0800745 }
Adam Langley68e71242016-12-12 11:06:16 -0800746 if (has_peer || has_cert_chain) {
747 ret->certs = sk_CRYPTO_BUFFER_new_null();
748 if (ret->certs == NULL) {
David Benjamin26416e92015-08-22 16:04:17 -0400749 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
750 goto err;
751 }
Adam Langley68e71242016-12-12 11:06:16 -0800752
753 if (has_peer) {
Adam Langleyd519bf62016-12-12 11:16:44 -0800754 /* TODO(agl): this should use the |SSL_CTX|'s pool. */
Adam Langley46db7af2017-02-01 15:49:37 -0800755 CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&peer, pool);
Adam Langley68e71242016-12-12 11:06:16 -0800756 if (buffer == NULL ||
757 !sk_CRYPTO_BUFFER_push(ret->certs, buffer)) {
758 CRYPTO_BUFFER_free(buffer);
Adam Langleye8509092016-11-07 14:24:33 -0800759 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamin26416e92015-08-22 16:04:17 -0400760 goto err;
761 }
762 }
Adam Langley68e71242016-12-12 11:06:16 -0800763
764 while (CBS_len(&cert_chain) > 0) {
765 CBS cert;
766 if (!CBS_get_any_asn1_element(&cert_chain, &cert, NULL, NULL) ||
767 CBS_len(&cert) == 0) {
768 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
769 goto err;
770 }
771
Adam Langleyd519bf62016-12-12 11:16:44 -0800772 /* TODO(agl): this should use the |SSL_CTX|'s pool. */
Adam Langley46db7af2017-02-01 15:49:37 -0800773 CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&cert, pool);
Adam Langley68e71242016-12-12 11:06:16 -0800774 if (buffer == NULL ||
775 !sk_CRYPTO_BUFFER_push(ret->certs, buffer)) {
776 CRYPTO_BUFFER_free(buffer);
777 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
778 goto err;
779 }
780 }
781 }
782
Adam Langley46db7af2017-02-01 15:49:37 -0800783 if (!x509_method->session_cache_objects(ret)) {
Adam Langley68e71242016-12-12 11:06:16 -0800784 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
785 goto err;
David Benjamin26416e92015-08-22 16:04:17 -0400786 }
787
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400788 CBS age_add;
789 int age_add_present;
Steven Valdez5b986082016-09-01 12:29:49 -0400790 if (!CBS_get_optional_asn1_octet_string(&session, &age_add, &age_add_present,
Steven Valdez1e6f11a2016-07-27 11:10:52 -0400791 kTicketAgeAddTag) ||
792 (age_add_present &&
793 !CBS_get_u32(&age_add, &ret->ticket_age_add)) ||
794 CBS_len(&age_add) != 0) {
795 goto err;
796 }
797 ret->ticket_age_add_valid = age_add_present;
798
Adam Langley364f7a62016-12-12 10:51:00 -0800799 int is_server;
800 if (!CBS_get_optional_asn1_bool(&session, &is_server, kIsServerTag,
801 1 /* default to true */)) {
802 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
803 goto err;
804 }
805 /* TODO: in time we can include |is_server| for servers too, then we can
806 enforce that client and server sessions are never mixed up. */
807
808 ret->is_server = is_server;
809
David Benjaminf1050fd2016-12-13 20:05:36 -0500810 if (!SSL_SESSION_parse_u16(&session, &ret->peer_signature_algorithm,
811 kPeerSignatureAlgorithmTag, 0) ||
Steven Valdez08b65f42016-12-07 15:29:45 -0500812 !SSL_SESSION_parse_u32(&session, &ret->ticket_max_early_data,
813 kTicketMaxEarlyDataTag, 0) ||
David Benjamin17b30832017-01-28 14:00:32 -0500814 !SSL_SESSION_parse_long(&session, &ret->auth_timeout, kAuthTimeoutTag,
815 ret->timeout) ||
Steven Valdez27a9e6a2017-02-14 13:20:40 -0500816 !SSL_SESSION_parse_octet_string(&session, &ret->early_alpn,
817 &ret->early_alpn_len, kEarlyALPNTag) ||
David Benjaminf1050fd2016-12-13 20:05:36 -0500818 CBS_len(&session) != 0) {
David Benjamin8be79a32015-08-23 01:37:36 -0400819 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
820 goto err;
821 }
Adam Langley95c29f32014-06-20 12:00:00 -0700822
David Benjaminfd67aa82015-06-15 19:41:48 -0400823 return ret;
824
825err:
826 SSL_SESSION_free(ret);
827 return NULL;
828}
829
Adam Langley46db7af2017-02-01 15:49:37 -0800830SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, size_t in_len,
831 const SSL_CTX *ctx) {
David Benjaminfd67aa82015-06-15 19:41:48 -0400832 CBS cbs;
833 CBS_init(&cbs, in, in_len);
Adam Langley46db7af2017-02-01 15:49:37 -0800834 SSL_SESSION *ret = SSL_SESSION_parse(&cbs, ctx->x509_method, ctx->pool);
David Benjaminfd67aa82015-06-15 19:41:48 -0400835 if (ret == NULL) {
836 return NULL;
837 }
838 if (CBS_len(&cbs) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -0400839 OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
David Benjaminfd67aa82015-06-15 19:41:48 -0400840 SSL_SESSION_free(ret);
841 return NULL;
842 }
843 return ret;
844}