OpenSSL 1.1.1-pre2
This commit is contained in:
@@ -0,0 +1,1676 @@
|
||||
/*
|
||||
* Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "internal/nelem.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include "../ssl_locl.h"
|
||||
#include "statem_locl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
|
||||
static int final_renegotiate(SSL *s, unsigned int context, int sent);
|
||||
static int init_server_name(SSL *s, unsigned int context);
|
||||
static int final_server_name(SSL *s, unsigned int context, int sent);
|
||||
#ifndef OPENSSL_NO_EC
|
||||
static int final_ec_pt_formats(SSL *s, unsigned int context, int sent);
|
||||
#endif
|
||||
static int init_session_ticket(SSL *s, unsigned int context);
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
static int init_status_request(SSL *s, unsigned int context);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
static int init_npn(SSL *s, unsigned int context);
|
||||
#endif
|
||||
static int init_alpn(SSL *s, unsigned int context);
|
||||
static int final_alpn(SSL *s, unsigned int context, int sent);
|
||||
static int init_sig_algs_cert(SSL *s, unsigned int context);
|
||||
static int init_sig_algs(SSL *s, unsigned int context);
|
||||
static int init_certificate_authorities(SSL *s, unsigned int context);
|
||||
static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
|
||||
unsigned int context,
|
||||
X509 *x,
|
||||
size_t chainidx);
|
||||
static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
static int init_srp(SSL *s, unsigned int context);
|
||||
#endif
|
||||
static int init_etm(SSL *s, unsigned int context);
|
||||
static int init_ems(SSL *s, unsigned int context);
|
||||
static int final_ems(SSL *s, unsigned int context, int sent);
|
||||
static int init_psk_kex_modes(SSL *s, unsigned int context);
|
||||
#ifndef OPENSSL_NO_EC
|
||||
static int final_key_share(SSL *s, unsigned int context, int sent);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
static int init_srtp(SSL *s, unsigned int context);
|
||||
#endif
|
||||
static int final_sig_algs(SSL *s, unsigned int context, int sent);
|
||||
static int final_early_data(SSL *s, unsigned int context, int sent);
|
||||
static int final_maxfragmentlen(SSL *s, unsigned int context, int sent);
|
||||
static int init_post_handshake_auth(SSL *s, unsigned int context);
|
||||
|
||||
/* Structure to define a built-in extension */
|
||||
typedef struct extensions_definition_st {
|
||||
/* The defined type for the extension */
|
||||
unsigned int type;
|
||||
/*
|
||||
* The context that this extension applies to, e.g. what messages and
|
||||
* protocol versions
|
||||
*/
|
||||
unsigned int context;
|
||||
/*
|
||||
* Initialise extension before parsing. Always called for relevant contexts
|
||||
* even if extension not present
|
||||
*/
|
||||
int (*init)(SSL *s, unsigned int context);
|
||||
/* Parse extension sent from client to server */
|
||||
int (*parse_ctos)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
/* Parse extension send from server to client */
|
||||
int (*parse_stoc)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
/* Construct extension sent from server to client */
|
||||
EXT_RETURN (*construct_stoc)(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
/* Construct extension sent from client to server */
|
||||
EXT_RETURN (*construct_ctos)(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
/*
|
||||
* Finalise extension after parsing. Always called where an extensions was
|
||||
* initialised even if the extension was not present. |sent| is set to 1 if
|
||||
* the extension was seen, or 0 otherwise.
|
||||
*/
|
||||
int (*final)(SSL *s, unsigned int context, int sent);
|
||||
} EXTENSION_DEFINITION;
|
||||
|
||||
/*
|
||||
* Definitions of all built-in extensions. NOTE: Changes in the number or order
|
||||
* of these extensions should be mirrored with equivalent changes to the
|
||||
* indexes ( TLSEXT_IDX_* ) defined in ssl_locl.h.
|
||||
* Each extension has an initialiser, a client and
|
||||
* server side parser and a finaliser. The initialiser is called (if the
|
||||
* extension is relevant to the given context) even if we did not see the
|
||||
* extension in the message that we received. The parser functions are only
|
||||
* called if we see the extension in the message. The finalisers are always
|
||||
* called if the initialiser was called.
|
||||
* There are also server and client side constructor functions which are always
|
||||
* called during message construction if the extension is relevant for the
|
||||
* given context.
|
||||
* The initialisation, parsing, finalisation and construction functions are
|
||||
* always called in the order defined in this list. Some extensions may depend
|
||||
* on others having been processed first, so the order of this list is
|
||||
* significant.
|
||||
* The extension context is defined by a series of flags which specify which
|
||||
* messages the extension is relevant to. These flags also specify whether the
|
||||
* extension is relevant to a particular protocol or protocol version.
|
||||
*
|
||||
* TODO(TLS1.3): Make sure we have a test to check the consistency of these
|
||||
*
|
||||
* NOTE: WebSphere Application Server 7+ cannot handle empty extensions at
|
||||
* the end, keep these extensions before signature_algorithm.
|
||||
*/
|
||||
#define INVALID_EXTENSION { 0x10000, 0, NULL, NULL, NULL, NULL, NULL, NULL }
|
||||
static const EXTENSION_DEFINITION ext_defs[] = {
|
||||
{
|
||||
TLSEXT_TYPE_renegotiate,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_SSL3_ALLOWED | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
|
||||
NULL, tls_parse_ctos_renegotiate, tls_parse_stoc_renegotiate,
|
||||
tls_construct_stoc_renegotiate, tls_construct_ctos_renegotiate,
|
||||
final_renegotiate
|
||||
},
|
||||
{
|
||||
TLSEXT_TYPE_server_name,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
|
||||
init_server_name,
|
||||
tls_parse_ctos_server_name, tls_parse_stoc_server_name,
|
||||
tls_construct_stoc_server_name, tls_construct_ctos_server_name,
|
||||
final_server_name
|
||||
},
|
||||
{
|
||||
TLSEXT_TYPE_max_fragment_length,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
|
||||
NULL, tls_parse_ctos_maxfragmentlen, tls_parse_stoc_maxfragmentlen,
|
||||
tls_construct_stoc_maxfragmentlen, tls_construct_ctos_maxfragmentlen,
|
||||
final_maxfragmentlen
|
||||
},
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
{
|
||||
TLSEXT_TYPE_srp,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
|
||||
init_srp, tls_parse_ctos_srp, NULL, NULL, tls_construct_ctos_srp, NULL
|
||||
},
|
||||
#else
|
||||
INVALID_EXTENSION,
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_EC
|
||||
{
|
||||
TLSEXT_TYPE_ec_point_formats,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_2_AND_BELOW_ONLY,
|
||||
NULL, tls_parse_ctos_ec_pt_formats, tls_parse_stoc_ec_pt_formats,
|
||||
tls_construct_stoc_ec_pt_formats, tls_construct_ctos_ec_pt_formats,
|
||||
final_ec_pt_formats
|
||||
},
|
||||
{
|
||||
/*
|
||||
* "supported_groups" is spread across several specifications.
|
||||
* It was originally specified as "elliptic_curves" in RFC 4492,
|
||||
* and broadened to include named FFDH groups by RFC 7919.
|
||||
* Both RFCs 4492 and 7919 do not include a provision for the server
|
||||
* to indicate to the client the complete list of groups supported
|
||||
* by the server, with the server instead just indicating the
|
||||
* selected group for this connection in the ServerKeyExchange
|
||||
* message. TLS 1.3 adds a scheme for the server to indicate
|
||||
* to the client its list of supported groups in the
|
||||
* EncryptedExtensions message, but none of the relevant
|
||||
* specifications permit sending supported_groups in the ServerHello.
|
||||
* Nonetheless (possibly due to the close proximity to the
|
||||
* "ec_point_formats" extension, which is allowed in the ServerHello),
|
||||
* there are several servers that send this extension in the
|
||||
* ServerHello anyway. Up to and including the 1.1.0 release,
|
||||
* we did not check for the presence of nonpermitted extensions,
|
||||
* so to avoid a regression, we must permit this extension in the
|
||||
* TLS 1.2 ServerHello as well.
|
||||
*
|
||||
* Note that there is no tls_parse_stoc_supported_groups function,
|
||||
* so we do not perform any additional parsing, validation, or
|
||||
* processing on the server's group list -- this is just a minimal
|
||||
* change to preserve compatibility with these misbehaving servers.
|
||||
*/
|
||||
TLSEXT_TYPE_supported_groups,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
|
||||
| SSL_EXT_TLS1_2_SERVER_HELLO,
|
||||
NULL, tls_parse_ctos_supported_groups, NULL,
|
||||
tls_construct_stoc_supported_groups,
|
||||
tls_construct_ctos_supported_groups, NULL
|
||||
},
|
||||
#else
|
||||
INVALID_EXTENSION,
|
||||
INVALID_EXTENSION,
|
||||
#endif
|
||||
{
|
||||
TLSEXT_TYPE_session_ticket,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_2_AND_BELOW_ONLY,
|
||||
init_session_ticket, tls_parse_ctos_session_ticket,
|
||||
tls_parse_stoc_session_ticket, tls_construct_stoc_session_ticket,
|
||||
tls_construct_ctos_session_ticket, NULL
|
||||
},
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
{
|
||||
TLSEXT_TYPE_status_request,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_CERTIFICATE,
|
||||
init_status_request, tls_parse_ctos_status_request,
|
||||
tls_parse_stoc_status_request, tls_construct_stoc_status_request,
|
||||
tls_construct_ctos_status_request, NULL
|
||||
},
|
||||
#else
|
||||
INVALID_EXTENSION,
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
{
|
||||
TLSEXT_TYPE_next_proto_neg,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_2_AND_BELOW_ONLY,
|
||||
init_npn, tls_parse_ctos_npn, tls_parse_stoc_npn,
|
||||
tls_construct_stoc_next_proto_neg, tls_construct_ctos_npn, NULL
|
||||
},
|
||||
#else
|
||||
INVALID_EXTENSION,
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* Must appear in this list after server_name so that finalisation
|
||||
* happens after server_name callbacks
|
||||
*/
|
||||
TLSEXT_TYPE_application_layer_protocol_negotiation,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
|
||||
init_alpn, tls_parse_ctos_alpn, tls_parse_stoc_alpn,
|
||||
tls_construct_stoc_alpn, tls_construct_ctos_alpn, final_alpn
|
||||
},
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
{
|
||||
TLSEXT_TYPE_use_srtp,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS | SSL_EXT_DTLS_ONLY,
|
||||
init_srtp, tls_parse_ctos_use_srtp, tls_parse_stoc_use_srtp,
|
||||
tls_construct_stoc_use_srtp, tls_construct_ctos_use_srtp, NULL
|
||||
},
|
||||
#else
|
||||
INVALID_EXTENSION,
|
||||
#endif
|
||||
{
|
||||
TLSEXT_TYPE_encrypt_then_mac,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_2_AND_BELOW_ONLY,
|
||||
init_etm, tls_parse_ctos_etm, tls_parse_stoc_etm,
|
||||
tls_construct_stoc_etm, tls_construct_ctos_etm, NULL
|
||||
},
|
||||
#ifndef OPENSSL_NO_CT
|
||||
{
|
||||
TLSEXT_TYPE_signed_certificate_timestamp,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_CERTIFICATE,
|
||||
NULL,
|
||||
/*
|
||||
* No server side support for this, but can be provided by a custom
|
||||
* extension. This is an exception to the rule that custom extensions
|
||||
* cannot override built in ones.
|
||||
*/
|
||||
NULL, tls_parse_stoc_sct, NULL, tls_construct_ctos_sct, NULL
|
||||
},
|
||||
#else
|
||||
INVALID_EXTENSION,
|
||||
#endif
|
||||
{
|
||||
TLSEXT_TYPE_extended_master_secret,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_2_AND_BELOW_ONLY,
|
||||
init_ems, tls_parse_ctos_ems, tls_parse_stoc_ems,
|
||||
tls_construct_stoc_ems, tls_construct_ctos_ems, final_ems
|
||||
},
|
||||
{
|
||||
TLSEXT_TYPE_signature_algorithms_cert,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
|
||||
init_sig_algs_cert, tls_parse_ctos_sig_algs_cert,
|
||||
tls_parse_ctos_sig_algs_cert,
|
||||
/* We do not generate signature_algorithms_cert at present. */
|
||||
NULL, NULL, NULL
|
||||
},
|
||||
{
|
||||
TLSEXT_TYPE_post_handshake_auth,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ONLY,
|
||||
init_post_handshake_auth,
|
||||
tls_parse_ctos_post_handshake_auth, NULL,
|
||||
NULL, tls_construct_ctos_post_handshake_auth,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
TLSEXT_TYPE_signature_algorithms,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
|
||||
init_sig_algs, tls_parse_ctos_sig_algs,
|
||||
tls_parse_ctos_sig_algs, tls_construct_ctos_sig_algs,
|
||||
tls_construct_ctos_sig_algs, final_sig_algs
|
||||
},
|
||||
{
|
||||
TLSEXT_TYPE_supported_versions,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_SERVER_HELLO | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST
|
||||
| SSL_EXT_TLS_IMPLEMENTATION_ONLY,
|
||||
NULL,
|
||||
/* Processed inline as part of version selection */
|
||||
NULL, tls_parse_stoc_supported_versions,
|
||||
tls_construct_stoc_supported_versions,
|
||||
tls_construct_ctos_supported_versions, NULL
|
||||
},
|
||||
{
|
||||
TLSEXT_TYPE_psk_kex_modes,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS_IMPLEMENTATION_ONLY
|
||||
| SSL_EXT_TLS1_3_ONLY,
|
||||
init_psk_kex_modes, tls_parse_ctos_psk_kex_modes, NULL, NULL,
|
||||
tls_construct_ctos_psk_kex_modes, NULL
|
||||
},
|
||||
#ifndef OPENSSL_NO_EC
|
||||
{
|
||||
/*
|
||||
* Must be in this list after supported_groups. We need that to have
|
||||
* been parsed before we do this one.
|
||||
*/
|
||||
TLSEXT_TYPE_key_share,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST | SSL_EXT_TLS_IMPLEMENTATION_ONLY
|
||||
| SSL_EXT_TLS1_3_ONLY,
|
||||
NULL, tls_parse_ctos_key_share, tls_parse_stoc_key_share,
|
||||
tls_construct_stoc_key_share, tls_construct_ctos_key_share,
|
||||
final_key_share
|
||||
},
|
||||
#endif
|
||||
{
|
||||
/* Must be after key_share */
|
||||
TLSEXT_TYPE_cookie,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST
|
||||
| SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY,
|
||||
NULL, tls_parse_ctos_cookie, tls_parse_stoc_cookie,
|
||||
tls_construct_stoc_cookie, tls_construct_ctos_cookie, NULL
|
||||
},
|
||||
{
|
||||
/*
|
||||
* Special unsolicited ServerHello extension only used when
|
||||
* SSL_OP_CRYPTOPRO_TLSEXT_BUG is set
|
||||
*/
|
||||
TLSEXT_TYPE_cryptopro_bug,
|
||||
SSL_EXT_TLS1_2_SERVER_HELLO | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
|
||||
NULL, NULL, NULL, tls_construct_stoc_cryptopro_bug, NULL, NULL
|
||||
},
|
||||
{
|
||||
TLSEXT_TYPE_early_data,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
|
||||
| SSL_EXT_TLS1_3_NEW_SESSION_TICKET | SSL_EXT_TLS1_3_ONLY,
|
||||
NULL, tls_parse_ctos_early_data, tls_parse_stoc_early_data,
|
||||
tls_construct_stoc_early_data, tls_construct_ctos_early_data,
|
||||
final_early_data
|
||||
},
|
||||
{
|
||||
TLSEXT_TYPE_certificate_authorities,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST
|
||||
| SSL_EXT_TLS1_3_ONLY,
|
||||
init_certificate_authorities,
|
||||
tls_parse_certificate_authorities, tls_parse_certificate_authorities,
|
||||
tls_construct_certificate_authorities,
|
||||
tls_construct_certificate_authorities, NULL,
|
||||
},
|
||||
{
|
||||
/* Must be immediately before pre_shared_key */
|
||||
TLSEXT_TYPE_padding,
|
||||
SSL_EXT_CLIENT_HELLO,
|
||||
NULL,
|
||||
/* We send this, but don't read it */
|
||||
NULL, NULL, NULL, tls_construct_ctos_padding, NULL
|
||||
},
|
||||
{
|
||||
/* Required by the TLSv1.3 spec to always be the last extension */
|
||||
TLSEXT_TYPE_psk,
|
||||
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO
|
||||
| SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY,
|
||||
NULL, tls_parse_ctos_psk, tls_parse_stoc_psk, tls_construct_stoc_psk,
|
||||
tls_construct_ctos_psk, NULL
|
||||
}
|
||||
};
|
||||
|
||||
/* Check whether an extension's context matches the current context */
|
||||
static int validate_context(SSL *s, unsigned int extctx, unsigned int thisctx)
|
||||
{
|
||||
/* Check we're allowed to use this extension in this context */
|
||||
if ((thisctx & extctx) == 0)
|
||||
return 0;
|
||||
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
if ((extctx & SSL_EXT_TLS_ONLY) != 0)
|
||||
return 0;
|
||||
} else if ((extctx & SSL_EXT_DTLS_ONLY) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_validate_all_contexts(SSL *s, unsigned int thisctx, RAW_EXTENSION *exts)
|
||||
{
|
||||
size_t i, num_exts, builtin_num = OSSL_NELEM(ext_defs), offset;
|
||||
RAW_EXTENSION *thisext;
|
||||
unsigned int context;
|
||||
ENDPOINT role = ENDPOINT_BOTH;
|
||||
|
||||
if ((thisctx & SSL_EXT_CLIENT_HELLO) != 0)
|
||||
role = ENDPOINT_SERVER;
|
||||
else if ((thisctx & SSL_EXT_TLS1_2_SERVER_HELLO) != 0)
|
||||
role = ENDPOINT_CLIENT;
|
||||
|
||||
/* Calculate the number of extensions in the extensions list */
|
||||
num_exts = builtin_num + s->cert->custext.meths_count;
|
||||
|
||||
for (thisext = exts, i = 0; i < num_exts; i++, thisext++) {
|
||||
if (!thisext->present)
|
||||
continue;
|
||||
|
||||
if (i < builtin_num) {
|
||||
context = ext_defs[i].context;
|
||||
} else {
|
||||
custom_ext_method *meth = NULL;
|
||||
|
||||
meth = custom_ext_find(&s->cert->custext, role, thisext->type,
|
||||
&offset);
|
||||
if (!ossl_assert(meth != NULL))
|
||||
return 0;
|
||||
context = meth->context;
|
||||
}
|
||||
|
||||
if (!validate_context(s, context, thisctx))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify whether we are allowed to use the extension |type| in the current
|
||||
* |context|. Returns 1 to indicate the extension is allowed or unknown or 0 to
|
||||
* indicate the extension is not allowed. If returning 1 then |*found| is set to
|
||||
* the definition for the extension we found.
|
||||
*/
|
||||
static int verify_extension(SSL *s, unsigned int context, unsigned int type,
|
||||
custom_ext_methods *meths, RAW_EXTENSION *rawexlist,
|
||||
RAW_EXTENSION **found)
|
||||
{
|
||||
size_t i;
|
||||
size_t builtin_num = OSSL_NELEM(ext_defs);
|
||||
const EXTENSION_DEFINITION *thisext;
|
||||
|
||||
for (i = 0, thisext = ext_defs; i < builtin_num; i++, thisext++) {
|
||||
if (type == thisext->type) {
|
||||
if (!validate_context(s, thisext->context, context))
|
||||
return 0;
|
||||
|
||||
*found = &rawexlist[i];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the custom extensions */
|
||||
if (meths != NULL) {
|
||||
size_t offset = 0;
|
||||
ENDPOINT role = ENDPOINT_BOTH;
|
||||
custom_ext_method *meth = NULL;
|
||||
|
||||
if ((context & SSL_EXT_CLIENT_HELLO) != 0)
|
||||
role = ENDPOINT_SERVER;
|
||||
else if ((context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0)
|
||||
role = ENDPOINT_CLIENT;
|
||||
|
||||
meth = custom_ext_find(meths, role, type, &offset);
|
||||
if (meth != NULL) {
|
||||
if (!validate_context(s, meth->context, context))
|
||||
return 0;
|
||||
*found = &rawexlist[offset + builtin_num];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unknown extension. We allow it */
|
||||
*found = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the context defined for an extension |extctx| means whether
|
||||
* the extension is relevant for the current context |thisctx| or not. Returns
|
||||
* 1 if the extension is relevant for this context, and 0 otherwise
|
||||
*/
|
||||
int extension_is_relevant(SSL *s, unsigned int extctx, unsigned int thisctx)
|
||||
{
|
||||
int is_tls13;
|
||||
|
||||
/*
|
||||
* For HRR we haven't selected the version yet but we know it will be
|
||||
* TLSv1.3
|
||||
*/
|
||||
if ((thisctx & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0)
|
||||
is_tls13 = 1;
|
||||
else
|
||||
is_tls13 = SSL_IS_TLS13(s);
|
||||
|
||||
if ((SSL_IS_DTLS(s)
|
||||
&& (extctx & SSL_EXT_TLS_IMPLEMENTATION_ONLY) != 0)
|
||||
|| (s->version == SSL3_VERSION
|
||||
&& (extctx & SSL_EXT_SSL3_ALLOWED) == 0)
|
||||
|| (is_tls13 && (extctx & SSL_EXT_TLS1_2_AND_BELOW_ONLY) != 0)
|
||||
|| (!is_tls13 && (extctx & SSL_EXT_TLS1_3_ONLY) != 0)
|
||||
|| (s->hit && (extctx & SSL_EXT_IGNORE_ON_RESUMPTION) != 0))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gather a list of all the extensions from the data in |packet]. |context|
|
||||
* tells us which message this extension is for. The raw extension data is
|
||||
* stored in |*res| on success. We don't actually process the content of the
|
||||
* extensions yet, except to check their types. This function also runs the
|
||||
* initialiser functions for all known extensions if |init| is nonzero (whether
|
||||
* we have collected them or not). If successful the caller is responsible for
|
||||
* freeing the contents of |*res|.
|
||||
*
|
||||
* Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be
|
||||
* more than one extension of the same type in a ClientHello or ServerHello.
|
||||
* This function returns 1 if all extensions are unique and we have parsed their
|
||||
* types, and 0 if the extensions contain duplicates, could not be successfully
|
||||
* found, or an internal error occurred. We only check duplicates for
|
||||
* extensions that we know about. We ignore others.
|
||||
*/
|
||||
int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
|
||||
RAW_EXTENSION **res, size_t *len, int init)
|
||||
{
|
||||
PACKET extensions = *packet;
|
||||
size_t i = 0;
|
||||
size_t num_exts;
|
||||
custom_ext_methods *exts = &s->cert->custext;
|
||||
RAW_EXTENSION *raw_extensions = NULL;
|
||||
const EXTENSION_DEFINITION *thisexd;
|
||||
|
||||
*res = NULL;
|
||||
|
||||
/*
|
||||
* Initialise server side custom extensions. Client side is done during
|
||||
* construction of extensions for the ClientHello.
|
||||
*/
|
||||
if ((context & SSL_EXT_CLIENT_HELLO) != 0)
|
||||
custom_ext_init(&s->cert->custext);
|
||||
|
||||
num_exts = OSSL_NELEM(ext_defs) + (exts != NULL ? exts->meths_count : 0);
|
||||
raw_extensions = OPENSSL_zalloc(num_exts * sizeof(*raw_extensions));
|
||||
if (raw_extensions == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while (PACKET_remaining(&extensions) > 0) {
|
||||
unsigned int type, idx;
|
||||
PACKET extension;
|
||||
RAW_EXTENSION *thisex;
|
||||
|
||||
if (!PACKET_get_net_2(&extensions, &type) ||
|
||||
!PACKET_get_length_prefixed_2(&extensions, &extension)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* Verify this extension is allowed. We only check duplicates for
|
||||
* extensions that we recognise. We also have a special case for the
|
||||
* PSK extension, which must be the last one in the ClientHello.
|
||||
*/
|
||||
if (!verify_extension(s, context, type, exts, raw_extensions, &thisex)
|
||||
|| (thisex != NULL && thisex->present == 1)
|
||||
|| (type == TLSEXT_TYPE_psk
|
||||
&& (context & SSL_EXT_CLIENT_HELLO) != 0
|
||||
&& PACKET_remaining(&extensions) != 0)) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_COLLECT_EXTENSIONS,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
goto err;
|
||||
}
|
||||
idx = thisex - raw_extensions;
|
||||
/*-
|
||||
* Check that we requested this extension (if appropriate). Requests can
|
||||
* be sent in the ClientHello and CertificateRequest. Unsolicited
|
||||
* extensions can be sent in the NewSessionTicket. We only do this for
|
||||
* the built-in extensions. Custom extensions have a different but
|
||||
* similar check elsewhere.
|
||||
* Special cases:
|
||||
* - The HRR cookie extension is unsolicited
|
||||
* - The renegotiate extension is unsolicited (the client signals
|
||||
* support via an SCSV)
|
||||
* - The signed_certificate_timestamp extension can be provided by a
|
||||
* custom extension or by the built-in version. We let the extension
|
||||
* itself handle unsolicited response checks.
|
||||
*/
|
||||
if (idx < OSSL_NELEM(ext_defs)
|
||||
&& (context & (SSL_EXT_CLIENT_HELLO
|
||||
| SSL_EXT_TLS1_3_CERTIFICATE_REQUEST
|
||||
| SSL_EXT_TLS1_3_NEW_SESSION_TICKET)) == 0
|
||||
&& type != TLSEXT_TYPE_cookie
|
||||
&& type != TLSEXT_TYPE_renegotiate
|
||||
&& type != TLSEXT_TYPE_signed_certificate_timestamp
|
||||
&& (s->ext.extflags[idx] & SSL_EXT_FLAG_SENT) == 0) {
|
||||
SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
|
||||
SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_UNSOLICITED_EXTENSION);
|
||||
goto err;
|
||||
}
|
||||
if (thisex != NULL) {
|
||||
thisex->data = extension;
|
||||
thisex->present = 1;
|
||||
thisex->type = type;
|
||||
thisex->received_order = i++;
|
||||
if (s->ext.debug_cb)
|
||||
s->ext.debug_cb(s, !s->server, thisex->type,
|
||||
PACKET_data(&thisex->data),
|
||||
PACKET_remaining(&thisex->data),
|
||||
s->ext.debug_arg);
|
||||
}
|
||||
}
|
||||
|
||||
if (init) {
|
||||
/*
|
||||
* Initialise all known extensions relevant to this context,
|
||||
* whether we have found them or not
|
||||
*/
|
||||
for (thisexd = ext_defs, i = 0; i < OSSL_NELEM(ext_defs);
|
||||
i++, thisexd++) {
|
||||
if (thisexd->init != NULL && (thisexd->context & context) != 0
|
||||
&& extension_is_relevant(s, thisexd->context, context)
|
||||
&& !thisexd->init(s, context)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*res = raw_extensions;
|
||||
if (len != NULL)
|
||||
*len = num_exts;
|
||||
return 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(raw_extensions);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Runs the parser for a given extension with index |idx|. |exts| contains the
|
||||
* list of all parsed extensions previously collected by
|
||||
* tls_collect_extensions(). The parser is only run if it is applicable for the
|
||||
* given |context| and the parser has not already been run. If this is for a
|
||||
* Certificate message, then we also provide the parser with the relevant
|
||||
* Certificate |x| and its position in the |chainidx| with 0 being the first
|
||||
* Certificate. Returns 1 on success or 0 on failure. If an extension is not
|
||||
* present this counted as success.
|
||||
*/
|
||||
int tls_parse_extension(SSL *s, TLSEXT_INDEX idx, int context,
|
||||
RAW_EXTENSION *exts, X509 *x, size_t chainidx)
|
||||
{
|
||||
RAW_EXTENSION *currext = &exts[idx];
|
||||
int (*parser)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx) = NULL;
|
||||
|
||||
/* Skip if the extension is not present */
|
||||
if (!currext->present)
|
||||
return 1;
|
||||
|
||||
/* Skip if we've already parsed this extension */
|
||||
if (currext->parsed)
|
||||
return 1;
|
||||
|
||||
currext->parsed = 1;
|
||||
|
||||
if (idx < OSSL_NELEM(ext_defs)) {
|
||||
/* We are handling a built-in extension */
|
||||
const EXTENSION_DEFINITION *extdef = &ext_defs[idx];
|
||||
|
||||
/* Check if extension is defined for our protocol. If not, skip */
|
||||
if (!extension_is_relevant(s, extdef->context, context))
|
||||
return 1;
|
||||
|
||||
parser = s->server ? extdef->parse_ctos : extdef->parse_stoc;
|
||||
|
||||
if (parser != NULL)
|
||||
return parser(s, &currext->data, context, x, chainidx);
|
||||
|
||||
/*
|
||||
* If the parser is NULL we fall through to the custom extension
|
||||
* processing
|
||||
*/
|
||||
}
|
||||
|
||||
/* Parse custom extensions */
|
||||
return custom_ext_parse(s, context, currext->type,
|
||||
PACKET_data(&currext->data),
|
||||
PACKET_remaining(&currext->data),
|
||||
x, chainidx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse all remaining extensions that have not yet been parsed. Also calls the
|
||||
* finalisation for all extensions at the end if |fin| is nonzero, whether we
|
||||
* collected them or not. Returns 1 for success or 0 for failure. If we are
|
||||
* working on a Certificate message then we also pass the Certificate |x| and
|
||||
* its position in the |chainidx|, with 0 being the first certificate.
|
||||
*/
|
||||
int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts, X509 *x,
|
||||
size_t chainidx, int fin)
|
||||
{
|
||||
size_t i, numexts = OSSL_NELEM(ext_defs);
|
||||
const EXTENSION_DEFINITION *thisexd;
|
||||
|
||||
/* Calculate the number of extensions in the extensions list */
|
||||
numexts += s->cert->custext.meths_count;
|
||||
|
||||
/* Parse each extension in turn */
|
||||
for (i = 0; i < numexts; i++) {
|
||||
if (!tls_parse_extension(s, i, context, exts, x, chainidx)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (fin) {
|
||||
/*
|
||||
* Finalise all known extensions relevant to this context,
|
||||
* whether we have found them or not
|
||||
*/
|
||||
for (i = 0, thisexd = ext_defs; i < OSSL_NELEM(ext_defs);
|
||||
i++, thisexd++) {
|
||||
if (thisexd->final != NULL && (thisexd->context & context) != 0
|
||||
&& !thisexd->final(s, context, exts[i].present)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int should_add_extension(SSL *s, unsigned int extctx, unsigned int thisctx,
|
||||
int max_version)
|
||||
{
|
||||
/* Skip if not relevant for our context */
|
||||
if ((extctx & thisctx) == 0)
|
||||
return 0;
|
||||
|
||||
/* Check if this extension is defined for our protocol. If not, skip */
|
||||
if ((SSL_IS_DTLS(s) && (extctx & SSL_EXT_TLS_IMPLEMENTATION_ONLY) != 0)
|
||||
|| (s->version == SSL3_VERSION
|
||||
&& (extctx & SSL_EXT_SSL3_ALLOWED) == 0)
|
||||
|| (SSL_IS_TLS13(s)
|
||||
&& (extctx & SSL_EXT_TLS1_2_AND_BELOW_ONLY) != 0)
|
||||
|| (!SSL_IS_TLS13(s)
|
||||
&& (extctx & SSL_EXT_TLS1_3_ONLY) != 0
|
||||
&& (thisctx & SSL_EXT_CLIENT_HELLO) == 0)
|
||||
|| ((extctx & SSL_EXT_TLS1_3_ONLY) != 0
|
||||
&& (thisctx & SSL_EXT_CLIENT_HELLO) != 0
|
||||
&& (SSL_IS_DTLS(s) || max_version < TLS1_3_VERSION)))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct all the extensions relevant to the current |context| and write
|
||||
* them to |pkt|. If this is an extension for a Certificate in a Certificate
|
||||
* message, then |x| will be set to the Certificate we are handling, and
|
||||
* |chainidx| will indicate the position in the chainidx we are processing (with
|
||||
* 0 being the first in the chain). Returns 1 on success or 0 on failure. On a
|
||||
* failure construction stops at the first extension to fail to construct.
|
||||
*/
|
||||
int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
size_t i;
|
||||
int min_version, max_version = 0, reason;
|
||||
const EXTENSION_DEFINITION *thisexd;
|
||||
|
||||
if (!WPACKET_start_sub_packet_u16(pkt)
|
||||
/*
|
||||
* If extensions are of zero length then we don't even add the
|
||||
* extensions length bytes to a ClientHello/ServerHello
|
||||
* (for non-TLSv1.3).
|
||||
*/
|
||||
|| ((context &
|
||||
(SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0
|
||||
&& !WPACKET_set_flags(pkt,
|
||||
WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
|
||||
reason = ssl_get_min_max_version(s, &min_version, &max_version);
|
||||
if (reason != 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
|
||||
reason);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add custom extensions first */
|
||||
if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
|
||||
/* On the server side with initialise during ClientHello parsing */
|
||||
custom_ext_init(&s->cert->custext);
|
||||
}
|
||||
if (!custom_ext_add(s, context, pkt, x, chainidx, max_version)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0, thisexd = ext_defs; i < OSSL_NELEM(ext_defs); i++, thisexd++) {
|
||||
EXT_RETURN (*construct)(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN ret;
|
||||
|
||||
/* Skip if not relevant for our context */
|
||||
if (!should_add_extension(s, thisexd->context, context, max_version))
|
||||
continue;
|
||||
|
||||
construct = s->server ? thisexd->construct_stoc
|
||||
: thisexd->construct_ctos;
|
||||
|
||||
if (construct == NULL)
|
||||
continue;
|
||||
|
||||
ret = construct(s, pkt, context, x, chainidx);
|
||||
if (ret == EXT_RETURN_FAIL) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
if (ret == EXT_RETURN_SENT
|
||||
&& (context & (SSL_EXT_CLIENT_HELLO
|
||||
| SSL_EXT_TLS1_3_CERTIFICATE_REQUEST
|
||||
| SSL_EXT_TLS1_3_NEW_SESSION_TICKET)) != 0)
|
||||
s->ext.extflags[i] |= SSL_EXT_FLAG_SENT;
|
||||
}
|
||||
|
||||
if (!WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Built in extension finalisation and initialisation functions. All initialise
|
||||
* or finalise the associated extension type for the given |context|. For
|
||||
* finalisers |sent| is set to 1 if we saw the extension during parsing, and 0
|
||||
* otherwise. These functions return 1 on success or 0 on failure.
|
||||
*/
|
||||
|
||||
static int final_renegotiate(SSL *s, unsigned int context, int sent)
|
||||
{
|
||||
if (!s->server) {
|
||||
/*
|
||||
* Check if we can connect to a server that doesn't support safe
|
||||
* renegotiation
|
||||
*/
|
||||
if (!(s->options & SSL_OP_LEGACY_SERVER_CONNECT)
|
||||
&& !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
|
||||
&& !sent) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE,
|
||||
SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Need RI if renegotiating */
|
||||
if (s->renegotiate
|
||||
&& !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
|
||||
&& !sent) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE,
|
||||
SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int init_server_name(SSL *s, unsigned int context)
|
||||
{
|
||||
if (s->server)
|
||||
s->servername_done = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int final_server_name(SSL *s, unsigned int context, int sent)
|
||||
{
|
||||
int ret = SSL_TLSEXT_ERR_NOACK, discard;
|
||||
int altmp = SSL_AD_UNRECOGNIZED_NAME;
|
||||
int was_ticket = (SSL_get_options(s) & SSL_OP_NO_TICKET) == 0;
|
||||
|
||||
if (!ossl_assert(s->ctx != NULL) || !ossl_assert(s->session_ctx != NULL)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->ctx->ext.servername_cb != NULL)
|
||||
ret = s->ctx->ext.servername_cb(s, &altmp,
|
||||
s->ctx->ext.servername_arg);
|
||||
else if (s->session_ctx->ext.servername_cb != NULL)
|
||||
ret = s->session_ctx->ext.servername_cb(s, &altmp,
|
||||
s->session_ctx->ext.servername_arg);
|
||||
|
||||
if (!sent) {
|
||||
OPENSSL_free(s->session->ext.hostname);
|
||||
s->session->ext.hostname = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we switched contexts (whether here or in the client_hello callback),
|
||||
* move the sess_accept increment from the session_ctx to the new
|
||||
* context, to avoid the confusing situation of having sess_accept_good
|
||||
* exceed sess_accept (zero) for the new context.
|
||||
*/
|
||||
if (SSL_IS_FIRST_HANDSHAKE(s) && s->ctx != s->session_ctx) {
|
||||
CRYPTO_atomic_add(&s->ctx->stats.sess_accept, 1, &discard,
|
||||
s->ctx->lock);
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_accept, -1, &discard,
|
||||
s->session_ctx->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're expecting to send a ticket, and tickets were previously enabled,
|
||||
* and now tickets are disabled, then turn off expected ticket.
|
||||
* Also, if this is not a resumption, create a new session ID
|
||||
*/
|
||||
if (ret == SSL_TLSEXT_ERR_OK && s->ext.ticket_expected
|
||||
&& was_ticket && (SSL_get_options(s) & SSL_OP_NO_TICKET) != 0) {
|
||||
s->ext.ticket_expected = 0;
|
||||
if (!s->hit) {
|
||||
SSL_SESSION* ss = SSL_get_session(s);
|
||||
|
||||
if (ss != NULL) {
|
||||
OPENSSL_free(ss->ext.tick);
|
||||
ss->ext.tick = NULL;
|
||||
ss->ext.ticklen = 0;
|
||||
ss->ext.tick_lifetime_hint = 0;
|
||||
ss->ext.tick_age_add = 0;
|
||||
ss->ext.tick_identity = 0;
|
||||
if (!ssl_generate_session_id(s, ss)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (ret) {
|
||||
case SSL_TLSEXT_ERR_ALERT_FATAL:
|
||||
SSLfatal(s, altmp, SSL_F_FINAL_SERVER_NAME, SSL_R_CALLBACK_FAILED);
|
||||
return 0;
|
||||
|
||||
case SSL_TLSEXT_ERR_ALERT_WARNING:
|
||||
ssl3_send_alert(s, SSL3_AL_WARNING, altmp);
|
||||
return 1;
|
||||
|
||||
case SSL_TLSEXT_ERR_NOACK:
|
||||
s->servername_done = 0;
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
static int final_ec_pt_formats(SSL *s, unsigned int context, int sent)
|
||||
{
|
||||
unsigned long alg_k, alg_a;
|
||||
|
||||
if (s->server)
|
||||
return 1;
|
||||
|
||||
alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
|
||||
alg_a = s->s3->tmp.new_cipher->algorithm_auth;
|
||||
|
||||
/*
|
||||
* If we are client and using an elliptic curve cryptography cipher
|
||||
* suite, then if server returns an EC point formats lists extension it
|
||||
* must contain uncompressed.
|
||||
*/
|
||||
if (s->ext.ecpointformats != NULL
|
||||
&& s->ext.ecpointformats_len > 0
|
||||
&& s->session->ext.ecpointformats != NULL
|
||||
&& s->session->ext.ecpointformats_len > 0
|
||||
&& ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))) {
|
||||
/* we are using an ECC cipher */
|
||||
size_t i;
|
||||
unsigned char *list = s->session->ext.ecpointformats;
|
||||
|
||||
for (i = 0; i < s->session->ext.ecpointformats_len; i++) {
|
||||
if (*list++ == TLSEXT_ECPOINTFORMAT_uncompressed)
|
||||
break;
|
||||
}
|
||||
if (i == s->session->ext.ecpointformats_len) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EC_PT_FORMATS,
|
||||
SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int init_session_ticket(SSL *s, unsigned int context)
|
||||
{
|
||||
if (!s->server)
|
||||
s->ext.ticket_expected = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
static int init_status_request(SSL *s, unsigned int context)
|
||||
{
|
||||
if (s->server) {
|
||||
s->ext.status_type = TLSEXT_STATUSTYPE_nothing;
|
||||
} else {
|
||||
/*
|
||||
* Ensure we get sensible values passed to tlsext_status_cb in the event
|
||||
* that we don't receive a status message
|
||||
*/
|
||||
OPENSSL_free(s->ext.ocsp.resp);
|
||||
s->ext.ocsp.resp = NULL;
|
||||
s->ext.ocsp.resp_len = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
static int init_npn(SSL *s, unsigned int context)
|
||||
{
|
||||
s->s3->npn_seen = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int init_alpn(SSL *s, unsigned int context)
|
||||
{
|
||||
OPENSSL_free(s->s3->alpn_selected);
|
||||
s->s3->alpn_selected = NULL;
|
||||
s->s3->alpn_selected_len = 0;
|
||||
if (s->server) {
|
||||
OPENSSL_free(s->s3->alpn_proposed);
|
||||
s->s3->alpn_proposed = NULL;
|
||||
s->s3->alpn_proposed_len = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int final_alpn(SSL *s, unsigned int context, int sent)
|
||||
{
|
||||
if (!s->server && !sent && s->session->ext.alpn_selected != NULL)
|
||||
s->ext.early_data_ok = 0;
|
||||
|
||||
if (!s->server || !SSL_IS_TLS13(s))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* Call alpn_select callback if needed. Has to be done after SNI and
|
||||
* cipher negotiation (HTTP/2 restricts permitted ciphers). In TLSv1.3
|
||||
* we also have to do this before we decide whether to accept early_data.
|
||||
* In TLSv1.3 we've already negotiated our cipher so we do this call now.
|
||||
* For < TLSv1.3 we defer it until after cipher negotiation.
|
||||
*
|
||||
* On failure SSLfatal() already called.
|
||||
*/
|
||||
return tls_handle_alpn(s);
|
||||
}
|
||||
|
||||
static int init_sig_algs(SSL *s, unsigned int context)
|
||||
{
|
||||
/* Clear any signature algorithms extension received */
|
||||
OPENSSL_free(s->s3->tmp.peer_sigalgs);
|
||||
s->s3->tmp.peer_sigalgs = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int init_sig_algs_cert(SSL *s, unsigned int context)
|
||||
{
|
||||
/* Clear any signature algorithms extension received */
|
||||
OPENSSL_free(s->s3->tmp.peer_cert_sigalgs);
|
||||
s->s3->tmp.peer_cert_sigalgs = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
static int init_srp(SSL *s, unsigned int context)
|
||||
{
|
||||
OPENSSL_free(s->srp_ctx.login);
|
||||
s->srp_ctx.login = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int init_etm(SSL *s, unsigned int context)
|
||||
{
|
||||
s->ext.use_etm = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int init_ems(SSL *s, unsigned int context)
|
||||
{
|
||||
if (!s->server)
|
||||
s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int final_ems(SSL *s, unsigned int context, int sent)
|
||||
{
|
||||
if (!s->server && s->hit) {
|
||||
/*
|
||||
* Check extended master secret extension is consistent with
|
||||
* original session.
|
||||
*/
|
||||
if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) !=
|
||||
!(s->session->flags & SSL_SESS_FLAG_EXTMS)) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_EMS,
|
||||
SSL_R_INCONSISTENT_EXTMS);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int init_certificate_authorities(SSL *s, unsigned int context)
|
||||
{
|
||||
sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free);
|
||||
s->s3->tmp.peer_ca_names = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
|
||||
unsigned int context,
|
||||
X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
const STACK_OF(X509_NAME) *ca_sk = SSL_get0_CA_list(s);
|
||||
|
||||
if (ca_sk == NULL || sk_X509_NAME_num(ca_sk) == 0)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_certificate_authorities)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
if (!construct_ca_names(s, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
if (!WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
if (!parse_ca_names(s, pkt))
|
||||
return 0;
|
||||
if (PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
static int init_srtp(SSL *s, unsigned int context)
|
||||
{
|
||||
if (s->server)
|
||||
s->srtp_profile = NULL;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int final_sig_algs(SSL *s, unsigned int context, int sent)
|
||||
{
|
||||
if (!sent && SSL_IS_TLS13(s) && !s->hit) {
|
||||
SSLfatal(s, TLS13_AD_MISSING_EXTENSION, SSL_F_FINAL_SIG_ALGS,
|
||||
SSL_R_MISSING_SIGALGS_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
static int final_key_share(SSL *s, unsigned int context, int sent)
|
||||
{
|
||||
if (!SSL_IS_TLS13(s))
|
||||
return 1;
|
||||
|
||||
/* Nothing to do for key_share in an HRR */
|
||||
if ((context & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* If
|
||||
* we are a client
|
||||
* AND
|
||||
* we have no key_share
|
||||
* AND
|
||||
* (we are not resuming
|
||||
* OR the kex_mode doesn't allow non key_share resumes)
|
||||
* THEN
|
||||
* fail;
|
||||
*/
|
||||
if (!s->server
|
||||
&& !sent
|
||||
&& (!s->hit
|
||||
|| (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0)) {
|
||||
/* Nothing left we can do - just fail */
|
||||
SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_KEY_SHARE,
|
||||
SSL_R_NO_SUITABLE_KEY_SHARE);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* IF
|
||||
* we are a server
|
||||
* THEN
|
||||
* IF
|
||||
* we have a suitable key_share
|
||||
* THEN
|
||||
* IF
|
||||
* we are stateless AND we have no cookie
|
||||
* THEN
|
||||
* send a HelloRetryRequest
|
||||
* ELSE
|
||||
* IF
|
||||
* we didn't already send a HelloRetryRequest
|
||||
* AND
|
||||
* the client sent a key_share extension
|
||||
* AND
|
||||
* (we are not resuming
|
||||
* OR the kex_mode allows key_share resumes)
|
||||
* AND
|
||||
* a shared group exists
|
||||
* THEN
|
||||
* send a HelloRetryRequest
|
||||
* ELSE IF
|
||||
* we are not resuming
|
||||
* OR
|
||||
* the kex_mode doesn't allow non key_share resumes
|
||||
* THEN
|
||||
* fail
|
||||
* ELSE IF
|
||||
* we are stateless AND we have no cookie
|
||||
* THEN
|
||||
* send a HelloRetryRequest
|
||||
*/
|
||||
if (s->server) {
|
||||
if (s->s3->peer_tmp != NULL) {
|
||||
/* We have a suitable key_share */
|
||||
if ((s->s3->flags & TLS1_FLAGS_STATELESS) != 0
|
||||
&& !s->ext.cookieok) {
|
||||
if (!ossl_assert(s->hello_retry_request == SSL_HRR_NONE)) {
|
||||
/*
|
||||
* If we are stateless then we wouldn't know about any
|
||||
* previously sent HRR - so how can this be anything other
|
||||
* than 0?
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
s->hello_retry_request = SSL_HRR_PENDING;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
/* No suitable key_share */
|
||||
if (s->hello_retry_request == SSL_HRR_NONE && sent
|
||||
&& (!s->hit
|
||||
|| (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE)
|
||||
!= 0)) {
|
||||
const uint16_t *pgroups, *clntgroups;
|
||||
size_t num_groups, clnt_num_groups, i;
|
||||
unsigned int group_id = 0;
|
||||
|
||||
/* Check if a shared group exists */
|
||||
|
||||
/* Get the clients list of supported groups. */
|
||||
tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups);
|
||||
tls1_get_supported_groups(s, &pgroups, &num_groups);
|
||||
|
||||
/*
|
||||
* Find the first group we allow that is also in client's list
|
||||
*/
|
||||
for (i = 0; i < num_groups; i++) {
|
||||
group_id = pgroups[i];
|
||||
|
||||
if (check_in_list(s, group_id, clntgroups, clnt_num_groups,
|
||||
1))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i < num_groups) {
|
||||
/* A shared group exists so send a HelloRetryRequest */
|
||||
s->s3->group_id = group_id;
|
||||
s->hello_retry_request = SSL_HRR_PENDING;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (!s->hit
|
||||
|| (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0) {
|
||||
/* Nothing left we can do - just fail */
|
||||
SSLfatal(s, sent ? SSL_AD_HANDSHAKE_FAILURE
|
||||
: SSL_AD_MISSING_EXTENSION,
|
||||
SSL_F_FINAL_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((s->s3->flags & TLS1_FLAGS_STATELESS) != 0
|
||||
&& !s->ext.cookieok) {
|
||||
if (!ossl_assert(s->hello_retry_request == SSL_HRR_NONE)) {
|
||||
/*
|
||||
* If we are stateless then we wouldn't know about any
|
||||
* previously sent HRR - so how can this be anything other
|
||||
* than 0?
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
s->hello_retry_request = SSL_HRR_PENDING;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We have a key_share so don't send any more HelloRetryRequest
|
||||
* messages
|
||||
*/
|
||||
if (s->hello_retry_request == SSL_HRR_PENDING)
|
||||
s->hello_retry_request = SSL_HRR_COMPLETE;
|
||||
} else {
|
||||
/*
|
||||
* For a client side resumption with no key_share we need to generate
|
||||
* the handshake secret (otherwise this is done during key_share
|
||||
* processing).
|
||||
*/
|
||||
if (!sent && !tls13_generate_handshake_secret(s, NULL, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int init_psk_kex_modes(SSL *s, unsigned int context)
|
||||
{
|
||||
s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_NONE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
|
||||
size_t binderoffset, const unsigned char *binderin,
|
||||
unsigned char *binderout, SSL_SESSION *sess, int sign,
|
||||
int external)
|
||||
{
|
||||
EVP_PKEY *mackey = NULL;
|
||||
EVP_MD_CTX *mctx = NULL;
|
||||
unsigned char hash[EVP_MAX_MD_SIZE], binderkey[EVP_MAX_MD_SIZE];
|
||||
unsigned char finishedkey[EVP_MAX_MD_SIZE], tmpbinder[EVP_MAX_MD_SIZE];
|
||||
unsigned char tmppsk[EVP_MAX_MD_SIZE];
|
||||
unsigned char *early_secret, *psk;
|
||||
const char resumption_label[] = "res binder";
|
||||
const char external_label[] = "ext binder";
|
||||
const char nonce_label[] = "resumption";
|
||||
const char *label;
|
||||
size_t bindersize, labelsize, hashsize = EVP_MD_size(md);
|
||||
int ret = -1;
|
||||
int usepskfored = 0;
|
||||
|
||||
if (external
|
||||
&& s->early_data_state == SSL_EARLY_DATA_CONNECTING
|
||||
&& s->session->ext.max_early_data == 0
|
||||
&& sess->ext.max_early_data > 0)
|
||||
usepskfored = 1;
|
||||
|
||||
if (external) {
|
||||
label = external_label;
|
||||
labelsize = sizeof(external_label) - 1;
|
||||
} else {
|
||||
label = resumption_label;
|
||||
labelsize = sizeof(resumption_label) - 1;
|
||||
}
|
||||
|
||||
if (sess->master_key_length != hashsize) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
|
||||
SSL_R_BAD_PSK);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (external) {
|
||||
psk = sess->master_key;
|
||||
} else {
|
||||
psk = tmppsk;
|
||||
if (!tls13_hkdf_expand(s, md, sess->master_key,
|
||||
(const unsigned char *)nonce_label,
|
||||
sizeof(nonce_label) - 1, sess->ext.tick_nonce,
|
||||
sess->ext.tick_nonce_len, psk, hashsize)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate the early_secret. On the server side we've selected a PSK to
|
||||
* resume with (internal or external) so we always do this. On the client
|
||||
* side we do this for a non-external (i.e. resumption) PSK or external PSK
|
||||
* that will be used for early_data so that it is in place for sending early
|
||||
* data. For client side external PSK not being used for early_data we
|
||||
* generate it but store it away for later use.
|
||||
*/
|
||||
if (s->server || !external || usepskfored)
|
||||
early_secret = (unsigned char *)s->early_secret;
|
||||
else
|
||||
early_secret = (unsigned char *)sess->early_secret;
|
||||
if (!tls13_generate_secret(s, md, NULL, psk, hashsize, early_secret)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the handshake hash for the binder key...the messages so far are
|
||||
* empty!
|
||||
*/
|
||||
mctx = EVP_MD_CTX_new();
|
||||
if (mctx == NULL
|
||||
|| EVP_DigestInit_ex(mctx, md, NULL) <= 0
|
||||
|| EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Generate the binder key */
|
||||
if (!tls13_hkdf_expand(s, md, early_secret, (unsigned char *)label,
|
||||
labelsize, hash, hashsize, binderkey, hashsize)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Generate the finished key */
|
||||
if (!tls13_derive_finishedkey(s, md, binderkey, finishedkey, hashsize)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_DigestInit_ex(mctx, md, NULL) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a hash of the ClientHello up to the start of the binders. If we are
|
||||
* following a HelloRetryRequest then this includes the hash of the first
|
||||
* ClientHello and the HelloRetryRequest itself.
|
||||
*/
|
||||
if (s->hello_retry_request == SSL_HRR_PENDING) {
|
||||
size_t hdatalen;
|
||||
void *hdata;
|
||||
|
||||
hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
|
||||
if (hdatalen <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
|
||||
SSL_R_BAD_HANDSHAKE_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* For servers the handshake buffer data will include the second
|
||||
* ClientHello - which we don't want - so we need to take that bit off.
|
||||
*/
|
||||
if (s->server) {
|
||||
PACKET hashprefix, msg;
|
||||
|
||||
/* Find how many bytes are left after the first two messages */
|
||||
if (!PACKET_buf_init(&hashprefix, hdata, hdatalen)
|
||||
|| !PACKET_forward(&hashprefix, 1)
|
||||
|| !PACKET_get_length_prefixed_3(&hashprefix, &msg)
|
||||
|| !PACKET_forward(&hashprefix, 1)
|
||||
|| !PACKET_get_length_prefixed_3(&hashprefix, &msg)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
hdatalen -= PACKET_remaining(&hashprefix);
|
||||
}
|
||||
|
||||
if (EVP_DigestUpdate(mctx, hdata, hdatalen) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (EVP_DigestUpdate(mctx, msgstart, binderoffset) <= 0
|
||||
|| EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
mackey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, finishedkey, hashsize);
|
||||
if (mackey == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!sign)
|
||||
binderout = tmpbinder;
|
||||
|
||||
bindersize = hashsize;
|
||||
if (EVP_DigestSignInit(mctx, NULL, md, NULL, mackey) <= 0
|
||||
|| EVP_DigestSignUpdate(mctx, hash, hashsize) <= 0
|
||||
|| EVP_DigestSignFinal(mctx, binderout, &bindersize) <= 0
|
||||
|| bindersize != hashsize) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (sign) {
|
||||
ret = 1;
|
||||
} else {
|
||||
/* HMAC keys can't do EVP_DigestVerify* - use CRYPTO_memcmp instead */
|
||||
ret = (CRYPTO_memcmp(binderin, binderout, hashsize) == 0);
|
||||
if (!ret)
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PSK_DO_BINDER,
|
||||
SSL_R_BINDER_DOES_NOT_VERIFY);
|
||||
}
|
||||
|
||||
err:
|
||||
OPENSSL_cleanse(binderkey, sizeof(binderkey));
|
||||
OPENSSL_cleanse(finishedkey, sizeof(finishedkey));
|
||||
EVP_PKEY_free(mackey);
|
||||
EVP_MD_CTX_free(mctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int final_early_data(SSL *s, unsigned int context, int sent)
|
||||
{
|
||||
if (!sent)
|
||||
return 1;
|
||||
|
||||
if (!s->server) {
|
||||
if (context == SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
|
||||
&& sent
|
||||
&& !s->ext.early_data_ok) {
|
||||
/*
|
||||
* If we get here then the server accepted our early_data but we
|
||||
* later realised that it shouldn't have done (e.g. inconsistent
|
||||
* ALPN)
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EARLY_DATA,
|
||||
SSL_R_BAD_EARLY_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (s->max_early_data == 0
|
||||
|| !s->hit
|
||||
|| s->session->ext.tick_identity != 0
|
||||
|| s->early_data_state != SSL_EARLY_DATA_ACCEPTING
|
||||
|| !s->ext.early_data_ok
|
||||
|| s->hello_retry_request != SSL_HRR_NONE) {
|
||||
s->ext.early_data = SSL_EARLY_DATA_REJECTED;
|
||||
} else {
|
||||
s->ext.early_data = SSL_EARLY_DATA_ACCEPTED;
|
||||
|
||||
if (!tls13_change_cipher_state(s,
|
||||
SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_SERVER_READ)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int final_maxfragmentlen(SSL *s, unsigned int context, int sent)
|
||||
{
|
||||
/*
|
||||
* Session resumption on server-side with MFL extension active
|
||||
* BUT MFL extension packet was not resent (i.e. sent == 0)
|
||||
*/
|
||||
if (s->server && s->hit && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
|
||||
&& !sent ) {
|
||||
SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_MAXFRAGMENTLEN,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Current SSL buffer is lower than requested MFL */
|
||||
if (s->session && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
|
||||
&& s->max_send_fragment < GET_MAX_FRAGMENT_LENGTH(s->session))
|
||||
/* trigger a larger buffer reallocation */
|
||||
if (!ssl3_setup_buffers(s)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int init_post_handshake_auth(SSL *s, unsigned int context)
|
||||
{
|
||||
s->post_handshake_auth = SSL_PHA_NONE;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,1942 @@
|
||||
/*
|
||||
* Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/ocsp.h>
|
||||
#include "../ssl_locl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include "statem_locl.h"
|
||||
|
||||
EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
/* Add RI if renegotiating */
|
||||
if (!s->renegotiate)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, s->s3->previous_client_finished,
|
||||
s->s3->previous_client_finished_len)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
if (s->ext.hostname == NULL)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
/* Add TLS extension servername to the Client Hello message */
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
|
||||
/* Sub-packet for server_name extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
/* Sub-packet for servername list (always 1 hostname)*/
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u8(pkt, TLSEXT_NAMETYPE_host_name)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, s->ext.hostname,
|
||||
strlen(s->ext.hostname))
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
/* Push a Max Fragment Len extension into ClientHello */
|
||||
EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
if (s->ext.max_fragment_len_mode == TLSEXT_max_fragment_length_DISABLED)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
/* Add Max Fragment Length extension if client enabled it. */
|
||||
/*-
|
||||
* 4 bytes for this extension type and extension length
|
||||
* 1 byte for the Max Fragment Length code value.
|
||||
*/
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_max_fragment_length)
|
||||
/* Sub-packet for Max Fragment Length extension (1 byte) */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u8(pkt, s->ext.max_fragment_len_mode)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
/* Add SRP username if there is one */
|
||||
if (s->srp_ctx.login == NULL)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_srp)
|
||||
/* Sub-packet for SRP extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u8(pkt)
|
||||
/* login must not be zero...internal error if so */
|
||||
|| !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)
|
||||
|| !WPACKET_memcpy(pkt, s->srp_ctx.login,
|
||||
strlen(s->srp_ctx.login))
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SRP,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
static int use_ecc(SSL *s)
|
||||
{
|
||||
int i, end;
|
||||
unsigned long alg_k, alg_a;
|
||||
STACK_OF(SSL_CIPHER) *cipher_stack = NULL;
|
||||
|
||||
/* See if we support any ECC ciphersuites */
|
||||
if (s->version == SSL3_VERSION)
|
||||
return 0;
|
||||
|
||||
cipher_stack = SSL_get_ciphers(s);
|
||||
end = sk_SSL_CIPHER_num(cipher_stack);
|
||||
for (i = 0; i < end; i++) {
|
||||
const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
|
||||
|
||||
alg_k = c->algorithm_mkey;
|
||||
alg_a = c->algorithm_auth;
|
||||
if ((alg_k & (SSL_kECDHE | SSL_kECDHEPSK))
|
||||
|| (alg_a & SSL_aECDSA)
|
||||
|| c->min_tls >= TLS1_3_VERSION)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
const unsigned char *pformats;
|
||||
size_t num_formats;
|
||||
|
||||
if (!use_ecc(s))
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
/* Add TLS extension ECPointFormats to the ClientHello message */
|
||||
tls1_get_formatlist(s, &pformats, &num_formats);
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
|
||||
/* Sub-packet for formats extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, pformats, num_formats)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
const uint16_t *pgroups = NULL;
|
||||
size_t num_groups = 0, i;
|
||||
|
||||
if (!use_ecc(s))
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
/*
|
||||
* Add TLS extension supported_groups to the ClientHello message
|
||||
*/
|
||||
/* TODO(TLS1.3): Add support for DHE groups */
|
||||
tls1_get_supported_groups(s, &pgroups, &num_groups);
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups)
|
||||
/* Sub-packet for supported_groups extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
/* Copy curve ID if supported */
|
||||
for (i = 0; i < num_groups; i++) {
|
||||
uint16_t ctmp = pgroups[i];
|
||||
|
||||
if (tls_curve_allowed(s, ctmp, SSL_SECOP_CURVE_SUPPORTED)) {
|
||||
if (!WPACKET_put_bytes_u16(pkt, ctmp)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
size_t ticklen;
|
||||
|
||||
if (!tls_use_ticket(s))
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!s->new_session && s->session != NULL
|
||||
&& s->session->ext.tick != NULL
|
||||
&& s->session->ssl_version != TLS1_3_VERSION) {
|
||||
ticklen = s->session->ext.ticklen;
|
||||
} else if (s->session && s->ext.session_ticket != NULL
|
||||
&& s->ext.session_ticket->data != NULL) {
|
||||
ticklen = s->ext.session_ticket->length;
|
||||
s->session->ext.tick = OPENSSL_malloc(ticklen);
|
||||
if (s->session->ext.tick == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
memcpy(s->session->ext.tick,
|
||||
s->ext.session_ticket->data, ticklen);
|
||||
s->session->ext.ticklen = ticklen;
|
||||
} else {
|
||||
ticklen = 0;
|
||||
}
|
||||
|
||||
if (ticklen == 0 && s->ext.session_ticket != NULL &&
|
||||
s->ext.session_ticket->data == NULL)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick, ticklen)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_ctos_sig_algs(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
size_t salglen;
|
||||
const uint16_t *salg;
|
||||
|
||||
if (!SSL_CLIENT_USE_SIGALGS(s))
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
salglen = tls12_get_psigalgs(s, 1, &salg);
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signature_algorithms)
|
||||
/* Sub-packet for sig-algs extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
/* Sub-packet for the actual list */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !tls12_copy_sigalgs(s, pkt, salg, salglen)
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* This extension isn't defined for client Certificates */
|
||||
if (x != NULL)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
|
||||
/* Sub-packet for status request extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u8(pkt, TLSEXT_STATUSTYPE_ocsp)
|
||||
/* Sub-packet for the ids */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
for (i = 0; i < sk_OCSP_RESPID_num(s->ext.ocsp.ids); i++) {
|
||||
unsigned char *idbytes;
|
||||
OCSP_RESPID *id = sk_OCSP_RESPID_value(s->ext.ocsp.ids, i);
|
||||
int idlen = i2d_OCSP_RESPID(id, NULL);
|
||||
|
||||
if (idlen <= 0
|
||||
/* Sub-packet for an individual id */
|
||||
|| !WPACKET_sub_allocate_bytes_u16(pkt, idlen, &idbytes)
|
||||
|| i2d_OCSP_RESPID(id, &idbytes) != idlen) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
}
|
||||
if (!WPACKET_close(pkt)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
if (s->ext.ocsp.exts) {
|
||||
unsigned char *extbytes;
|
||||
int extlen = i2d_X509_EXTENSIONS(s->ext.ocsp.exts, NULL);
|
||||
|
||||
if (extlen < 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
if (!WPACKET_allocate_bytes(pkt, extlen, &extbytes)
|
||||
|| i2d_X509_EXTENSIONS(s->ext.ocsp.exts, &extbytes)
|
||||
!= extlen) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
}
|
||||
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
EXT_RETURN tls_construct_ctos_npn(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
if (s->ctx->ext.npn_select_cb == NULL || !SSL_IS_FIRST_HANDSHAKE(s))
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
/*
|
||||
* The client advertises an empty extension to indicate its support
|
||||
* for Next Protocol Negotiation
|
||||
*/
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_NPN,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
EXT_RETURN tls_construct_ctos_alpn(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
s->s3->alpn_sent = 0;
|
||||
|
||||
if (s->ext.alpn == NULL || !SSL_IS_FIRST_HANDSHAKE(s))
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt,
|
||||
TLSEXT_TYPE_application_layer_protocol_negotiation)
|
||||
/* Sub-packet ALPN extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, s->ext.alpn, s->ext.alpn_len)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_ALPN,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
s->s3->alpn_sent = 1;
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = SSL_get_srtp_profiles(s);
|
||||
int i, end;
|
||||
|
||||
if (clnt == NULL)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
|
||||
/* Sub-packet for SRTP extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
/* Sub-packet for the protection profile list */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
end = sk_SRTP_PROTECTION_PROFILE_num(clnt);
|
||||
for (i = 0; i < end; i++) {
|
||||
const SRTP_PROTECTION_PROFILE *prof =
|
||||
sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
|
||||
|
||||
if (prof == NULL || !WPACKET_put_bytes_u16(pkt, prof->id)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
}
|
||||
if (!WPACKET_close(pkt)
|
||||
/* Add an empty use_mki value */
|
||||
|| !WPACKET_put_bytes_u8(pkt, 0)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
EXT_RETURN tls_construct_ctos_etm(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
if (s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_ETM,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_CT
|
||||
EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
if (s->ct_validation_callback == NULL)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
/* Not defined for client Certificates */
|
||||
if (x != NULL)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signed_certificate_timestamp)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SCT,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
EXT_RETURN tls_construct_ctos_ems(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EMS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
int currv, min_version, max_version, reason;
|
||||
|
||||
reason = ssl_get_min_max_version(s, &min_version, &max_version);
|
||||
if (reason != 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, reason);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't include this if we can't negotiate TLSv1.3. We can do a straight
|
||||
* comparison here because we will never be called in DTLS.
|
||||
*/
|
||||
if (max_version < TLS1_3_VERSION)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u8(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(TLS1.3): There is some discussion on the TLS list as to whether
|
||||
* we should include versions <TLS1.2. For the moment we do. To be
|
||||
* reviewed later.
|
||||
*/
|
||||
for (currv = max_version; currv >= min_version; currv--) {
|
||||
/* TODO(TLS1.3): Remove this first if clause prior to release!! */
|
||||
if (currv == TLS1_3_VERSION) {
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
} else if (!WPACKET_put_bytes_u16(pkt, currv)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
}
|
||||
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a psk_kex_modes extension.
|
||||
*/
|
||||
EXT_RETURN tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
#ifndef OPENSSL_NO_TLS1_3
|
||||
int nodhe = s->options & SSL_OP_ALLOW_NO_DHE_KEX;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk_kex_modes)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u8(pkt)
|
||||
|| !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE_DHE)
|
||||
|| (nodhe && !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE))
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_KE_DHE;
|
||||
if (nodhe)
|
||||
s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE;
|
||||
#endif
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_TLS1_3
|
||||
static int add_key_share(SSL *s, WPACKET *pkt, unsigned int curve_id)
|
||||
{
|
||||
unsigned char *encoded_point = NULL;
|
||||
EVP_PKEY *key_share_key = NULL;
|
||||
size_t encodedlen;
|
||||
|
||||
if (s->s3->tmp.pkey != NULL) {
|
||||
if (!ossl_assert(s->hello_retry_request == SSL_HRR_PENDING)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Could happen if we got an HRR that wasn't requesting a new key_share
|
||||
*/
|
||||
key_share_key = s->s3->tmp.pkey;
|
||||
} else {
|
||||
key_share_key = ssl_generate_pkey_group(s, curve_id);
|
||||
if (key_share_key == NULL) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode the public key. */
|
||||
encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key,
|
||||
&encoded_point);
|
||||
if (encodedlen == 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Create KeyShareEntry */
|
||||
if (!WPACKET_put_bytes_u16(pkt, curve_id)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, encoded_point, encodedlen)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(TLS1.3): When changing to send more than one key_share we're
|
||||
* going to need to be able to save more than one EVP_PKEY. For now
|
||||
* we reuse the existing tmp.pkey
|
||||
*/
|
||||
s->s3->tmp.pkey = key_share_key;
|
||||
s->s3->group_id = curve_id;
|
||||
OPENSSL_free(encoded_point);
|
||||
|
||||
return 1;
|
||||
err:
|
||||
if (s->s3->tmp.pkey == NULL)
|
||||
EVP_PKEY_free(key_share_key);
|
||||
OPENSSL_free(encoded_point);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
#ifndef OPENSSL_NO_TLS1_3
|
||||
size_t i, num_groups = 0;
|
||||
const uint16_t *pgroups = NULL;
|
||||
uint16_t curve_id = 0;
|
||||
|
||||
/* key_share extension */
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
|
||||
/* Extension data sub-packet */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
/* KeyShare list sub-packet */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
tls1_get_supported_groups(s, &pgroups, &num_groups);
|
||||
|
||||
/*
|
||||
* TODO(TLS1.3): Make the number of key_shares sent configurable. For
|
||||
* now, just send one
|
||||
*/
|
||||
if (s->s3->group_id != 0) {
|
||||
curve_id = s->s3->group_id;
|
||||
} else {
|
||||
for (i = 0; i < num_groups; i++) {
|
||||
|
||||
if (!tls_curve_allowed(s, pgroups[i], SSL_SECOP_CURVE_SUPPORTED))
|
||||
continue;
|
||||
|
||||
curve_id = pgroups[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (curve_id == 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
|
||||
SSL_R_NO_SUITABLE_KEY_SHARE);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
if (!add_key_share(s, pkt, curve_id)) {
|
||||
/* SSLfatal() already called */
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_ctos_cookie(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
EXT_RETURN ret = EXT_RETURN_FAIL;
|
||||
|
||||
/* Should only be set if we've had an HRR */
|
||||
if (s->ext.tls13_cookie_len == 0)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_cookie)
|
||||
/* Extension data sub-packet */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, s->ext.tls13_cookie,
|
||||
s->ext.tls13_cookie_len)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_COOKIE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = EXT_RETURN_SENT;
|
||||
end:
|
||||
OPENSSL_free(s->ext.tls13_cookie);
|
||||
s->ext.tls13_cookie = NULL;
|
||||
s->ext.tls13_cookie_len = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
const unsigned char *id = NULL;
|
||||
size_t idlen = 0;
|
||||
SSL_SESSION *psksess = NULL;
|
||||
SSL_SESSION *edsess = NULL;
|
||||
const EVP_MD *handmd = NULL;
|
||||
|
||||
if (s->hello_retry_request == SSL_HRR_PENDING)
|
||||
handmd = ssl_handshake_md(s);
|
||||
|
||||
if (s->psk_use_session_cb != NULL
|
||||
&& (!s->psk_use_session_cb(s, handmd, &id, &idlen, &psksess)
|
||||
|| (psksess != NULL
|
||||
&& psksess->ssl_version != TLS1_3_VERSION))) {
|
||||
SSL_SESSION_free(psksess);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
|
||||
SSL_R_BAD_PSK);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
SSL_SESSION_free(s->psksession);
|
||||
s->psksession = psksess;
|
||||
if (psksess != NULL) {
|
||||
OPENSSL_free(s->psksession_id);
|
||||
s->psksession_id = OPENSSL_memdup(id, idlen);
|
||||
if (s->psksession_id == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
s->psksession_id_len = idlen;
|
||||
}
|
||||
|
||||
if (s->early_data_state != SSL_EARLY_DATA_CONNECTING
|
||||
|| (s->session->ext.max_early_data == 0
|
||||
&& (psksess == NULL || psksess->ext.max_early_data == 0))) {
|
||||
s->max_early_data = 0;
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
}
|
||||
edsess = s->session->ext.max_early_data != 0 ? s->session : psksess;
|
||||
s->max_early_data = edsess->ext.max_early_data;
|
||||
|
||||
if (edsess->ext.hostname != NULL) {
|
||||
if (s->ext.hostname == NULL
|
||||
|| (s->ext.hostname != NULL
|
||||
&& strcmp(s->ext.hostname, edsess->ext.hostname) != 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
|
||||
SSL_R_INCONSISTENT_EARLY_DATA_SNI);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((s->ext.alpn == NULL && edsess->ext.alpn_selected != NULL)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
|
||||
SSL_R_INCONSISTENT_EARLY_DATA_ALPN);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that we are offering an ALPN protocol consistent with the early
|
||||
* data.
|
||||
*/
|
||||
if (edsess->ext.alpn_selected != NULL) {
|
||||
PACKET prots, alpnpkt;
|
||||
int found = 0;
|
||||
|
||||
if (!PACKET_buf_init(&prots, s->ext.alpn, s->ext.alpn_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
while (PACKET_get_length_prefixed_1(&prots, &alpnpkt)) {
|
||||
if (PACKET_equal(&alpnpkt, edsess->ext.alpn_selected,
|
||||
edsess->ext.alpn_selected_len)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
|
||||
SSL_R_INCONSISTENT_EARLY_DATA_ALPN);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* We set this to rejected here. Later, if the server acknowledges the
|
||||
* extension, we set it to accepted.
|
||||
*/
|
||||
s->ext.early_data = SSL_EARLY_DATA_REJECTED;
|
||||
s->ext.early_data_ok = 1;
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
#define F5_WORKAROUND_MIN_MSG_LEN 0xff
|
||||
#define F5_WORKAROUND_MAX_MSG_LEN 0x200
|
||||
|
||||
/*
|
||||
* PSK pre binder overhead =
|
||||
* 2 bytes for TLSEXT_TYPE_psk
|
||||
* 2 bytes for extension length
|
||||
* 2 bytes for identities list length
|
||||
* 2 bytes for identity length
|
||||
* 4 bytes for obfuscated_ticket_age
|
||||
* 2 bytes for binder list length
|
||||
* 1 byte for binder length
|
||||
* The above excludes the number of bytes for the identity itself and the
|
||||
* subsequent binder bytes
|
||||
*/
|
||||
#define PSK_PRE_BINDER_OVERHEAD (2 + 2 + 2 + 2 + 4 + 2 + 1)
|
||||
|
||||
EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
unsigned char *padbytes;
|
||||
size_t hlen;
|
||||
|
||||
if ((s->options & SSL_OP_TLSEXT_PADDING) == 0)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
/*
|
||||
* Add padding to workaround bugs in F5 terminators. See RFC7685.
|
||||
* This code calculates the length of all extensions added so far but
|
||||
* excludes the PSK extension (because that MUST be written last). Therefore
|
||||
* this extension MUST always appear second to last.
|
||||
*/
|
||||
if (!WPACKET_get_total_written(pkt, &hlen)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PADDING,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're going to send a PSK then that will be written out after this
|
||||
* extension, so we need to calculate how long it is going to be.
|
||||
*/
|
||||
if (s->session->ssl_version == TLS1_3_VERSION
|
||||
&& s->session->ext.ticklen != 0
|
||||
&& s->session->cipher != NULL) {
|
||||
const EVP_MD *md = ssl_md(s->session->cipher->algorithm2);
|
||||
|
||||
if (md != NULL) {
|
||||
/*
|
||||
* Add the fixed PSK overhead, the identity length and the binder
|
||||
* length.
|
||||
*/
|
||||
hlen += PSK_PRE_BINDER_OVERHEAD + s->session->ext.ticklen
|
||||
+ EVP_MD_size(md);
|
||||
}
|
||||
}
|
||||
|
||||
if (hlen > F5_WORKAROUND_MIN_MSG_LEN && hlen < F5_WORKAROUND_MAX_MSG_LEN) {
|
||||
/* Calculate the amount of padding we need to add */
|
||||
hlen = F5_WORKAROUND_MAX_MSG_LEN - hlen;
|
||||
|
||||
/*
|
||||
* Take off the size of extension header itself (2 bytes for type and
|
||||
* 2 bytes for length bytes), but ensure that the extension is at least
|
||||
* 1 byte long so as not to have an empty extension last (WebSphere 7.x,
|
||||
* 8.x are intolerant of that condition)
|
||||
*/
|
||||
if (hlen > 4)
|
||||
hlen -= 4;
|
||||
else
|
||||
hlen = 1;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_padding)
|
||||
|| !WPACKET_sub_allocate_bytes_u16(pkt, hlen, &padbytes)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PADDING,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
memset(padbytes, 0, hlen);
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct the pre_shared_key extension
|
||||
*/
|
||||
EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
#ifndef OPENSSL_NO_TLS1_3
|
||||
uint32_t now, agesec, agems = 0;
|
||||
size_t reshashsize = 0, pskhashsize = 0, binderoffset, msglen;
|
||||
unsigned char *resbinder = NULL, *pskbinder = NULL, *msgstart = NULL;
|
||||
const EVP_MD *handmd = NULL, *mdres = NULL, *mdpsk = NULL;
|
||||
int dores = 0;
|
||||
|
||||
s->session->ext.tick_identity = TLSEXT_PSK_BAD_IDENTITY;
|
||||
|
||||
/*
|
||||
* Note: At this stage of the code we only support adding a single
|
||||
* resumption PSK. If we add support for multiple PSKs then the length
|
||||
* calculations in the padding extension will need to be adjusted.
|
||||
*/
|
||||
|
||||
/*
|
||||
* If this is an incompatible or new session then we have nothing to resume
|
||||
* so don't add this extension.
|
||||
*/
|
||||
if (s->session->ssl_version != TLS1_3_VERSION
|
||||
|| (s->session->ext.ticklen == 0 && s->psksession == NULL))
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (s->hello_retry_request == SSL_HRR_PENDING)
|
||||
handmd = ssl_handshake_md(s);
|
||||
|
||||
if (s->session->ext.ticklen != 0) {
|
||||
/* Get the digest associated with the ciphersuite in the session */
|
||||
if (s->session->cipher == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
mdres = ssl_md(s->session->cipher->algorithm2);
|
||||
if (mdres == NULL) {
|
||||
/*
|
||||
* Don't recognize this cipher so we can't use the session.
|
||||
* Ignore it
|
||||
*/
|
||||
goto dopsksess;
|
||||
}
|
||||
|
||||
if (s->hello_retry_request == SSL_HRR_PENDING && mdres != handmd) {
|
||||
/*
|
||||
* Selected ciphersuite hash does not match the hash for the session
|
||||
* so we can't use it.
|
||||
*/
|
||||
goto dopsksess;
|
||||
}
|
||||
|
||||
/*
|
||||
* Technically the C standard just says time() returns a time_t and says
|
||||
* nothing about the encoding of that type. In practice most
|
||||
* implementations follow POSIX which holds it as an integral type in
|
||||
* seconds since epoch. We've already made the assumption that we can do
|
||||
* this in multiple places in the code, so portability shouldn't be an
|
||||
* issue.
|
||||
*/
|
||||
now = (uint32_t)time(NULL);
|
||||
agesec = now - (uint32_t)s->session->time;
|
||||
/*
|
||||
* We calculate the age in seconds but the server may work in ms. Due to
|
||||
* rounding errors we could overestimate the age by up to 1s. It is
|
||||
* better to underestimate it. Otherwise, if the RTT is very short, when
|
||||
* the server calculates the age reported by the client it could be
|
||||
* bigger than the age calculated on the server - which should never
|
||||
* happen.
|
||||
*/
|
||||
if (agesec > 0)
|
||||
agesec--;
|
||||
|
||||
if (s->session->ext.tick_lifetime_hint < agesec) {
|
||||
/* Ticket is too old. Ignore it. */
|
||||
goto dopsksess;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate age in ms. We're just doing it to nearest second. Should be
|
||||
* good enough.
|
||||
*/
|
||||
agems = agesec * (uint32_t)1000;
|
||||
|
||||
if (agesec != 0 && agems / (uint32_t)1000 != agesec) {
|
||||
/*
|
||||
* Overflow. Shouldn't happen unless this is a *really* old session.
|
||||
* If so we just ignore it.
|
||||
*/
|
||||
goto dopsksess;
|
||||
}
|
||||
|
||||
/*
|
||||
* Obfuscate the age. Overflow here is fine, this addition is supposed
|
||||
* to be mod 2^32.
|
||||
*/
|
||||
agems += s->session->ext.tick_age_add;
|
||||
|
||||
reshashsize = EVP_MD_size(mdres);
|
||||
dores = 1;
|
||||
}
|
||||
|
||||
dopsksess:
|
||||
if (!dores && s->psksession == NULL)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (s->psksession != NULL) {
|
||||
mdpsk = ssl_md(s->psksession->cipher->algorithm2);
|
||||
if (mdpsk == NULL) {
|
||||
/*
|
||||
* Don't recognize this cipher so we can't use the session.
|
||||
* If this happens it's an application bug.
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
|
||||
SSL_R_BAD_PSK);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
if (s->hello_retry_request == SSL_HRR_PENDING && mdpsk != handmd) {
|
||||
/*
|
||||
* Selected ciphersuite hash does not match the hash for the PSK
|
||||
* session. This is an application bug.
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
|
||||
SSL_R_BAD_PSK);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
pskhashsize = EVP_MD_size(mdpsk);
|
||||
}
|
||||
|
||||
/* Create the extension, but skip over the binder for now */
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
if (dores) {
|
||||
if (!WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick,
|
||||
s->session->ext.ticklen)
|
||||
|| !WPACKET_put_bytes_u32(pkt, agems)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->psksession != NULL) {
|
||||
if (!WPACKET_sub_memcpy_u16(pkt, s->psksession_id,
|
||||
s->psksession_id_len)
|
||||
|| !WPACKET_put_bytes_u32(pkt, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!WPACKET_close(pkt)
|
||||
|| !WPACKET_get_total_written(pkt, &binderoffset)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| (dores
|
||||
&& !WPACKET_sub_allocate_bytes_u8(pkt, reshashsize, &resbinder))
|
||||
|| (s->psksession != NULL
|
||||
&& !WPACKET_sub_allocate_bytes_u8(pkt, pskhashsize, &pskbinder))
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_get_total_written(pkt, &msglen)
|
||||
/*
|
||||
* We need to fill in all the sub-packet lengths now so we can
|
||||
* calculate the HMAC of the message up to the binders
|
||||
*/
|
||||
|| !WPACKET_fill_lengths(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
msgstart = WPACKET_get_curr(pkt) - msglen;
|
||||
|
||||
if (dores
|
||||
&& tls_psk_do_binder(s, mdres, msgstart, binderoffset, NULL,
|
||||
resbinder, s->session, 1, 0) != 1) {
|
||||
/* SSLfatal() already called */
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
if (s->psksession != NULL
|
||||
&& tls_psk_do_binder(s, mdpsk, msgstart, binderoffset, NULL,
|
||||
pskbinder, s->psksession, 1, 1) != 1) {
|
||||
/* SSLfatal() already called */
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
if (dores)
|
||||
s->session->ext.tick_identity = 0;
|
||||
if (s->psksession != NULL)
|
||||
s->psksession->ext.tick_identity = (dores ? 1 : 0);
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
#else
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
#endif
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt,
|
||||
unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
#ifndef OPENSSL_NO_TLS1_3
|
||||
if (!s->pha_forced) {
|
||||
int i, n = 0;
|
||||
|
||||
/* check for cert, if present, we can do post-handshake auth */
|
||||
if (s->cert == NULL)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
for (i = 0; i < SSL_PKEY_NUM; i++) {
|
||||
if (s->cert->pkeys[i].x509 != NULL
|
||||
&& s->cert->pkeys[i].privatekey != NULL)
|
||||
n++;
|
||||
}
|
||||
|
||||
/* no identity certificates, so no extension */
|
||||
if (n == 0)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
}
|
||||
|
||||
/* construct extension - 0 length, no contents */
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_post_handshake_auth)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
s->post_handshake_auth = SSL_PHA_EXT_SENT;
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
#else
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parse the server's renegotiation binding and abort if it's not right
|
||||
*/
|
||||
int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
size_t expected_len = s->s3->previous_client_finished_len
|
||||
+ s->s3->previous_server_finished_len;
|
||||
size_t ilen;
|
||||
const unsigned char *data;
|
||||
|
||||
/* Check for logic errors */
|
||||
if (!ossl_assert(expected_len == 0
|
||||
|| s->s3->previous_client_finished_len != 0)
|
||||
|| !ossl_assert(expected_len == 0
|
||||
|| s->s3->previous_server_finished_len != 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse the length byte */
|
||||
if (!PACKET_get_1_len(pkt, &ilen)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
|
||||
SSL_R_RENEGOTIATION_ENCODING_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Consistency check */
|
||||
if (PACKET_remaining(pkt) != ilen) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
|
||||
SSL_R_RENEGOTIATION_ENCODING_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check that the extension matches */
|
||||
if (ilen != expected_len) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
|
||||
SSL_R_RENEGOTIATION_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!PACKET_get_bytes(pkt, &data, s->s3->previous_client_finished_len)
|
||||
|| memcmp(data, s->s3->previous_client_finished,
|
||||
s->s3->previous_client_finished_len) != 0) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
|
||||
SSL_R_RENEGOTIATION_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!PACKET_get_bytes(pkt, &data, s->s3->previous_server_finished_len)
|
||||
|| memcmp(data, s->s3->previous_server_finished,
|
||||
s->s3->previous_server_finished_len) != 0) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
|
||||
SSL_R_RENEGOTIATION_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
s->s3->send_connection_binding = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Parse the server's max fragment len extension packet */
|
||||
int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
unsigned int value;
|
||||
|
||||
if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* |value| should contains a valid max-fragment-length code. */
|
||||
if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
|
||||
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Must be the same value as client-configured one who was sent to server */
|
||||
/*-
|
||||
* RFC 6066: if a client receives a maximum fragment length negotiation
|
||||
* response that differs from the length it requested, ...
|
||||
* It must abort with SSL_AD_ILLEGAL_PARAMETER alert
|
||||
*/
|
||||
if (value != s->ext.max_fragment_len_mode) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
|
||||
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Maximum Fragment Length Negotiation succeeded.
|
||||
* The negotiated Maximum Fragment Length is binding now.
|
||||
*/
|
||||
s->session->ext.max_fragment_len_mode = value;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
if (s->ext.hostname == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (PACKET_remaining(pkt) > 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s->hit) {
|
||||
if (s->session->ext.hostname != NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname);
|
||||
if (s->session->ext.hostname == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
size_t ecpointformats_len;
|
||||
PACKET ecptformatlist;
|
||||
|
||||
if (!PACKET_as_length_prefixed_1(pkt, &ecptformatlist)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
if (!s->hit) {
|
||||
ecpointformats_len = PACKET_remaining(&ecptformatlist);
|
||||
if (ecpointformats_len == 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, SSL_R_BAD_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->session->ext.ecpointformats_len = 0;
|
||||
OPENSSL_free(s->session->ext.ecpointformats);
|
||||
s->session->ext.ecpointformats = OPENSSL_malloc(ecpointformats_len);
|
||||
if (s->session->ext.ecpointformats == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->session->ext.ecpointformats_len = ecpointformats_len;
|
||||
|
||||
if (!PACKET_copy_bytes(&ecptformatlist,
|
||||
s->session->ext.ecpointformats,
|
||||
ecpointformats_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
if (s->ext.session_ticket_cb != NULL &&
|
||||
!s->ext.session_ticket_cb(s, PACKET_data(pkt),
|
||||
PACKET_remaining(pkt),
|
||||
s->ext.session_ticket_cb_arg)) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!tls_use_ticket(s)) {
|
||||
SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
|
||||
SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
if (PACKET_remaining(pkt) > 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->ext.ticket_expected = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
/*
|
||||
* MUST only be sent if we've requested a status
|
||||
* request message. In TLS <= 1.2 it must also be empty.
|
||||
*/
|
||||
if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) {
|
||||
SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
|
||||
SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
if (!SSL_IS_TLS13(s) && PACKET_remaining(pkt) > 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
/* We only know how to handle this if it's for the first Certificate in
|
||||
* the chain. We ignore any other responses.
|
||||
*/
|
||||
if (chainidx != 0)
|
||||
return 1;
|
||||
|
||||
/* SSLfatal() already called */
|
||||
return tls_process_cert_status_body(s, pkt);
|
||||
}
|
||||
|
||||
/* Set flag to expect CertificateStatus message */
|
||||
s->ext.status_expected = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef OPENSSL_NO_CT
|
||||
int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
/*
|
||||
* Only take it if we asked for it - i.e if there is no CT validation
|
||||
* callback set, then a custom extension MAY be processing it, so we
|
||||
* need to let control continue to flow to that.
|
||||
*/
|
||||
if (s->ct_validation_callback != NULL) {
|
||||
size_t size = PACKET_remaining(pkt);
|
||||
|
||||
/* Simply copy it off for later processing */
|
||||
OPENSSL_free(s->ext.scts);
|
||||
s->ext.scts = NULL;
|
||||
|
||||
s->ext.scts_len = (uint16_t)size;
|
||||
if (size > 0) {
|
||||
s->ext.scts = OPENSSL_malloc(size);
|
||||
if (s->ext.scts == NULL
|
||||
|| !PACKET_copy_bytes(pkt, s->ext.scts, size)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SCT,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ENDPOINT role = (context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0
|
||||
? ENDPOINT_CLIENT : ENDPOINT_BOTH;
|
||||
|
||||
/*
|
||||
* If we didn't ask for it then there must be a custom extension,
|
||||
* otherwise this is unsolicited.
|
||||
*/
|
||||
if (custom_ext_find(&s->cert->custext, role,
|
||||
TLSEXT_TYPE_signed_certificate_timestamp,
|
||||
NULL) == NULL) {
|
||||
SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_SCT,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!custom_ext_parse(s, context,
|
||||
TLSEXT_TYPE_signed_certificate_timestamp,
|
||||
PACKET_data(pkt), PACKET_remaining(pkt),
|
||||
x, chainidx)) {
|
||||
/* SSLfatal already called */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
/*
|
||||
* ssl_next_proto_validate validates a Next Protocol Negotiation block. No
|
||||
* elements of zero length are allowed and the set of elements must exactly
|
||||
* fill the length of the block. Returns 1 on success or 0 on failure.
|
||||
*/
|
||||
static int ssl_next_proto_validate(SSL *s, PACKET *pkt)
|
||||
{
|
||||
PACKET tmp_protocol;
|
||||
|
||||
while (PACKET_remaining(pkt)) {
|
||||
if (!PACKET_get_length_prefixed_1(pkt, &tmp_protocol)
|
||||
|| PACKET_remaining(&tmp_protocol) == 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_NEXT_PROTO_VALIDATE,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
unsigned char *selected;
|
||||
unsigned char selected_len;
|
||||
PACKET tmppkt;
|
||||
|
||||
/* Check if we are in a renegotiation. If so ignore this extension */
|
||||
if (!SSL_IS_FIRST_HANDSHAKE(s))
|
||||
return 1;
|
||||
|
||||
/* We must have requested it. */
|
||||
if (s->ctx->ext.npn_select_cb == NULL) {
|
||||
SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_NPN,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The data must be valid */
|
||||
tmppkt = *pkt;
|
||||
if (!ssl_next_proto_validate(s, &tmppkt)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
if (s->ctx->ext.npn_select_cb(s, &selected, &selected_len,
|
||||
PACKET_data(pkt),
|
||||
PACKET_remaining(pkt),
|
||||
s->ctx->ext.npn_select_cb_arg) !=
|
||||
SSL_TLSEXT_ERR_OK) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_STOC_NPN,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Could be non-NULL if server has sent multiple NPN extensions in
|
||||
* a single Serverhello
|
||||
*/
|
||||
OPENSSL_free(s->ext.npn);
|
||||
s->ext.npn = OPENSSL_malloc(selected_len);
|
||||
if (s->ext.npn == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_NPN,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(s->ext.npn, selected, selected_len);
|
||||
s->ext.npn_len = selected_len;
|
||||
s->s3->npn_seen = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
/* We must have requested it. */
|
||||
if (!s->s3->alpn_sent) {
|
||||
SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_ALPN,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
/*-
|
||||
* The extension data consists of:
|
||||
* uint16 list_length
|
||||
* uint8 proto_length;
|
||||
* uint8 proto[proto_length];
|
||||
*/
|
||||
if (!PACKET_get_net_2_len(pkt, &len)
|
||||
|| PACKET_remaining(pkt) != len || !PACKET_get_1_len(pkt, &len)
|
||||
|| PACKET_remaining(pkt) != len) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_free(s->s3->alpn_selected);
|
||||
s->s3->alpn_selected = OPENSSL_malloc(len);
|
||||
if (s->s3->alpn_selected == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (!PACKET_copy_bytes(pkt, s->s3->alpn_selected, len)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
s->s3->alpn_selected_len = len;
|
||||
|
||||
if (s->session->ext.alpn_selected == NULL
|
||||
|| s->session->ext.alpn_selected_len != len
|
||||
|| memcmp(s->session->ext.alpn_selected, s->s3->alpn_selected, len)
|
||||
!= 0) {
|
||||
/* ALPN not consistent with the old session so cannot use early_data */
|
||||
s->ext.early_data_ok = 0;
|
||||
}
|
||||
if (!s->hit) {
|
||||
/* If a new session then update it with the selected ALPN */
|
||||
s->session->ext.alpn_selected =
|
||||
OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len);
|
||||
if (s->session->ext.alpn_selected == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
s->session->ext.alpn_selected_len = s->s3->alpn_selected_len;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
int tls_parse_stoc_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
unsigned int id, ct, mki;
|
||||
int i;
|
||||
STACK_OF(SRTP_PROTECTION_PROFILE) *clnt;
|
||||
SRTP_PROTECTION_PROFILE *prof;
|
||||
|
||||
if (!PACKET_get_net_2(pkt, &ct) || ct != 2
|
||||
|| !PACKET_get_net_2(pkt, &id)
|
||||
|| !PACKET_get_1(pkt, &mki)
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
|
||||
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mki != 0) {
|
||||
/* Must be no MKI, since we never offer one */
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_USE_SRTP,
|
||||
SSL_R_BAD_SRTP_MKI_VALUE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Throw an error if the server gave us an unsolicited extension */
|
||||
clnt = SSL_get_srtp_profiles(s);
|
||||
if (clnt == NULL) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
|
||||
SSL_R_NO_SRTP_PROFILES);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the server gave us something we support (and
|
||||
* presumably offered)
|
||||
*/
|
||||
for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(clnt); i++) {
|
||||
prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
|
||||
|
||||
if (prof->id == id) {
|
||||
s->srtp_profile = prof;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
|
||||
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
/* Ignore if inappropriate ciphersuite */
|
||||
if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)
|
||||
&& s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD
|
||||
&& s->s3->tmp.new_cipher->algorithm_enc != SSL_RC4)
|
||||
s->ext.use_etm = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
|
||||
if (!s->hit)
|
||||
s->session->flags |= SSL_SESS_FLAG_EXTMS;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
unsigned int version;
|
||||
|
||||
if (!PACKET_get_net_2(pkt, &version)
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO(TLS1.3): Remove this before release */
|
||||
if (version == TLS1_3_VERSION_DRAFT)
|
||||
version = TLS1_3_VERSION;
|
||||
|
||||
/* We ignore this extension for HRRs except to sanity check it */
|
||||
if (context == SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) {
|
||||
/*
|
||||
* The only protocol version we support which has an HRR message is
|
||||
* TLSv1.3, therefore we shouldn't be getting an HRR for anything else.
|
||||
*/
|
||||
if (version != TLS1_3_VERSION) {
|
||||
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
|
||||
SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS,
|
||||
SSL_R_BAD_HRR_VERSION);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We just set it here. We validate it in ssl_choose_client_version */
|
||||
s->version = version;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
#ifndef OPENSSL_NO_TLS1_3
|
||||
unsigned int group_id;
|
||||
PACKET encoded_pt;
|
||||
EVP_PKEY *ckey = s->s3->tmp.pkey, *skey = NULL;
|
||||
|
||||
/* Sanity check */
|
||||
if (ckey == NULL || s->s3->peer_tmp != NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!PACKET_get_net_2(pkt, &group_id)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((context & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0) {
|
||||
const uint16_t *pgroups = NULL;
|
||||
size_t i, num_groups;
|
||||
|
||||
if (PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* It is an error if the HelloRetryRequest wants a key_share that we
|
||||
* already sent in the first ClientHello
|
||||
*/
|
||||
if (group_id == s->s3->group_id) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Validate the selected group is one we support */
|
||||
tls1_get_supported_groups(s, &pgroups, &num_groups);
|
||||
for (i = 0; i < num_groups; i++) {
|
||||
if (group_id == pgroups[i])
|
||||
break;
|
||||
}
|
||||
if (i >= num_groups
|
||||
|| !tls_curve_allowed(s, group_id, SSL_SECOP_CURVE_SUPPORTED)) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->s3->group_id = group_id;
|
||||
EVP_PKEY_free(s->s3->tmp.pkey);
|
||||
s->s3->tmp.pkey = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (group_id != s->s3->group_id) {
|
||||
/*
|
||||
* This isn't for the group that we sent in the original
|
||||
* key_share!
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
|
||||
SSL_R_BAD_KEY_SHARE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!PACKET_as_length_prefixed_2(pkt, &encoded_pt)
|
||||
|| PACKET_remaining(&encoded_pt) == 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
skey = ssl_generate_pkey(ckey);
|
||||
if (skey == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (!EVP_PKEY_set1_tls_encodedpoint(skey, PACKET_data(&encoded_pt),
|
||||
PACKET_remaining(&encoded_pt))) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
|
||||
SSL_R_BAD_ECPOINT);
|
||||
EVP_PKEY_free(skey);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ssl_derive(s, ckey, skey, 1) == 0) {
|
||||
/* SSLfatal() already called */
|
||||
EVP_PKEY_free(skey);
|
||||
return 0;
|
||||
}
|
||||
s->s3->peer_tmp = skey;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
PACKET cookie;
|
||||
|
||||
if (!PACKET_as_length_prefixed_2(pkt, &cookie)
|
||||
|| !PACKET_memdup(&cookie, &s->ext.tls13_cookie,
|
||||
&s->ext.tls13_cookie_len)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_COOKIE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) {
|
||||
unsigned long max_early_data;
|
||||
|
||||
if (!PACKET_get_net_4(pkt, &max_early_data)
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
|
||||
SSL_R_INVALID_MAX_EARLY_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->session->ext.max_early_data = max_early_data;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s->ext.early_data_ok
|
||||
|| !s->hit
|
||||
|| s->session->ext.tick_identity != 0) {
|
||||
/*
|
||||
* If we get here then we didn't send early data, or we didn't resume
|
||||
* using the first identity, or the SNI/ALPN is not consistent so the
|
||||
* server should not be accepting it.
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->ext.early_data = SSL_EARLY_DATA_ACCEPTED;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
#ifndef OPENSSL_NO_TLS1_3
|
||||
unsigned int identity;
|
||||
|
||||
if (!PACKET_get_net_2(pkt, &identity) || PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_PSK,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->session->ext.tick_identity == (int)identity) {
|
||||
s->hit = 1;
|
||||
SSL_SESSION_free(s->psksession);
|
||||
s->psksession = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (s->psksession == NULL
|
||||
|| s->psksession->ext.tick_identity != (int)identity) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_PSK,
|
||||
SSL_R_BAD_PSK_IDENTITY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we used the external PSK for sending early_data then s->early_secret
|
||||
* is already set up, so don't overwrite it. Otherwise we copy the
|
||||
* early_secret across that we generated earlier.
|
||||
*/
|
||||
if ((s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY
|
||||
&& s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING)
|
||||
|| s->session->ext.max_early_data > 0
|
||||
|| s->psksession->ext.max_early_data == 0)
|
||||
memcpy(s->early_secret, s->psksession->early_secret, EVP_MAX_MD_SIZE);
|
||||
|
||||
SSL_SESSION_free(s->session);
|
||||
s->session = s->psksession;
|
||||
s->psksession = NULL;
|
||||
s->hit = 1;
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,533 @@
|
||||
/*
|
||||
* Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/* Custom extension utility functions */
|
||||
|
||||
#include <openssl/ct.h>
|
||||
#include "../ssl_locl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include "statem_locl.h"
|
||||
|
||||
typedef struct {
|
||||
void *add_arg;
|
||||
custom_ext_add_cb add_cb;
|
||||
custom_ext_free_cb free_cb;
|
||||
} custom_ext_add_cb_wrap;
|
||||
|
||||
typedef struct {
|
||||
void *parse_arg;
|
||||
custom_ext_parse_cb parse_cb;
|
||||
} custom_ext_parse_cb_wrap;
|
||||
|
||||
/*
|
||||
* Provide thin wrapper callbacks which convert new style arguments to old style
|
||||
*/
|
||||
static int custom_ext_add_old_cb_wrap(SSL *s, unsigned int ext_type,
|
||||
unsigned int context,
|
||||
const unsigned char **out,
|
||||
size_t *outlen, X509 *x, size_t chainidx,
|
||||
int *al, void *add_arg)
|
||||
{
|
||||
custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg;
|
||||
|
||||
if (add_cb_wrap->add_cb == NULL)
|
||||
return 1;
|
||||
|
||||
return add_cb_wrap->add_cb(s, ext_type, out, outlen, al,
|
||||
add_cb_wrap->add_arg);
|
||||
}
|
||||
|
||||
static void custom_ext_free_old_cb_wrap(SSL *s, unsigned int ext_type,
|
||||
unsigned int context,
|
||||
const unsigned char *out, void *add_arg)
|
||||
{
|
||||
custom_ext_add_cb_wrap *add_cb_wrap = (custom_ext_add_cb_wrap *)add_arg;
|
||||
|
||||
if (add_cb_wrap->free_cb == NULL)
|
||||
return;
|
||||
|
||||
add_cb_wrap->free_cb(s, ext_type, out, add_cb_wrap->add_arg);
|
||||
}
|
||||
|
||||
static int custom_ext_parse_old_cb_wrap(SSL *s, unsigned int ext_type,
|
||||
unsigned int context,
|
||||
const unsigned char *in,
|
||||
size_t inlen, X509 *x, size_t chainidx,
|
||||
int *al, void *parse_arg)
|
||||
{
|
||||
custom_ext_parse_cb_wrap *parse_cb_wrap =
|
||||
(custom_ext_parse_cb_wrap *)parse_arg;
|
||||
|
||||
if (parse_cb_wrap->parse_cb == NULL)
|
||||
return 1;
|
||||
|
||||
return parse_cb_wrap->parse_cb(s, ext_type, in, inlen, al,
|
||||
parse_cb_wrap->parse_arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a custom extension from the list. The |role| param is there to
|
||||
* support the legacy API where custom extensions for client and server could
|
||||
* be set independently on the same SSL_CTX. It is set to ENDPOINT_SERVER if we
|
||||
* are trying to find a method relevant to the server, ENDPOINT_CLIENT for the
|
||||
* client, or ENDPOINT_BOTH for either
|
||||
*/
|
||||
custom_ext_method *custom_ext_find(const custom_ext_methods *exts,
|
||||
ENDPOINT role, unsigned int ext_type,
|
||||
size_t *idx)
|
||||
{
|
||||
size_t i;
|
||||
custom_ext_method *meth = exts->meths;
|
||||
|
||||
for (i = 0; i < exts->meths_count; i++, meth++) {
|
||||
if (ext_type == meth->ext_type
|
||||
&& (role == ENDPOINT_BOTH || role == meth->role
|
||||
|| meth->role == ENDPOINT_BOTH)) {
|
||||
if (idx != NULL)
|
||||
*idx = i;
|
||||
return meth;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise custom extensions flags to indicate neither sent nor received.
|
||||
*/
|
||||
void custom_ext_init(custom_ext_methods *exts)
|
||||
{
|
||||
size_t i;
|
||||
custom_ext_method *meth = exts->meths;
|
||||
|
||||
for (i = 0; i < exts->meths_count; i++, meth++)
|
||||
meth->ext_flags = 0;
|
||||
}
|
||||
|
||||
/* Pass received custom extension data to the application for parsing. */
|
||||
int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type,
|
||||
const unsigned char *ext_data, size_t ext_size, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
int al;
|
||||
custom_ext_methods *exts = &s->cert->custext;
|
||||
custom_ext_method *meth;
|
||||
ENDPOINT role = ENDPOINT_BOTH;
|
||||
|
||||
if ((context & (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0)
|
||||
role = s->server ? ENDPOINT_SERVER : ENDPOINT_CLIENT;
|
||||
|
||||
meth = custom_ext_find(exts, role, ext_type, NULL);
|
||||
/* If not found return success */
|
||||
if (!meth)
|
||||
return 1;
|
||||
|
||||
/* Check if extension is defined for our protocol. If not, skip */
|
||||
if (!extension_is_relevant(s, meth->context, context))
|
||||
return 1;
|
||||
|
||||
if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS)) != 0) {
|
||||
/*
|
||||
* If it's ServerHello or EncryptedExtensions we can't have any
|
||||
* extensions not sent in ClientHello.
|
||||
*/
|
||||
if ((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0) {
|
||||
SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_CUSTOM_EXT_PARSE,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Extensions received in the ClientHello are marked with the
|
||||
* SSL_EXT_FLAG_RECEIVED. This is so we know to add the equivalent
|
||||
* extensions in the ServerHello/EncryptedExtensions message
|
||||
*/
|
||||
if ((context & SSL_EXT_CLIENT_HELLO) != 0)
|
||||
meth->ext_flags |= SSL_EXT_FLAG_RECEIVED;
|
||||
|
||||
/* If no parse function set return success */
|
||||
if (!meth->parse_cb)
|
||||
return 1;
|
||||
|
||||
if (meth->parse_cb(s, ext_type, context, ext_data, ext_size, x, chainidx,
|
||||
&al, meth->parse_arg) <= 0) {
|
||||
SSLfatal(s, al, SSL_F_CUSTOM_EXT_PARSE, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Request custom extension data from the application and add to the return
|
||||
* buffer.
|
||||
*/
|
||||
int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x, size_t chainidx,
|
||||
int maxversion)
|
||||
{
|
||||
custom_ext_methods *exts = &s->cert->custext;
|
||||
custom_ext_method *meth;
|
||||
size_t i;
|
||||
int al;
|
||||
|
||||
for (i = 0; i < exts->meths_count; i++) {
|
||||
const unsigned char *out = NULL;
|
||||
size_t outlen = 0;
|
||||
|
||||
meth = exts->meths + i;
|
||||
|
||||
if (!should_add_extension(s, meth->context, context, maxversion))
|
||||
continue;
|
||||
|
||||
if ((context & (SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
|
||||
| SSL_EXT_TLS1_3_CERTIFICATE
|
||||
| SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)) != 0) {
|
||||
/* Only send extensions present in ClientHello. */
|
||||
if (!(meth->ext_flags & SSL_EXT_FLAG_RECEIVED))
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* We skip it if the callback is absent - except for a ClientHello where
|
||||
* we add an empty extension.
|
||||
*/
|
||||
if ((context & SSL_EXT_CLIENT_HELLO) == 0 && meth->add_cb == NULL)
|
||||
continue;
|
||||
|
||||
if (meth->add_cb != NULL) {
|
||||
int cb_retval = meth->add_cb(s, meth->ext_type, context, &out,
|
||||
&outlen, x, chainidx, &al,
|
||||
meth->add_arg);
|
||||
|
||||
if (cb_retval < 0) {
|
||||
SSLfatal(s, al, SSL_F_CUSTOM_EXT_ADD, SSL_R_CALLBACK_FAILED);
|
||||
return 0; /* error */
|
||||
}
|
||||
if (cb_retval == 0)
|
||||
continue; /* skip this extension */
|
||||
}
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, meth->ext_type)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| (outlen > 0 && !WPACKET_memcpy(pkt, out, outlen))
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
|
||||
/*
|
||||
* We can't send duplicates: code logic should prevent this.
|
||||
*/
|
||||
if (!ossl_assert((meth->ext_flags & SSL_EXT_FLAG_SENT) == 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CUSTOM_EXT_ADD,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Indicate extension has been sent: this is both a sanity check to
|
||||
* ensure we don't send duplicate extensions and indicates that it
|
||||
* is not an error if the extension is present in ServerHello.
|
||||
*/
|
||||
meth->ext_flags |= SSL_EXT_FLAG_SENT;
|
||||
}
|
||||
if (meth->free_cb != NULL)
|
||||
meth->free_cb(s, meth->ext_type, context, out, meth->add_arg);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy the flags from src to dst for any extensions that exist in both */
|
||||
int custom_exts_copy_flags(custom_ext_methods *dst,
|
||||
const custom_ext_methods *src)
|
||||
{
|
||||
size_t i;
|
||||
custom_ext_method *methsrc = src->meths;
|
||||
|
||||
for (i = 0; i < src->meths_count; i++, methsrc++) {
|
||||
custom_ext_method *methdst = custom_ext_find(dst, methsrc->role,
|
||||
methsrc->ext_type, NULL);
|
||||
|
||||
if (methdst == NULL)
|
||||
continue;
|
||||
|
||||
methdst->ext_flags = methsrc->ext_flags;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Copy table of custom extensions */
|
||||
int custom_exts_copy(custom_ext_methods *dst, const custom_ext_methods *src)
|
||||
{
|
||||
size_t i;
|
||||
int err = 0;
|
||||
|
||||
if (src->meths_count > 0) {
|
||||
dst->meths =
|
||||
OPENSSL_memdup(src->meths,
|
||||
sizeof(*src->meths) * src->meths_count);
|
||||
if (dst->meths == NULL)
|
||||
return 0;
|
||||
dst->meths_count = src->meths_count;
|
||||
|
||||
for (i = 0; i < src->meths_count; i++) {
|
||||
custom_ext_method *methsrc = src->meths + i;
|
||||
custom_ext_method *methdst = dst->meths + i;
|
||||
|
||||
if (methsrc->add_cb != custom_ext_add_old_cb_wrap)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* We have found an old style API wrapper. We need to copy the
|
||||
* arguments too.
|
||||
*/
|
||||
|
||||
if (err) {
|
||||
methdst->add_arg = NULL;
|
||||
methdst->parse_arg = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
methdst->add_arg = OPENSSL_memdup(methsrc->add_arg,
|
||||
sizeof(custom_ext_add_cb_wrap));
|
||||
methdst->parse_arg = OPENSSL_memdup(methsrc->parse_arg,
|
||||
sizeof(custom_ext_parse_cb_wrap));
|
||||
|
||||
if (methdst->add_arg == NULL || methdst->parse_arg == NULL)
|
||||
err = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (err) {
|
||||
custom_exts_free(dst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void custom_exts_free(custom_ext_methods *exts)
|
||||
{
|
||||
size_t i;
|
||||
custom_ext_method *meth;
|
||||
|
||||
for (i = 0, meth = exts->meths; i < exts->meths_count; i++, meth++) {
|
||||
if (meth->add_cb != custom_ext_add_old_cb_wrap)
|
||||
continue;
|
||||
|
||||
/* Old style API wrapper. Need to free the arguments too */
|
||||
OPENSSL_free(meth->add_arg);
|
||||
OPENSSL_free(meth->parse_arg);
|
||||
}
|
||||
OPENSSL_free(exts->meths);
|
||||
}
|
||||
|
||||
/* Return true if a client custom extension exists, false otherwise */
|
||||
int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx, unsigned int ext_type)
|
||||
{
|
||||
return custom_ext_find(&ctx->cert->custext, ENDPOINT_CLIENT, ext_type,
|
||||
NULL) != NULL;
|
||||
}
|
||||
|
||||
static int add_custom_ext_intern(SSL_CTX *ctx, ENDPOINT role,
|
||||
unsigned int ext_type,
|
||||
unsigned int context,
|
||||
SSL_custom_ext_add_cb_ex add_cb,
|
||||
SSL_custom_ext_free_cb_ex free_cb,
|
||||
void *add_arg,
|
||||
SSL_custom_ext_parse_cb_ex parse_cb,
|
||||
void *parse_arg)
|
||||
{
|
||||
custom_ext_methods *exts = &ctx->cert->custext;
|
||||
custom_ext_method *meth, *tmp;
|
||||
|
||||
/*
|
||||
* Check application error: if add_cb is not set free_cb will never be
|
||||
* called.
|
||||
*/
|
||||
if (add_cb == NULL && free_cb != NULL)
|
||||
return 0;
|
||||
|
||||
#ifndef OPENSSL_NO_CT
|
||||
/*
|
||||
* We don't want applications registering callbacks for SCT extensions
|
||||
* whilst simultaneously using the built-in SCT validation features, as
|
||||
* these two things may not play well together.
|
||||
*/
|
||||
if (ext_type == TLSEXT_TYPE_signed_certificate_timestamp
|
||||
&& (context & SSL_EXT_CLIENT_HELLO) != 0
|
||||
&& SSL_CTX_ct_is_enabled(ctx))
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Don't add if extension supported internally, but make exception
|
||||
* for extension types that previously were not supported, but now are.
|
||||
*/
|
||||
if (SSL_extension_supported(ext_type)
|
||||
&& ext_type != TLSEXT_TYPE_signed_certificate_timestamp)
|
||||
return 0;
|
||||
|
||||
/* Extension type must fit in 16 bits */
|
||||
if (ext_type > 0xffff)
|
||||
return 0;
|
||||
/* Search for duplicate */
|
||||
if (custom_ext_find(exts, role, ext_type, NULL))
|
||||
return 0;
|
||||
tmp = OPENSSL_realloc(exts->meths,
|
||||
(exts->meths_count + 1) * sizeof(custom_ext_method));
|
||||
if (tmp == NULL)
|
||||
return 0;
|
||||
|
||||
exts->meths = tmp;
|
||||
meth = exts->meths + exts->meths_count;
|
||||
memset(meth, 0, sizeof(*meth));
|
||||
meth->role = role;
|
||||
meth->context = context;
|
||||
meth->parse_cb = parse_cb;
|
||||
meth->add_cb = add_cb;
|
||||
meth->free_cb = free_cb;
|
||||
meth->ext_type = ext_type;
|
||||
meth->add_arg = add_arg;
|
||||
meth->parse_arg = parse_arg;
|
||||
exts->meths_count++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int add_old_custom_ext(SSL_CTX *ctx, ENDPOINT role,
|
||||
unsigned int ext_type,
|
||||
unsigned int context,
|
||||
custom_ext_add_cb add_cb,
|
||||
custom_ext_free_cb free_cb,
|
||||
void *add_arg,
|
||||
custom_ext_parse_cb parse_cb, void *parse_arg)
|
||||
{
|
||||
custom_ext_add_cb_wrap *add_cb_wrap
|
||||
= OPENSSL_malloc(sizeof(*add_cb_wrap));
|
||||
custom_ext_parse_cb_wrap *parse_cb_wrap
|
||||
= OPENSSL_malloc(sizeof(*parse_cb_wrap));
|
||||
int ret;
|
||||
|
||||
if (add_cb_wrap == NULL || parse_cb_wrap == NULL) {
|
||||
OPENSSL_free(add_cb_wrap);
|
||||
OPENSSL_free(parse_cb_wrap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
add_cb_wrap->add_arg = add_arg;
|
||||
add_cb_wrap->add_cb = add_cb;
|
||||
add_cb_wrap->free_cb = free_cb;
|
||||
parse_cb_wrap->parse_arg = parse_arg;
|
||||
parse_cb_wrap->parse_cb = parse_cb;
|
||||
|
||||
ret = add_custom_ext_intern(ctx, role, ext_type,
|
||||
context,
|
||||
custom_ext_add_old_cb_wrap,
|
||||
custom_ext_free_old_cb_wrap,
|
||||
add_cb_wrap,
|
||||
custom_ext_parse_old_cb_wrap,
|
||||
parse_cb_wrap);
|
||||
|
||||
if (!ret) {
|
||||
OPENSSL_free(add_cb_wrap);
|
||||
OPENSSL_free(parse_cb_wrap);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Application level functions to add the old custom extension callbacks */
|
||||
int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
|
||||
custom_ext_add_cb add_cb,
|
||||
custom_ext_free_cb free_cb,
|
||||
void *add_arg,
|
||||
custom_ext_parse_cb parse_cb, void *parse_arg)
|
||||
{
|
||||
return add_old_custom_ext(ctx, ENDPOINT_CLIENT, ext_type,
|
||||
SSL_EXT_TLS1_2_AND_BELOW_ONLY
|
||||
| SSL_EXT_CLIENT_HELLO
|
||||
| SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_IGNORE_ON_RESUMPTION,
|
||||
add_cb, free_cb, add_arg, parse_cb, parse_arg);
|
||||
}
|
||||
|
||||
int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
|
||||
custom_ext_add_cb add_cb,
|
||||
custom_ext_free_cb free_cb,
|
||||
void *add_arg,
|
||||
custom_ext_parse_cb parse_cb, void *parse_arg)
|
||||
{
|
||||
return add_old_custom_ext(ctx, ENDPOINT_SERVER, ext_type,
|
||||
SSL_EXT_TLS1_2_AND_BELOW_ONLY
|
||||
| SSL_EXT_CLIENT_HELLO
|
||||
| SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_IGNORE_ON_RESUMPTION,
|
||||
add_cb, free_cb, add_arg, parse_cb, parse_arg);
|
||||
}
|
||||
|
||||
int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
|
||||
unsigned int context,
|
||||
SSL_custom_ext_add_cb_ex add_cb,
|
||||
SSL_custom_ext_free_cb_ex free_cb,
|
||||
void *add_arg,
|
||||
SSL_custom_ext_parse_cb_ex parse_cb, void *parse_arg)
|
||||
{
|
||||
return add_custom_ext_intern(ctx, ENDPOINT_BOTH, ext_type, context, add_cb,
|
||||
free_cb, add_arg, parse_cb, parse_arg);
|
||||
}
|
||||
|
||||
int SSL_extension_supported(unsigned int ext_type)
|
||||
{
|
||||
switch (ext_type) {
|
||||
/* Internally supported extensions. */
|
||||
case TLSEXT_TYPE_application_layer_protocol_negotiation:
|
||||
#ifndef OPENSSL_NO_EC
|
||||
case TLSEXT_TYPE_ec_point_formats:
|
||||
case TLSEXT_TYPE_supported_groups:
|
||||
case TLSEXT_TYPE_key_share:
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
case TLSEXT_TYPE_next_proto_neg:
|
||||
#endif
|
||||
case TLSEXT_TYPE_padding:
|
||||
case TLSEXT_TYPE_renegotiate:
|
||||
case TLSEXT_TYPE_max_fragment_length:
|
||||
case TLSEXT_TYPE_server_name:
|
||||
case TLSEXT_TYPE_session_ticket:
|
||||
case TLSEXT_TYPE_signature_algorithms:
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
case TLSEXT_TYPE_srp:
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
case TLSEXT_TYPE_status_request:
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_CT
|
||||
case TLSEXT_TYPE_signed_certificate_timestamp:
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
case TLSEXT_TYPE_use_srtp:
|
||||
#endif
|
||||
case TLSEXT_TYPE_encrypt_then_mac:
|
||||
case TLSEXT_TYPE_supported_versions:
|
||||
case TLSEXT_TYPE_extended_master_secret:
|
||||
case TLSEXT_TYPE_psk_kex_modes:
|
||||
case TLSEXT_TYPE_cookie:
|
||||
case TLSEXT_TYPE_early_data:
|
||||
case TLSEXT_TYPE_certificate_authorities:
|
||||
case TLSEXT_TYPE_psk:
|
||||
case TLSEXT_TYPE_post_handshake_auth:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,1823 @@
|
||||
/*
|
||||
* Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/ocsp.h>
|
||||
#include "../ssl_locl.h"
|
||||
#include "statem_locl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
|
||||
#define COOKIE_STATE_FORMAT_VERSION 0
|
||||
|
||||
/*
|
||||
* 2 bytes for packet length, 2 bytes for format version, 2 bytes for
|
||||
* protocol version, 2 bytes for group id, 2 bytes for cipher id, 1 byte for
|
||||
* key_share present flag, 4 bytes for timestamp, 2 bytes for the hashlen,
|
||||
* EVP_MAX_MD_SIZE for transcript hash, 1 byte for app cookie length, app cookie
|
||||
* length bytes, SHA256_DIGEST_LENGTH bytes for the HMAC of the whole thing.
|
||||
*/
|
||||
#define MAX_COOKIE_SIZE (2 + 2 + 2 + 2 + 2 + 1 + 4 + 2 + EVP_MAX_MD_SIZE + 1 \
|
||||
+ SSL_COOKIE_LENGTH + SHA256_DIGEST_LENGTH)
|
||||
|
||||
/*
|
||||
* Message header + 2 bytes for protocol version + number of random bytes +
|
||||
* + 1 byte for legacy session id length + number of bytes in legacy session id
|
||||
* + 2 bytes for ciphersuite + 1 byte for legacy compression
|
||||
* + 2 bytes for extension block length + 6 bytes for key_share extension
|
||||
* + 4 bytes for cookie extension header + the number of bytes in the cookie
|
||||
*/
|
||||
#define MAX_HRR_SIZE (SSL3_HM_HEADER_LENGTH + 2 + SSL3_RANDOM_SIZE + 1 \
|
||||
+ SSL_MAX_SSL_SESSION_ID_LENGTH + 2 + 1 + 2 + 6 + 4 \
|
||||
+ MAX_COOKIE_SIZE)
|
||||
|
||||
/*
|
||||
* Parse the client's renegotiation binding and abort if it's not right
|
||||
*/
|
||||
int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
unsigned int ilen;
|
||||
const unsigned char *data;
|
||||
|
||||
/* Parse the length byte */
|
||||
if (!PACKET_get_1(pkt, &ilen)
|
||||
|| !PACKET_get_bytes(pkt, &data, ilen)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
|
||||
SSL_R_RENEGOTIATION_ENCODING_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check that the extension matches */
|
||||
if (ilen != s->s3->previous_client_finished_len) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
|
||||
SSL_R_RENEGOTIATION_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memcmp(data, s->s3->previous_client_finished,
|
||||
s->s3->previous_client_finished_len)) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
|
||||
SSL_R_RENEGOTIATION_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->s3->send_connection_binding = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-
|
||||
* The servername extension is treated as follows:
|
||||
*
|
||||
* - Only the hostname type is supported with a maximum length of 255.
|
||||
* - The servername is rejected if too long or if it contains zeros,
|
||||
* in which case an fatal alert is generated.
|
||||
* - The servername field is maintained together with the session cache.
|
||||
* - When a session is resumed, the servername call back invoked in order
|
||||
* to allow the application to position itself to the right context.
|
||||
* - The servername is acknowledged if it is new for a session or when
|
||||
* it is identical to a previously used for the same session.
|
||||
* Applications can control the behaviour. They can at any time
|
||||
* set a 'desirable' servername for a new SSL object. This can be the
|
||||
* case for example with HTTPS when a Host: header field is received and
|
||||
* a renegotiation is requested. In this case, a possible servername
|
||||
* presented in the new client hello is only acknowledged if it matches
|
||||
* the value of the Host: field.
|
||||
* - Applications must use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
|
||||
* if they provide for changing an explicit servername context for the
|
||||
* session, i.e. when the session has been established with a servername
|
||||
* extension.
|
||||
* - On session reconnect, the servername extension may be absent.
|
||||
*/
|
||||
int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
unsigned int servname_type;
|
||||
PACKET sni, hostname;
|
||||
|
||||
if (!PACKET_as_length_prefixed_2(pkt, &sni)
|
||||
/* ServerNameList must be at least 1 byte long. */
|
||||
|| PACKET_remaining(&sni) == 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Although the intent was for server_name to be extensible, RFC 4366
|
||||
* was not clear about it; and so OpenSSL among other implementations,
|
||||
* always and only allows a 'host_name' name types.
|
||||
* RFC 6066 corrected the mistake but adding new name types
|
||||
* is nevertheless no longer feasible, so act as if no other
|
||||
* SNI types can exist, to simplify parsing.
|
||||
*
|
||||
* Also note that the RFC permits only one SNI value per type,
|
||||
* i.e., we can only have a single hostname.
|
||||
*/
|
||||
if (!PACKET_get_1(&sni, &servname_type)
|
||||
|| servname_type != TLSEXT_NAMETYPE_host_name
|
||||
|| !PACKET_as_length_prefixed_2(&sni, &hostname)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s->hit) {
|
||||
if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) {
|
||||
SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME,
|
||||
SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (PACKET_contains_zero_byte(&hostname)) {
|
||||
SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME,
|
||||
SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
OPENSSL_free(s->session->ext.hostname);
|
||||
s->session->ext.hostname = NULL;
|
||||
if (!PACKET_strndup(&hostname, &s->session->ext.hostname)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->servername_done = 1;
|
||||
} else {
|
||||
/*
|
||||
* TODO(openssl-team): if the SNI doesn't match, we MUST
|
||||
* fall back to a full handshake.
|
||||
*/
|
||||
s->servername_done = s->session->ext.hostname
|
||||
&& PACKET_equal(&hostname, s->session->ext.hostname,
|
||||
strlen(s->session->ext.hostname));
|
||||
|
||||
if (!s->servername_done && s->session->ext.hostname != NULL)
|
||||
s->ext.early_data_ok = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
unsigned int value;
|
||||
|
||||
if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Received |value| should be a valid max-fragment-length code. */
|
||||
if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
|
||||
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* RFC 6066: The negotiated length applies for the duration of the session
|
||||
* including session resumptions.
|
||||
* We should receive the same code as in resumed session !
|
||||
*/
|
||||
if (s->hit && s->session->ext.max_fragment_len_mode != value) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
|
||||
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store it in session, so it'll become binding for us
|
||||
* and we'll include it in a next Server Hello.
|
||||
*/
|
||||
s->session->ext.max_fragment_len_mode = value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
PACKET srp_I;
|
||||
|
||||
if (!PACKET_as_length_prefixed_1(pkt, &srp_I)
|
||||
|| PACKET_contains_zero_byte(&srp_I)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_SRP,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(openssl-team): currently, we re-authenticate the user
|
||||
* upon resumption. Instead, we MUST ignore the login.
|
||||
*/
|
||||
if (!PACKET_strndup(&srp_I, &s->srp_ctx.login)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SRP,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
PACKET ec_point_format_list;
|
||||
|
||||
if (!PACKET_as_length_prefixed_1(pkt, &ec_point_format_list)
|
||||
|| PACKET_remaining(&ec_point_format_list) == 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s->hit) {
|
||||
if (!PACKET_memdup(&ec_point_format_list,
|
||||
&s->session->ext.ecpointformats,
|
||||
&s->session->ext.ecpointformats_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif /* OPENSSL_NO_EC */
|
||||
|
||||
int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
if (s->ext.session_ticket_cb &&
|
||||
!s->ext.session_ticket_cb(s, PACKET_data(pkt),
|
||||
PACKET_remaining(pkt),
|
||||
s->ext.session_ticket_cb_arg)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_parse_ctos_sig_algs_cert(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
PACKET supported_sig_algs;
|
||||
|
||||
if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs)
|
||||
|| PACKET_remaining(&supported_sig_algs) == 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 1)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
PACKET supported_sig_algs;
|
||||
|
||||
if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs)
|
||||
|| PACKET_remaining(&supported_sig_algs) == 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 0)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
PACKET responder_id_list, exts;
|
||||
|
||||
/* Not defined if we get one of these in a client Certificate */
|
||||
if (x != NULL)
|
||||
return 1;
|
||||
|
||||
if (!PACKET_get_1(pkt, (unsigned int *)&s->ext.status_type)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) {
|
||||
/*
|
||||
* We don't know what to do with any other type so ignore it.
|
||||
*/
|
||||
s->ext.status_type = TLSEXT_STATUSTYPE_nothing;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!PACKET_get_length_prefixed_2 (pkt, &responder_id_list)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We remove any OCSP_RESPIDs from a previous handshake
|
||||
* to prevent unbounded memory growth - CVE-2016-6304
|
||||
*/
|
||||
sk_OCSP_RESPID_pop_free(s->ext.ocsp.ids, OCSP_RESPID_free);
|
||||
if (PACKET_remaining(&responder_id_list) > 0) {
|
||||
s->ext.ocsp.ids = sk_OCSP_RESPID_new_null();
|
||||
if (s->ext.ocsp.ids == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
s->ext.ocsp.ids = NULL;
|
||||
}
|
||||
|
||||
while (PACKET_remaining(&responder_id_list) > 0) {
|
||||
OCSP_RESPID *id;
|
||||
PACKET responder_id;
|
||||
const unsigned char *id_data;
|
||||
|
||||
if (!PACKET_get_length_prefixed_2(&responder_id_list, &responder_id)
|
||||
|| PACKET_remaining(&responder_id) == 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
id_data = PACKET_data(&responder_id);
|
||||
/* TODO(size_t): Convert d2i_* to size_t */
|
||||
id = d2i_OCSP_RESPID(NULL, &id_data,
|
||||
(int)PACKET_remaining(&responder_id));
|
||||
if (id == NULL) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (id_data != PACKET_end(&responder_id)) {
|
||||
OCSP_RESPID_free(id);
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!sk_OCSP_RESPID_push(s->ext.ocsp.ids, id)) {
|
||||
OCSP_RESPID_free(id);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read in request_extensions */
|
||||
if (!PACKET_as_length_prefixed_2(pkt, &exts)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (PACKET_remaining(&exts) > 0) {
|
||||
const unsigned char *ext_data = PACKET_data(&exts);
|
||||
|
||||
sk_X509_EXTENSION_pop_free(s->ext.ocsp.exts,
|
||||
X509_EXTENSION_free);
|
||||
s->ext.ocsp.exts =
|
||||
d2i_X509_EXTENSIONS(NULL, &ext_data, (int)PACKET_remaining(&exts));
|
||||
if (s->ext.ocsp.exts == NULL || ext_data != PACKET_end(&exts)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
int tls_parse_ctos_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
/*
|
||||
* We shouldn't accept this extension on a
|
||||
* renegotiation.
|
||||
*/
|
||||
if (SSL_IS_FIRST_HANDSHAKE(s))
|
||||
s->s3->npn_seen = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Save the ALPN extension in a ClientHello.|pkt| holds the contents of the ALPN
|
||||
* extension, not including type and length. Returns: 1 on success, 0 on error.
|
||||
*/
|
||||
int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
PACKET protocol_list, save_protocol_list, protocol;
|
||||
|
||||
if (!SSL_IS_FIRST_HANDSHAKE(s))
|
||||
return 1;
|
||||
|
||||
if (!PACKET_as_length_prefixed_2(pkt, &protocol_list)
|
||||
|| PACKET_remaining(&protocol_list) < 2) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
save_protocol_list = protocol_list;
|
||||
do {
|
||||
/* Protocol names can't be empty. */
|
||||
if (!PACKET_get_length_prefixed_1(&protocol_list, &protocol)
|
||||
|| PACKET_remaining(&protocol) == 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
} while (PACKET_remaining(&protocol_list) != 0);
|
||||
|
||||
OPENSSL_free(s->s3->alpn_proposed);
|
||||
s->s3->alpn_proposed = NULL;
|
||||
s->s3->alpn_proposed_len = 0;
|
||||
if (!PACKET_memdup(&save_protocol_list,
|
||||
&s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
STACK_OF(SRTP_PROTECTION_PROFILE) *srvr;
|
||||
unsigned int ct, mki_len, id;
|
||||
int i, srtp_pref;
|
||||
PACKET subpkt;
|
||||
|
||||
/* Ignore this if we have no SRTP profiles */
|
||||
if (SSL_get_srtp_profiles(s) == NULL)
|
||||
return 1;
|
||||
|
||||
/* Pull off the length of the cipher suite list and check it is even */
|
||||
if (!PACKET_get_net_2(pkt, &ct) || (ct & 1) != 0
|
||||
|| !PACKET_get_sub_packet(pkt, &subpkt, ct)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
|
||||
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
srvr = SSL_get_srtp_profiles(s);
|
||||
s->srtp_profile = NULL;
|
||||
/* Search all profiles for a match initially */
|
||||
srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr);
|
||||
|
||||
while (PACKET_remaining(&subpkt)) {
|
||||
if (!PACKET_get_net_2(&subpkt, &id)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
|
||||
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only look for match in profiles of higher preference than
|
||||
* current match.
|
||||
* If no profiles have been have been configured then this
|
||||
* does nothing.
|
||||
*/
|
||||
for (i = 0; i < srtp_pref; i++) {
|
||||
SRTP_PROTECTION_PROFILE *sprof =
|
||||
sk_SRTP_PROTECTION_PROFILE_value(srvr, i);
|
||||
|
||||
if (sprof->id == id) {
|
||||
s->srtp_profile = sprof;
|
||||
srtp_pref = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now extract the MKI value as a sanity check, but discard it for now */
|
||||
if (!PACKET_get_1(pkt, &mki_len)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
|
||||
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!PACKET_forward(pkt, mki_len)
|
||||
|| PACKET_remaining(pkt)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
|
||||
SSL_R_BAD_SRTP_MKI_VALUE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int tls_parse_ctos_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC))
|
||||
s->ext.use_etm = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a psk_kex_modes extension received in the ClientHello. |pkt| contains
|
||||
* the raw PACKET data for the extension. Returns 1 on success or 0 on failure.
|
||||
*/
|
||||
int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
#ifndef OPENSSL_NO_TLS1_3
|
||||
PACKET psk_kex_modes;
|
||||
unsigned int mode;
|
||||
|
||||
if (!PACKET_as_length_prefixed_1(pkt, &psk_kex_modes)
|
||||
|| PACKET_remaining(&psk_kex_modes) == 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (PACKET_get_1(&psk_kex_modes, &mode)) {
|
||||
if (mode == TLSEXT_KEX_MODE_KE_DHE)
|
||||
s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE_DHE;
|
||||
else if (mode == TLSEXT_KEX_MODE_KE
|
||||
&& (s->options & SSL_OP_ALLOW_NO_DHE_KEX) != 0)
|
||||
s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a key_share extension received in the ClientHello. |pkt| contains
|
||||
* the raw PACKET data for the extension. Returns 1 on success or 0 on failure.
|
||||
*/
|
||||
int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
#ifndef OPENSSL_NO_TLS1_3
|
||||
unsigned int group_id;
|
||||
PACKET key_share_list, encoded_pt;
|
||||
const uint16_t *clntgroups, *srvrgroups;
|
||||
size_t clnt_num_groups, srvr_num_groups;
|
||||
int found = 0;
|
||||
|
||||
if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0)
|
||||
return 1;
|
||||
|
||||
/* Sanity check */
|
||||
if (s->s3->peer_tmp != NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get our list of supported groups */
|
||||
tls1_get_supported_groups(s, &srvrgroups, &srvr_num_groups);
|
||||
/* Get the clients list of supported groups. */
|
||||
tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups);
|
||||
if (clnt_num_groups == 0) {
|
||||
/*
|
||||
* This can only happen if the supported_groups extension was not sent,
|
||||
* because we verify that the length is non-zero when we process that
|
||||
* extension.
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
|
||||
SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->s3->group_id != 0 && PACKET_remaining(&key_share_list) == 0) {
|
||||
/*
|
||||
* If we set a group_id already, then we must have sent an HRR
|
||||
* requesting a new key_share. If we haven't got one then that is an
|
||||
* error
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
|
||||
SSL_R_BAD_KEY_SHARE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (PACKET_remaining(&key_share_list) > 0) {
|
||||
if (!PACKET_get_net_2(&key_share_list, &group_id)
|
||||
|| !PACKET_get_length_prefixed_2(&key_share_list, &encoded_pt)
|
||||
|| PACKET_remaining(&encoded_pt) == 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we already found a suitable key_share we loop through the
|
||||
* rest to verify the structure, but don't process them.
|
||||
*/
|
||||
if (found)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If we sent an HRR then the key_share sent back MUST be for the group
|
||||
* we requested, and must be the only key_share sent.
|
||||
*/
|
||||
if (s->s3->group_id != 0
|
||||
&& (group_id != s->s3->group_id
|
||||
|| PACKET_remaining(&key_share_list) != 0)) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if this share is in supported_groups sent from client */
|
||||
if (!check_in_list(s, group_id, clntgroups, clnt_num_groups, 0)) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if this share is for a group we can use */
|
||||
if (!check_in_list(s, group_id, srvrgroups, srvr_num_groups, 1)) {
|
||||
/* Share not suitable */
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((s->s3->peer_tmp = ssl_generate_param_group(group_id)) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
|
||||
SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->s3->group_id = group_id;
|
||||
|
||||
if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
|
||||
PACKET_data(&encoded_pt),
|
||||
PACKET_remaining(&encoded_pt))) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_ECPOINT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
found = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
unsigned int format, version, key_share, group_id;
|
||||
EVP_MD_CTX *hctx;
|
||||
EVP_PKEY *pkey;
|
||||
PACKET cookie, raw, chhash, appcookie;
|
||||
WPACKET hrrpkt;
|
||||
const unsigned char *data, *mdin, *ciphdata;
|
||||
unsigned char hmac[SHA256_DIGEST_LENGTH];
|
||||
unsigned char hrr[MAX_HRR_SIZE];
|
||||
size_t rawlen, hmaclen, hrrlen, ciphlen;
|
||||
unsigned long tm, now;
|
||||
|
||||
/* Ignore any cookie if we're not set up to verify it */
|
||||
if (s->ctx->app_verify_cookie_cb == NULL
|
||||
|| (s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
|
||||
return 1;
|
||||
|
||||
if (!PACKET_as_length_prefixed_2(pkt, &cookie)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
raw = cookie;
|
||||
data = PACKET_data(&raw);
|
||||
rawlen = PACKET_remaining(&raw);
|
||||
if (rawlen < SHA256_DIGEST_LENGTH
|
||||
|| !PACKET_forward(&raw, rawlen - SHA256_DIGEST_LENGTH)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
mdin = PACKET_data(&raw);
|
||||
|
||||
/* Verify the HMAC of the cookie */
|
||||
hctx = EVP_MD_CTX_create();
|
||||
pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
|
||||
s->session_ctx->ext.cookie_hmac_key,
|
||||
sizeof(s->session_ctx->ext.cookie_hmac_key));
|
||||
if (hctx == NULL || pkey == NULL) {
|
||||
EVP_MD_CTX_free(hctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
hmaclen = SHA256_DIGEST_LENGTH;
|
||||
if (EVP_DigestSignInit(hctx, NULL, EVP_sha256(), NULL, pkey) <= 0
|
||||
|| EVP_DigestSign(hctx, hmac, &hmaclen, data,
|
||||
rawlen - SHA256_DIGEST_LENGTH) <= 0
|
||||
|| hmaclen != SHA256_DIGEST_LENGTH) {
|
||||
EVP_MD_CTX_free(hctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_MD_CTX_free(hctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
|
||||
if (CRYPTO_memcmp(hmac, mdin, SHA256_DIGEST_LENGTH) != 0) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
SSL_R_COOKIE_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!PACKET_get_net_2(&cookie, &format)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
/* Check the cookie format is something we recognise. Ignore it if not */
|
||||
if (format != COOKIE_STATE_FORMAT_VERSION)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
* The rest of these checks really shouldn't fail since we have verified the
|
||||
* HMAC above.
|
||||
*/
|
||||
|
||||
/* Check the version number is sane */
|
||||
if (!PACKET_get_net_2(&cookie, &version)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
if (version != TLS1_3_VERSION) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!PACKET_get_net_2(&cookie, &group_id)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ciphdata = PACKET_data(&cookie);
|
||||
if (!PACKET_forward(&cookie, 2)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
if (group_id != s->s3->group_id
|
||||
|| s->s3->tmp.new_cipher
|
||||
!= ssl_get_cipher_by_char(s, ciphdata, 0)) {
|
||||
/*
|
||||
* We chose a different cipher or group id this time around to what is
|
||||
* in the cookie. Something must have changed.
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
SSL_R_BAD_CIPHER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!PACKET_get_1(&cookie, &key_share)
|
||||
|| !PACKET_get_net_4(&cookie, &tm)
|
||||
|| !PACKET_get_length_prefixed_2(&cookie, &chhash)
|
||||
|| !PACKET_get_length_prefixed_1(&cookie, &appcookie)
|
||||
|| PACKET_remaining(&cookie) != SHA256_DIGEST_LENGTH) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We tolerate a cookie age of up to 10 minutes (= 60 * 10 seconds) */
|
||||
now = (unsigned long)time(NULL);
|
||||
if (tm > now || (now - tm) > 600) {
|
||||
/* Cookie is stale. Ignore it */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Verify the app cookie */
|
||||
if (s->ctx->app_verify_cookie_cb(s, PACKET_data(&appcookie),
|
||||
PACKET_remaining(&appcookie)) == 0) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
SSL_R_COOKIE_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reconstruct the HRR that we would have sent in response to the original
|
||||
* ClientHello so we can add it to the transcript hash.
|
||||
* Note: This won't work with custom HRR extensions
|
||||
*/
|
||||
if (!WPACKET_init_static_len(&hrrpkt, hrr, sizeof(hrr), 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (!WPACKET_put_bytes_u8(&hrrpkt, SSL3_MT_SERVER_HELLO)
|
||||
|| !WPACKET_start_sub_packet_u24(&hrrpkt)
|
||||
|| !WPACKET_put_bytes_u16(&hrrpkt, TLS1_2_VERSION)
|
||||
|| !WPACKET_memcpy(&hrrpkt, hrrrandom, SSL3_RANDOM_SIZE)
|
||||
|| !WPACKET_sub_memcpy_u8(&hrrpkt, s->tmp_session_id,
|
||||
s->tmp_session_id_len)
|
||||
|| !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, &hrrpkt,
|
||||
&ciphlen)
|
||||
|| !WPACKET_put_bytes_u8(&hrrpkt, 0)
|
||||
|| !WPACKET_start_sub_packet_u16(&hrrpkt)) {
|
||||
WPACKET_cleanup(&hrrpkt);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_supported_versions)
|
||||
|| !WPACKET_start_sub_packet_u16(&hrrpkt)
|
||||
/* TODO(TLS1.3): Fix this before release */
|
||||
|| !WPACKET_put_bytes_u16(&hrrpkt, TLS1_3_VERSION_DRAFT)
|
||||
|| !WPACKET_close(&hrrpkt)) {
|
||||
WPACKET_cleanup(&hrrpkt);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (key_share) {
|
||||
if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_key_share)
|
||||
|| !WPACKET_start_sub_packet_u16(&hrrpkt)
|
||||
|| !WPACKET_put_bytes_u16(&hrrpkt, s->s3->group_id)
|
||||
|| !WPACKET_close(&hrrpkt)) {
|
||||
WPACKET_cleanup(&hrrpkt);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_cookie)
|
||||
|| !WPACKET_start_sub_packet_u16(&hrrpkt)
|
||||
|| !WPACKET_sub_memcpy_u16(&hrrpkt, data, rawlen)
|
||||
|| !WPACKET_close(&hrrpkt) /* cookie extension */
|
||||
|| !WPACKET_close(&hrrpkt) /* extension block */
|
||||
|| !WPACKET_close(&hrrpkt) /* message */
|
||||
|| !WPACKET_get_total_written(&hrrpkt, &hrrlen)
|
||||
|| !WPACKET_finish(&hrrpkt)) {
|
||||
WPACKET_cleanup(&hrrpkt);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Reconstruct the transcript hash */
|
||||
if (!create_synthetic_message_hash(s, PACKET_data(&chhash),
|
||||
PACKET_remaining(&chhash), hrr,
|
||||
hrrlen)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Act as if this ClientHello came after a HelloRetryRequest */
|
||||
s->hello_retry_request = 1;
|
||||
|
||||
s->ext.cookieok = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
PACKET supported_groups_list;
|
||||
|
||||
/* Each group is 2 bytes and we must have at least 1. */
|
||||
if (!PACKET_as_length_prefixed_2(pkt, &supported_groups_list)
|
||||
|| PACKET_remaining(&supported_groups_list) == 0
|
||||
|| (PACKET_remaining(&supported_groups_list) % 2) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s->hit || SSL_IS_TLS13(s)) {
|
||||
OPENSSL_free(s->session->ext.supportedgroups);
|
||||
s->session->ext.supportedgroups = NULL;
|
||||
s->session->ext.supportedgroups_len = 0;
|
||||
if (!tls1_save_u16(&supported_groups_list,
|
||||
&s->session->ext.supportedgroups,
|
||||
&s->session->ext.supportedgroups_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
/* The extension must always be empty */
|
||||
if (PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_EMS, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
if (PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_EARLY_DATA, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->hello_retry_request != SSL_HRR_NONE) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PARSE_CTOS_EARLY_DATA, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
PACKET identities, binders, binder;
|
||||
size_t binderoffset, hashsize;
|
||||
SSL_SESSION *sess = NULL;
|
||||
unsigned int id, i, ext = 0;
|
||||
const EVP_MD *md = NULL;
|
||||
|
||||
/*
|
||||
* If we have no PSK kex mode that we recognise then we can't resume so
|
||||
* ignore this extension
|
||||
*/
|
||||
if ((s->ext.psk_kex_mode
|
||||
& (TLSEXT_KEX_MODE_FLAG_KE | TLSEXT_KEX_MODE_FLAG_KE_DHE)) == 0)
|
||||
return 1;
|
||||
|
||||
if (!PACKET_get_length_prefixed_2(pkt, &identities)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (id = 0; PACKET_remaining(&identities) != 0; id++) {
|
||||
PACKET identity;
|
||||
unsigned long ticket_agel;
|
||||
|
||||
if (!PACKET_get_length_prefixed_2(&identities, &identity)
|
||||
|| !PACKET_get_net_4(&identities, &ticket_agel)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->psk_find_session_cb != NULL
|
||||
&& !s->psk_find_session_cb(s, PACKET_data(&identity),
|
||||
PACKET_remaining(&identity),
|
||||
&sess)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sess != NULL) {
|
||||
/* We found a PSK */
|
||||
SSL_SESSION *sesstmp = ssl_session_dup(sess, 0);
|
||||
|
||||
if (sesstmp == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
SSL_SESSION_free(sess);
|
||||
sess = sesstmp;
|
||||
|
||||
/*
|
||||
* We've just been told to use this session for this context so
|
||||
* make sure the sid_ctx matches up.
|
||||
*/
|
||||
memcpy(sess->sid_ctx, s->sid_ctx, s->sid_ctx_length);
|
||||
sess->sid_ctx_length = s->sid_ctx_length;
|
||||
ext = 1;
|
||||
if (id == 0)
|
||||
s->ext.early_data_ok = 1;
|
||||
} else {
|
||||
uint32_t ticket_age = 0, now, agesec, agems;
|
||||
int ret = tls_decrypt_ticket(s, PACKET_data(&identity),
|
||||
PACKET_remaining(&identity), NULL, 0,
|
||||
&sess);
|
||||
|
||||
if (ret == TICKET_FATAL_ERR_MALLOC
|
||||
|| ret == TICKET_FATAL_ERR_OTHER) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (ret == TICKET_NO_DECRYPT)
|
||||
continue;
|
||||
|
||||
ticket_age = (uint32_t)ticket_agel;
|
||||
now = (uint32_t)time(NULL);
|
||||
agesec = now - (uint32_t)sess->time;
|
||||
agems = agesec * (uint32_t)1000;
|
||||
ticket_age -= sess->ext.tick_age_add;
|
||||
|
||||
/*
|
||||
* For simplicity we do our age calculations in seconds. If the
|
||||
* client does it in ms then it could appear that their ticket age
|
||||
* is longer than ours (our ticket age calculation should always be
|
||||
* slightly longer than the client's due to the network latency).
|
||||
* Therefore we add 1000ms to our age calculation to adjust for
|
||||
* rounding errors.
|
||||
*/
|
||||
if (id == 0
|
||||
&& sess->timeout >= (long)agesec
|
||||
&& agems / (uint32_t)1000 == agesec
|
||||
&& ticket_age <= agems + 1000
|
||||
&& ticket_age + TICKET_AGE_ALLOWANCE >= agems + 1000) {
|
||||
/*
|
||||
* Ticket age is within tolerance and not expired. We allow it
|
||||
* for early data
|
||||
*/
|
||||
s->ext.early_data_ok = 1;
|
||||
}
|
||||
}
|
||||
|
||||
md = ssl_md(sess->cipher->algorithm2);
|
||||
if (md != ssl_md(s->s3->tmp.new_cipher->algorithm2)) {
|
||||
/* The ciphersuite is not compatible with this session. */
|
||||
SSL_SESSION_free(sess);
|
||||
sess = NULL;
|
||||
s->ext.early_data_ok = 0;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (sess == NULL)
|
||||
return 1;
|
||||
|
||||
binderoffset = PACKET_data(pkt) - (const unsigned char *)s->init_buf->data;
|
||||
hashsize = EVP_MD_size(md);
|
||||
|
||||
if (!PACKET_get_length_prefixed_2(pkt, &binders)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 0; i <= id; i++) {
|
||||
if (!PACKET_get_length_prefixed_1(&binders, &binder)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (PACKET_remaining(&binder) != hashsize) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
goto err;
|
||||
}
|
||||
if (tls_psk_do_binder(s, md, (const unsigned char *)s->init_buf->data,
|
||||
binderoffset, PACKET_data(&binder), NULL, sess, 0,
|
||||
ext) != 1) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
sess->ext.tick_identity = id;
|
||||
|
||||
SSL_SESSION_free(s->session);
|
||||
s->session = sess;
|
||||
return 1;
|
||||
err:
|
||||
SSL_SESSION_free(sess);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tls_parse_ctos_post_handshake_auth(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
if (PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH,
|
||||
SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->post_handshake_auth = SSL_PHA_EXT_RECEIVED;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the server's renegotiation binding
|
||||
*/
|
||||
EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
if (!s->s3->send_connection_binding)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
/* Still add this even if SSL_OP_NO_RENEGOTIATION is set */
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u8(pkt)
|
||||
|| !WPACKET_memcpy(pkt, s->s3->previous_client_finished,
|
||||
s->s3->previous_client_finished_len)
|
||||
|| !WPACKET_memcpy(pkt, s->s3->previous_server_finished,
|
||||
s->s3->previous_server_finished_len)
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
if (s->hit || s->servername_done != 1
|
||||
|| s->session->ext.hostname == NULL)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
/* Add/include the server's max fragment len extension into ServerHello */
|
||||
EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
if (!USE_MAX_FRAGMENT_LENGTH_EXT(s->session))
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
/*-
|
||||
* 4 bytes for this extension type and extension length
|
||||
* 1 byte for the Max Fragment Length code value.
|
||||
*/
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_max_fragment_length)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u8(pkt, s->session->ext.max_fragment_len_mode)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
|
||||
unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
|
||||
int using_ecc = ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))
|
||||
&& (s->session->ext.ecpointformats != NULL);
|
||||
const unsigned char *plist;
|
||||
size_t plistlen;
|
||||
|
||||
if (!using_ecc)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
tls1_get_formatlist(s, &plist, &plistlen);
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, plist, plistlen)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
const uint16_t *groups;
|
||||
size_t numgroups, i, first = 1;
|
||||
|
||||
/* s->s3->group_id is non zero if we accepted a key_share */
|
||||
if (s->s3->group_id == 0)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
/* Get our list of supported groups */
|
||||
tls1_get_supported_groups(s, &groups, &numgroups);
|
||||
if (numgroups == 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
/* Copy group ID if supported */
|
||||
for (i = 0; i < numgroups; i++) {
|
||||
uint16_t group = groups[i];
|
||||
|
||||
if (tls_curve_allowed(s, group, SSL_SECOP_CURVE_SUPPORTED)) {
|
||||
if (first) {
|
||||
/*
|
||||
* Check if the client is already using our preferred group. If
|
||||
* so we don't need to add this extension
|
||||
*/
|
||||
if (s->s3->group_id == group)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
/* Add extension header */
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups)
|
||||
/* Sub-packet for supported_groups extension */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
first = 0;
|
||||
}
|
||||
if (!WPACKET_put_bytes_u16(pkt, group)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
if (!s->ext.ticket_expected || !tls_use_ticket(s)) {
|
||||
s->ext.ticket_expected = 0;
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
}
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
if (!s->ext.status_expected)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (SSL_IS_TLS13(s) && chainidx != 0)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* In TLSv1.3 we include the certificate status itself. In <= TLSv1.2 we
|
||||
* send back an empty extension, with the certificate status appearing as a
|
||||
* separate message
|
||||
*/
|
||||
if (SSL_IS_TLS13(s) && !tls_construct_cert_status_body(s, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
if (!WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
const unsigned char *npa;
|
||||
unsigned int npalen;
|
||||
int ret;
|
||||
int npn_seen = s->s3->npn_seen;
|
||||
|
||||
s->s3->npn_seen = 0;
|
||||
if (!npn_seen || s->ctx->ext.npn_advertised_cb == NULL)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
ret = s->ctx->ext.npn_advertised_cb(s, &npa, &npalen,
|
||||
s->ctx->ext.npn_advertised_cb_arg);
|
||||
if (ret == SSL_TLSEXT_ERR_OK) {
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, npa, npalen)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
s->s3->npn_seen = 1;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
EXT_RETURN tls_construct_stoc_alpn(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
if (s->s3->alpn_selected == NULL)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt,
|
||||
TLSEXT_TYPE_application_layer_protocol_negotiation)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, s->s3->alpn_selected,
|
||||
s->s3->alpn_selected_len)
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_ALPN, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
EXT_RETURN tls_construct_stoc_use_srtp(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
if (s->srtp_profile == NULL)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 2)
|
||||
|| !WPACKET_put_bytes_u16(pkt, s->srtp_profile->id)
|
||||
|| !WPACKET_put_bytes_u8(pkt, 0)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
if (!s->ext.use_etm)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
/*
|
||||
* Don't use encrypt_then_mac if AEAD or RC4 might want to disable
|
||||
* for other cases too.
|
||||
*/
|
||||
if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD
|
||||
|| s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4
|
||||
|| s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT
|
||||
|| s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) {
|
||||
s->ext.use_etm = 0;
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
}
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_ETM,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
if ((s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) == 0)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EMS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
if (!SSL_IS_TLS13(s))
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
/* TODO(TLS1.3): Update to remove the TLSv1.3 draft indicator */
|
||||
|| !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
#ifndef OPENSSL_NO_TLS1_3
|
||||
unsigned char *encodedPoint;
|
||||
size_t encoded_pt_len = 0;
|
||||
EVP_PKEY *ckey = s->s3->peer_tmp, *skey = NULL;
|
||||
|
||||
if (s->hello_retry_request == SSL_HRR_PENDING) {
|
||||
if (ckey != NULL) {
|
||||
/* Original key_share was acceptable so don't ask for another one */
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
}
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u16(pkt, s->s3->group_id)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
if (ckey == NULL) {
|
||||
/* No key_share received from client - must be resuming */
|
||||
if (!s->hit || !tls13_generate_handshake_secret(s, NULL, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
}
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u16(pkt, s->s3->group_id)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
skey = ssl_generate_pkey(ckey);
|
||||
if (skey == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
/* Generate encoding of server key */
|
||||
encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(skey, &encodedPoint);
|
||||
if (encoded_pt_len == 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
|
||||
ERR_R_EC_LIB);
|
||||
EVP_PKEY_free(skey);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
EVP_PKEY_free(skey);
|
||||
OPENSSL_free(encodedPoint);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
OPENSSL_free(encodedPoint);
|
||||
|
||||
/* This causes the crypto state to be updated based on the derived keys */
|
||||
s->s3->tmp.pkey = skey;
|
||||
if (ssl_derive(s, skey, ckey, 1) == 0) {
|
||||
/* SSLfatal() already called */
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
unsigned char *hashval1, *hashval2, *appcookie1, *appcookie2, *cookie;
|
||||
unsigned char *hmac, *hmac2;
|
||||
size_t startlen, ciphlen, totcookielen, hashlen, hmaclen;
|
||||
unsigned int appcookielen;
|
||||
EVP_MD_CTX *hctx;
|
||||
EVP_PKEY *pkey;
|
||||
int ret = EXT_RETURN_FAIL;
|
||||
|
||||
if (s->ctx->app_gen_cookie_cb == NULL
|
||||
|| (s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_cookie)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_get_total_written(pkt, &startlen)
|
||||
|| !WPACKET_reserve_bytes(pkt, MAX_COOKIE_SIZE, &cookie)
|
||||
|| !WPACKET_put_bytes_u16(pkt, COOKIE_STATE_FORMAT_VERSION)
|
||||
|| !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION)
|
||||
|| !WPACKET_put_bytes_u16(pkt, s->s3->group_id)
|
||||
|| !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt,
|
||||
&ciphlen)
|
||||
/* Is there a key_share extension present in this HRR? */
|
||||
|| !WPACKET_put_bytes_u8(pkt, s->s3->peer_tmp == NULL)
|
||||
|| !WPACKET_put_bytes_u32(pkt, (unsigned int)time(NULL))
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &hashval1)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the hash of the initial ClientHello. ssl_handshake_hash() operates
|
||||
* on raw buffers, so we first reserve sufficient bytes (above) and then
|
||||
* subsequently allocate them (below)
|
||||
*/
|
||||
if (!ssl3_digest_cached_records(s, 0)
|
||||
|| !ssl_handshake_hash(s, hashval1, EVP_MAX_MD_SIZE, &hashlen)) {
|
||||
/* SSLfatal() already called */
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
if (!WPACKET_allocate_bytes(pkt, hashlen, &hashval2)
|
||||
|| !ossl_assert(hashval1 == hashval2)
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_start_sub_packet_u8(pkt)
|
||||
|| !WPACKET_reserve_bytes(pkt, SSL_COOKIE_LENGTH, &appcookie1)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
/* Generate the application cookie */
|
||||
if (s->ctx->app_gen_cookie_cb(s, appcookie1, &appcookielen) == 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
|
||||
SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
if (!WPACKET_allocate_bytes(pkt, appcookielen, &appcookie2)
|
||||
|| !ossl_assert(appcookie1 == appcookie2)
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_get_total_written(pkt, &totcookielen)
|
||||
|| !WPACKET_reserve_bytes(pkt, SHA256_DIGEST_LENGTH, &hmac)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
hmaclen = SHA256_DIGEST_LENGTH;
|
||||
|
||||
totcookielen -= startlen;
|
||||
if (!ossl_assert(totcookielen <= MAX_COOKIE_SIZE - SHA256_DIGEST_LENGTH)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
/* HMAC the cookie */
|
||||
hctx = EVP_MD_CTX_create();
|
||||
pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
|
||||
s->session_ctx->ext.cookie_hmac_key,
|
||||
sizeof(s->session_ctx->ext.cookie_hmac_key));
|
||||
if (hctx == NULL || pkey == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_DigestSignInit(hctx, NULL, EVP_sha256(), NULL, pkey) <= 0
|
||||
|| EVP_DigestSign(hctx, hmac, &hmaclen, cookie,
|
||||
totcookielen) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!ossl_assert(totcookielen + hmaclen <= MAX_COOKIE_SIZE)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!WPACKET_allocate_bytes(pkt, hmaclen, &hmac2)
|
||||
|| !ossl_assert(hmac == hmac2)
|
||||
|| !ossl_assert(cookie == hmac - totcookielen)
|
||||
|| !WPACKET_close(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = EXT_RETURN_SENT;
|
||||
|
||||
err:
|
||||
EVP_MD_CTX_free(hctx);
|
||||
EVP_PKEY_free(pkey);
|
||||
return ret;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
const unsigned char cryptopro_ext[36] = {
|
||||
0xfd, 0xe8, /* 65000 */
|
||||
0x00, 0x20, /* 32 bytes length */
|
||||
0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85,
|
||||
0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06,
|
||||
0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08,
|
||||
0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17
|
||||
};
|
||||
|
||||
if (((s->s3->tmp.new_cipher->id & 0xFFFF) != 0x80
|
||||
&& (s->s3->tmp.new_cipher->id & 0xFFFF) != 0x81)
|
||||
|| (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG) == 0)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_memcpy(pkt, cryptopro_ext, sizeof(cryptopro_ext))) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx)
|
||||
{
|
||||
if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) {
|
||||
if (s->max_early_data == 0)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u32(pkt, s->max_early_data)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
|
||||
EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx)
|
||||
{
|
||||
if (!s->hit)
|
||||
return EXT_RETURN_NOT_SENT;
|
||||
|
||||
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk)
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_put_bytes_u16(pkt, s->session->ext.tick_identity)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_STOC_PSK, ERR_R_INTERNAL_ERROR);
|
||||
return EXT_RETURN_FAIL;
|
||||
}
|
||||
|
||||
return EXT_RETURN_SENT;
|
||||
}
|
||||
+215
-107
@@ -7,9 +7,11 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/rand.h>
|
||||
#include "../ssl_locl.h"
|
||||
#include "statem_locl.h"
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* This file implements the SSL/TLS/DTLS state machines.
|
||||
@@ -105,19 +107,39 @@ void ossl_statem_clear(SSL *s)
|
||||
*/
|
||||
void ossl_statem_set_renegotiate(SSL *s)
|
||||
{
|
||||
s->statem.state = MSG_FLOW_RENEGOTIATE;
|
||||
s->statem.in_init = 1;
|
||||
s->statem.request_state = TLS_ST_SW_HELLO_REQ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put the state machine into an error state. This is a permanent error for
|
||||
* the current connection.
|
||||
* Put the state machine into an error state and send an alert if appropriate.
|
||||
* This is a permanent error for the current connection.
|
||||
*/
|
||||
void ossl_statem_set_error(SSL *s)
|
||||
void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
|
||||
int line)
|
||||
{
|
||||
/* We shouldn't call SSLfatal() twice. Once is enough */
|
||||
assert(s->statem.state != MSG_FLOW_ERROR);
|
||||
s->statem.in_init = 1;
|
||||
s->statem.state = MSG_FLOW_ERROR;
|
||||
ERR_put_error(ERR_LIB_SSL, func, reason, file, line);
|
||||
if (al != SSL_AD_NO_ALERT)
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
}
|
||||
|
||||
/*
|
||||
* This macro should only be called if we are already expecting to be in
|
||||
* a fatal error state. We verify that we are, and set it if not (this would
|
||||
* indicate a bug).
|
||||
*/
|
||||
#define check_fatal(s, f) \
|
||||
do { \
|
||||
if (!ossl_assert((s)->statem.in_init \
|
||||
&& (s)->statem.state == MSG_FLOW_ERROR)) \
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, (f), \
|
||||
SSL_R_MISSING_FATAL); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Discover whether the current connection is in the error state.
|
||||
*
|
||||
@@ -151,6 +173,60 @@ void ossl_statem_set_in_handshake(SSL *s, int inhand)
|
||||
s->statem.in_handshake--;
|
||||
}
|
||||
|
||||
/* Are we in a sensible state to skip over unreadable early data? */
|
||||
int ossl_statem_skip_early_data(SSL *s)
|
||||
{
|
||||
if (s->ext.early_data != SSL_EARLY_DATA_REJECTED)
|
||||
return 0;
|
||||
|
||||
if (!s->server || s->statem.hand_state != TLS_ST_EARLY_DATA)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when we are in SSL_read*(), SSL_write*(), or SSL_accept()
|
||||
* /SSL_connect()/SSL_do_handshake(). Used to test whether we are in an early
|
||||
* data state and whether we should attempt to move the handshake on if so.
|
||||
* |sending| is 1 if we are attempting to send data (SSL_write*()), 0 if we are
|
||||
* attempting to read data (SSL_read*()), or -1 if we are in SSL_do_handshake()
|
||||
* or similar.
|
||||
*/
|
||||
void ossl_statem_check_finish_init(SSL *s, int sending)
|
||||
{
|
||||
if (sending == -1) {
|
||||
if (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END
|
||||
|| s->statem.hand_state == TLS_ST_EARLY_DATA) {
|
||||
ossl_statem_set_in_init(s, 1);
|
||||
if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
|
||||
/*
|
||||
* SSL_connect() or SSL_do_handshake() has been called directly.
|
||||
* We don't allow any more writing of early data.
|
||||
*/
|
||||
s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
|
||||
}
|
||||
}
|
||||
} else if (!s->server) {
|
||||
if ((sending && (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END
|
||||
|| s->statem.hand_state == TLS_ST_EARLY_DATA)
|
||||
&& s->early_data_state != SSL_EARLY_DATA_WRITING)
|
||||
|| (!sending && s->statem.hand_state == TLS_ST_EARLY_DATA)) {
|
||||
ossl_statem_set_in_init(s, 1);
|
||||
/*
|
||||
* SSL_write() has been called directly. We don't allow any more
|
||||
* writing of early data.
|
||||
*/
|
||||
if (sending && s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY)
|
||||
s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
|
||||
}
|
||||
} else {
|
||||
if (s->early_data_state == SSL_EARLY_DATA_FINISHED_READING
|
||||
&& s->statem.hand_state == TLS_ST_EARLY_DATA)
|
||||
ossl_statem_set_in_init(s, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ossl_statem_set_hello_verify_done(SSL *s)
|
||||
{
|
||||
s->statem.state = MSG_FLOW_UNINITED;
|
||||
@@ -189,10 +265,10 @@ static info_cb get_callback(SSL *s)
|
||||
|
||||
/*
|
||||
* The main message flow state machine. We start in the MSG_FLOW_UNINITED or
|
||||
* MSG_FLOW_RENEGOTIATE state and finish in MSG_FLOW_FINISHED. Valid states and
|
||||
* MSG_FLOW_FINISHED state and finish in MSG_FLOW_FINISHED. Valid states and
|
||||
* transitions are as follows:
|
||||
*
|
||||
* MSG_FLOW_UNINITED MSG_FLOW_RENEGOTIATE
|
||||
* MSG_FLOW_UNINITED MSG_FLOW_FINISHED
|
||||
* | |
|
||||
* +-----------------------+
|
||||
* v
|
||||
@@ -218,7 +294,6 @@ static info_cb get_callback(SSL *s)
|
||||
static int state_machine(SSL *s, int server)
|
||||
{
|
||||
BUF_MEM *buf = NULL;
|
||||
unsigned long Time = (unsigned long)time(NULL);
|
||||
void (*cb) (const SSL *ssl, int type, int val) = NULL;
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
int ret = -1;
|
||||
@@ -229,7 +304,6 @@ static int state_machine(SSL *s, int server)
|
||||
return -1;
|
||||
}
|
||||
|
||||
RAND_add(&Time, sizeof(Time), 0);
|
||||
ERR_clear_error();
|
||||
clear_sys_error();
|
||||
|
||||
@@ -237,7 +311,11 @@ static int state_machine(SSL *s, int server)
|
||||
|
||||
st->in_handshake++;
|
||||
if (!SSL_in_init(s) || SSL_in_before(s)) {
|
||||
if (!SSL_clear(s))
|
||||
/*
|
||||
* If we are stateless then we already called SSL_clear() - don't do
|
||||
* it again and clear the STATELESS flag itself.
|
||||
*/
|
||||
if ((s->s3->flags & TLS1_FLAGS_STATELESS) == 0 && !SSL_clear(s))
|
||||
return -1;
|
||||
}
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
@@ -251,60 +329,54 @@ static int state_machine(SSL *s, int server)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef OPENSSL_NO_HEARTBEATS
|
||||
/*
|
||||
* If we're awaiting a HeartbeatResponse, pretend we already got and
|
||||
* don't await it anymore, because Heartbeats don't make sense during
|
||||
* handshakes anyway.
|
||||
*/
|
||||
if (s->tlsext_hb_pending) {
|
||||
if (SSL_IS_DTLS(s))
|
||||
dtls1_stop_timer(s);
|
||||
s->tlsext_hb_pending = 0;
|
||||
s->tlsext_hb_seq++;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialise state machine */
|
||||
|
||||
if (st->state == MSG_FLOW_RENEGOTIATE) {
|
||||
s->renegotiate = 1;
|
||||
if (!server)
|
||||
s->ctx->stats.sess_connect_renegotiate++;
|
||||
}
|
||||
|
||||
if (st->state == MSG_FLOW_UNINITED || st->state == MSG_FLOW_RENEGOTIATE) {
|
||||
if (st->state == MSG_FLOW_UNINITED
|
||||
|| st->state == MSG_FLOW_FINISHED) {
|
||||
if (st->state == MSG_FLOW_UNINITED) {
|
||||
st->hand_state = TLS_ST_BEFORE;
|
||||
st->request_state = TLS_ST_BEFORE;
|
||||
}
|
||||
|
||||
s->server = server;
|
||||
if (cb != NULL)
|
||||
cb(s, SSL_CB_HANDSHAKE_START, 1);
|
||||
|
||||
/*
|
||||
* Fatal errors in this block don't send an alert because we have
|
||||
* failed to even initialise properly. Sending an alert is probably
|
||||
* doomed to failure.
|
||||
*/
|
||||
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
if ((s->version & 0xff00) != (DTLS1_VERSION & 0xff00) &&
|
||||
(server || (s->version & 0xff00) != (DTLS1_BAD_VER & 0xff00))) {
|
||||
SSLerr(SSL_F_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if ((s->version >> 8) != SSL3_VERSION_MAJOR) {
|
||||
SSLerr(SSL_F_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ssl_security(s, SSL_SECOP_VERSION, 0, s->version, NULL)) {
|
||||
SSLerr(SSL_F_STATE_MACHINE, SSL_R_VERSION_TOO_LOW);
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (s->init_buf == NULL) {
|
||||
if ((buf = BUF_MEM_new()) == NULL) {
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto end;
|
||||
}
|
||||
if (!BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto end;
|
||||
}
|
||||
s->init_buf = buf;
|
||||
@@ -312,6 +384,8 @@ static int state_machine(SSL *s, int server)
|
||||
}
|
||||
|
||||
if (!ssl3_setup_buffers(s)) {
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto end;
|
||||
}
|
||||
s->init_num = 0;
|
||||
@@ -329,65 +403,24 @@ static int state_machine(SSL *s, int server)
|
||||
if (!SSL_IS_DTLS(s) || !BIO_dgram_is_sctp(SSL_get_wbio(s)))
|
||||
#endif
|
||||
if (!ssl_init_wbio_buffer(s)) {
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!server || st->state != MSG_FLOW_RENEGOTIATE) {
|
||||
if (!ssl3_init_finished_mac(s)) {
|
||||
ossl_statem_set_error(s);
|
||||
if ((SSL_in_before(s))
|
||||
|| s->renegotiate) {
|
||||
if (!tls_setup_handshake(s)) {
|
||||
/* SSLfatal() already called */
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (server) {
|
||||
if (st->state != MSG_FLOW_RENEGOTIATE) {
|
||||
s->ctx->stats.sess_accept++;
|
||||
} else if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
|
||||
/*
|
||||
* Shouldn't happen? The record layer should have prevented this
|
||||
*/
|
||||
SSLerr(SSL_F_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
ossl_statem_set_error(s);
|
||||
goto end;
|
||||
} else if (!s->s3->send_connection_binding &&
|
||||
!(s->options &
|
||||
SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)) {
|
||||
/*
|
||||
* Server attempting to renegotiate with client that doesn't
|
||||
* support secure renegotiation.
|
||||
*/
|
||||
SSLerr(SSL_F_STATE_MACHINE,
|
||||
SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
|
||||
ossl_statem_set_error(s);
|
||||
goto end;
|
||||
} else {
|
||||
/*
|
||||
* st->state == MSG_FLOW_RENEGOTIATE, we will just send a
|
||||
* HelloRequest
|
||||
*/
|
||||
s->ctx->stats.sess_accept_renegotiate++;
|
||||
}
|
||||
|
||||
s->s3->tmp.cert_request = 0;
|
||||
} else {
|
||||
s->ctx->stats.sess_connect++;
|
||||
|
||||
/* mark client_random uninitialized */
|
||||
memset(s->s3->client_random, 0, sizeof(s->s3->client_random));
|
||||
s->hit = 0;
|
||||
|
||||
s->s3->tmp.cert_req = 0;
|
||||
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
st->use_timer = 1;
|
||||
}
|
||||
if (SSL_IS_FIRST_HANDSHAKE(s))
|
||||
st->read_state_first_init = 1;
|
||||
}
|
||||
|
||||
st->state = MSG_FLOW_WRITING;
|
||||
init_write_state_machine(s);
|
||||
st->read_state_first_init = 1;
|
||||
}
|
||||
|
||||
while (st->state != MSG_FLOW_FINISHED) {
|
||||
@@ -413,12 +446,12 @@ static int state_machine(SSL *s, int server)
|
||||
}
|
||||
} else {
|
||||
/* Error */
|
||||
ossl_statem_set_error(s);
|
||||
check_fatal(s, SSL_F_STATE_MACHINE);
|
||||
SSLerr(SSL_F_STATE_MACHINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
st->state = MSG_FLOW_UNINITED;
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
@@ -500,12 +533,12 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
int ret, mt;
|
||||
unsigned long len = 0;
|
||||
size_t len = 0;
|
||||
int (*transition) (SSL *s, int mt);
|
||||
PACKET pkt;
|
||||
MSG_PROCESS_RETURN(*process_message) (SSL *s, PACKET *pkt);
|
||||
WORK_STATE(*post_process_message) (SSL *s, WORK_STATE wst);
|
||||
unsigned long (*max_message_size) (SSL *s);
|
||||
size_t (*max_message_size) (SSL *s);
|
||||
void (*cb) (const SSL *ssl, int type, int val) = NULL;
|
||||
|
||||
cb = get_callback(s);
|
||||
@@ -557,13 +590,13 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
|
||||
* to that state if so
|
||||
*/
|
||||
if (!transition(s, mt)) {
|
||||
ossl_statem_set_error(s);
|
||||
check_fatal(s, SSL_F_READ_STATE_MACHINE);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
|
||||
if (s->s3->tmp.message_size > max_message_size(s)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
|
||||
SSLerr(SSL_F_READ_STATE_MACHINE, SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_READ_STATE_MACHINE,
|
||||
SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
|
||||
@@ -572,8 +605,8 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
|
||||
&& s->s3->tmp.message_size > 0
|
||||
&& !grow_init_buf(s, s->s3->tmp.message_size
|
||||
+ SSL3_HM_HEADER_LENGTH)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
SSLerr(SSL_F_READ_STATE_MACHINE, ERR_R_BUF_LIB);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
|
||||
ERR_R_BUF_LIB);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
|
||||
@@ -592,8 +625,8 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
|
||||
|
||||
s->first_packet = 0;
|
||||
if (!PACKET_buf_init(&pkt, s->init_msg, len)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
SSLerr(SSL_F_READ_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
ret = process_message(s, &pkt);
|
||||
@@ -603,6 +636,7 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
|
||||
|
||||
switch (ret) {
|
||||
case MSG_PROCESS_ERROR:
|
||||
check_fatal(s, SSL_F_READ_STATE_MACHINE);
|
||||
return SUB_STATE_ERROR;
|
||||
|
||||
case MSG_PROCESS_FINISHED_READING:
|
||||
@@ -625,7 +659,12 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
|
||||
case READ_STATE_POST_PROCESS:
|
||||
st->read_state_work = post_process_message(s, st->read_state_work);
|
||||
switch (st->read_state_work) {
|
||||
default:
|
||||
case WORK_ERROR:
|
||||
check_fatal(s, SSL_F_READ_STATE_MACHINE);
|
||||
/* Fall through */
|
||||
case WORK_MORE_A:
|
||||
case WORK_MORE_B:
|
||||
case WORK_MORE_C:
|
||||
return SUB_STATE_ERROR;
|
||||
|
||||
case WORK_FINISHED_CONTINUE:
|
||||
@@ -642,9 +681,8 @@ static SUB_STATE_RETURN read_state_machine(SSL *s)
|
||||
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
SSLerr(SSL_F_READ_STATE_MACHINE, ERR_R_INTERNAL_ERROR);
|
||||
ossl_statem_set_error(s);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -716,8 +754,13 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
|
||||
WRITE_TRAN(*transition) (SSL *s);
|
||||
WORK_STATE(*pre_work) (SSL *s, WORK_STATE wst);
|
||||
WORK_STATE(*post_work) (SSL *s, WORK_STATE wst);
|
||||
int (*construct_message) (SSL *s);
|
||||
int (*get_construct_message_f) (SSL *s, WPACKET *pkt,
|
||||
int (**confunc) (SSL *s, WPACKET *pkt),
|
||||
int *mt);
|
||||
void (*cb) (const SSL *ssl, int type, int val) = NULL;
|
||||
int (*confunc) (SSL *s, WPACKET *pkt);
|
||||
int mt;
|
||||
WPACKET pkt;
|
||||
|
||||
cb = get_callback(s);
|
||||
|
||||
@@ -725,12 +768,12 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
|
||||
transition = ossl_statem_server_write_transition;
|
||||
pre_work = ossl_statem_server_pre_work;
|
||||
post_work = ossl_statem_server_post_work;
|
||||
construct_message = ossl_statem_server_construct_message;
|
||||
get_construct_message_f = ossl_statem_server_construct_message;
|
||||
} else {
|
||||
transition = ossl_statem_client_write_transition;
|
||||
pre_work = ossl_statem_client_pre_work;
|
||||
post_work = ossl_statem_client_post_work;
|
||||
construct_message = ossl_statem_client_construct_message;
|
||||
get_construct_message_f = ossl_statem_client_construct_message;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
@@ -753,14 +796,20 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
|
||||
return SUB_STATE_FINISHED;
|
||||
break;
|
||||
|
||||
default:
|
||||
case WRITE_TRAN_ERROR:
|
||||
check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case WRITE_STATE_PRE_WORK:
|
||||
switch (st->write_state_work = pre_work(s, st->write_state_work)) {
|
||||
default:
|
||||
case WORK_ERROR:
|
||||
check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
|
||||
/* Fall through */
|
||||
case WORK_MORE_A:
|
||||
case WORK_MORE_B:
|
||||
case WORK_MORE_C:
|
||||
return SUB_STATE_ERROR;
|
||||
|
||||
case WORK_FINISHED_CONTINUE:
|
||||
@@ -770,8 +819,35 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
|
||||
case WORK_FINISHED_STOP:
|
||||
return SUB_STATE_END_HANDSHAKE;
|
||||
}
|
||||
if (construct_message(s) == 0)
|
||||
if (!get_construct_message_f(s, &pkt, &confunc, &mt)) {
|
||||
/* SSLfatal() already called */
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
if (mt == SSL3_MT_DUMMY) {
|
||||
/* Skip construction and sending. This isn't a "real" state */
|
||||
st->write_state = WRITE_STATE_POST_WORK;
|
||||
st->write_state_work = WORK_MORE_A;
|
||||
break;
|
||||
}
|
||||
if (!WPACKET_init(&pkt, s->init_buf)
|
||||
|| !ssl_set_handshake_header(s, &pkt, mt)) {
|
||||
WPACKET_cleanup(&pkt);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
if (confunc != NULL && !confunc(s, &pkt)) {
|
||||
WPACKET_cleanup(&pkt);
|
||||
check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
if (!ssl_close_construct_packet(s, &pkt, mt)
|
||||
|| !WPACKET_finish(&pkt)) {
|
||||
WPACKET_cleanup(&pkt);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
|
||||
/* Fall through */
|
||||
|
||||
@@ -789,7 +865,12 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
|
||||
|
||||
case WRITE_STATE_POST_WORK:
|
||||
switch (st->write_state_work = post_work(s, st->write_state_work)) {
|
||||
default:
|
||||
case WORK_ERROR:
|
||||
check_fatal(s, SSL_F_WRITE_STATE_MACHINE);
|
||||
/* Fall through */
|
||||
case WORK_MORE_A:
|
||||
case WORK_MORE_B:
|
||||
case WORK_MORE_C:
|
||||
return SUB_STATE_ERROR;
|
||||
|
||||
case WORK_FINISHED_CONTINUE:
|
||||
@@ -802,6 +883,8 @@ static SUB_STATE_RETURN write_state_machine(SSL *s)
|
||||
break;
|
||||
|
||||
default:
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return SUB_STATE_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -823,7 +906,7 @@ int statem_flush(SSL *s)
|
||||
|
||||
/*
|
||||
* Called by the record layer to determine whether application data is
|
||||
* allowed to be sent in the current handshake state or not.
|
||||
* allowed to be received in the current handshake state or not.
|
||||
*
|
||||
* Return values are:
|
||||
* 1: Yes (application data allowed)
|
||||
@@ -833,7 +916,7 @@ int ossl_statem_app_data_allowed(SSL *s)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
if (st->state == MSG_FLOW_UNINITED || st->state == MSG_FLOW_RENEGOTIATE)
|
||||
if (st->state == MSG_FLOW_UNINITED)
|
||||
return 0;
|
||||
|
||||
if (!s->s3->in_read_app_data || (s->s3->total_renegotiations == 0))
|
||||
@@ -858,3 +941,28 @@ int ossl_statem_app_data_allowed(SSL *s)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function returns 1 if TLS exporter is ready to export keying
|
||||
* material, or 0 if otherwise.
|
||||
*/
|
||||
int ossl_statem_export_allowed(SSL *s)
|
||||
{
|
||||
return s->s3->previous_server_finished_len != 0
|
||||
&& s->statem.hand_state != TLS_ST_SW_FINISHED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 1 if early TLS exporter is ready to export keying material,
|
||||
* or 0 if otherwise.
|
||||
*/
|
||||
int ossl_statem_export_early_allowed(SSL *s)
|
||||
{
|
||||
/*
|
||||
* The early exporter secret is only present on the server if we
|
||||
* have accepted early_data. It is present on the client as long
|
||||
* as we have sent early_data.
|
||||
*/
|
||||
return s->ext.early_data == SSL_EARLY_DATA_ACCEPTED
|
||||
|| (!s->server && s->ext.early_data != SSL_EARLY_DATA_NOT_SENT);
|
||||
}
|
||||
+28
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -27,7 +27,9 @@ typedef enum {
|
||||
/* We're working on phase A */
|
||||
WORK_MORE_A,
|
||||
/* We're working on phase B */
|
||||
WORK_MORE_B
|
||||
WORK_MORE_B,
|
||||
/* We're working on phase C */
|
||||
WORK_MORE_C
|
||||
} WORK_STATE;
|
||||
|
||||
/* Write transition return codes */
|
||||
@@ -46,8 +48,6 @@ typedef enum {
|
||||
MSG_FLOW_UNINITED,
|
||||
/* A permanent error with this connection */
|
||||
MSG_FLOW_ERROR,
|
||||
/* We are about to renegotiate */
|
||||
MSG_FLOW_RENEGOTIATE,
|
||||
/* We are reading messages */
|
||||
MSG_FLOW_READING,
|
||||
/* We are writing messages */
|
||||
@@ -86,10 +86,17 @@ struct ossl_statem_st {
|
||||
READ_STATE read_state;
|
||||
WORK_STATE read_state_work;
|
||||
OSSL_HANDSHAKE_STATE hand_state;
|
||||
/* The handshake state requested by an API call (e.g. HelloRequest) */
|
||||
OSSL_HANDSHAKE_STATE request_state;
|
||||
int in_init;
|
||||
int read_state_first_init;
|
||||
/* true when we are actually in SSL_accept() or SSL_connect() */
|
||||
int in_handshake;
|
||||
/*
|
||||
* True when are processing a "real" handshake that needs cleaning up (not
|
||||
* just a HelloRequest or similar).
|
||||
*/
|
||||
int cleanuphand;
|
||||
/* Should we skip the CertificateVerify message? */
|
||||
unsigned int no_cert_verify;
|
||||
int use_timer;
|
||||
@@ -107,10 +114,26 @@ __owur int ossl_statem_accept(SSL *s);
|
||||
__owur int ossl_statem_connect(SSL *s);
|
||||
void ossl_statem_clear(SSL *s);
|
||||
void ossl_statem_set_renegotiate(SSL *s);
|
||||
void ossl_statem_set_error(SSL *s);
|
||||
void ossl_statem_fatal(SSL *s, int al, int func, int reason, const char *file,
|
||||
int line);
|
||||
# define SSL_AD_NO_ALERT -1
|
||||
# ifndef OPENSSL_NO_ERR
|
||||
# define SSLfatal(s, al, f, r) ossl_statem_fatal((s), (al), (f), (r), \
|
||||
OPENSSL_FILE, OPENSSL_LINE)
|
||||
# else
|
||||
# define SSLfatal(s, al, f, r) ossl_statem_fatal((s), (al), (f), (r), NULL, 0)
|
||||
# endif
|
||||
|
||||
int ossl_statem_in_error(const SSL *s);
|
||||
void ossl_statem_set_in_init(SSL *s, int init);
|
||||
int ossl_statem_get_in_handshake(SSL *s);
|
||||
void ossl_statem_set_in_handshake(SSL *s, int inhand);
|
||||
__owur int ossl_statem_skip_early_data(SSL *s);
|
||||
void ossl_statem_check_finish_init(SSL *s, int send);
|
||||
void ossl_statem_set_hello_verify_done(SSL *s);
|
||||
__owur int ossl_statem_app_data_allowed(SSL *s);
|
||||
__owur int ossl_statem_export_allowed(SSL *s);
|
||||
__owur int ossl_statem_export_early_allowed(SSL *s);
|
||||
|
||||
/* Flush the write BIO */
|
||||
int statem_flush(SSL *s);
|
||||
+1989
-1168
@@ -1,5 +1,7 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||
* Copyright 2005 Nokia. All rights reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -7,47 +9,8 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* Portions of the attached software ("Contribution") are developed by
|
||||
* SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
|
||||
*
|
||||
* The Contribution is licensed pursuant to the OpenSSL open source
|
||||
* license provided above.
|
||||
*
|
||||
* ECC cipher suite support in OpenSSL originally written by
|
||||
* Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
|
||||
*
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright 2005 Nokia. All rights reserved.
|
||||
*
|
||||
* The portions of the attached software ("Contribution") is developed by
|
||||
* Nokia Corporation and is licensed pursuant to the OpenSSL open source
|
||||
* license.
|
||||
*
|
||||
* The Contribution, originally written by Mika Kousa and Pasi Eronen of
|
||||
* Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
|
||||
* support (see RFC 4279) to OpenSSL.
|
||||
*
|
||||
* No patent licenses or other rights except those expressly stated in
|
||||
* the OpenSSL open source license shall be deemed granted or received
|
||||
* expressly, by implication, estoppel, or otherwise.
|
||||
*
|
||||
* No assurances are provided by Nokia that the Contribution does not
|
||||
* infringe the patent or other intellectual property rights of any third
|
||||
* party or that the license provides you with all the necessary rights
|
||||
* to make use of the Contribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
|
||||
* ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
|
||||
* SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
|
||||
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
|
||||
* OTHERWISE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "../ssl_locl.h"
|
||||
#include "statem_locl.h"
|
||||
#include <openssl/buffer.h>
|
||||
@@ -59,11 +22,13 @@
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/engine.h>
|
||||
|
||||
static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s, PACKET *pkt);
|
||||
static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt);
|
||||
|
||||
static ossl_inline int cert_req_allowed(SSL *s);
|
||||
static int key_exchange_expected(SSL *s);
|
||||
static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b);
|
||||
static int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
|
||||
unsigned char *p);
|
||||
WPACKET *pkt);
|
||||
|
||||
/*
|
||||
* Is a CertificateRequest message allowed at the moment or not?
|
||||
@@ -106,22 +71,150 @@ static int key_exchange_expected(SSL *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ossl_statem_client_read_transition() encapsulates the logic for the allowed
|
||||
* handshake state transitions when a TLS1.3 client is reading messages from the
|
||||
* server. The message type that the server has sent is provided in |mt|. The
|
||||
* current state is in |s->statem.hand_state|.
|
||||
*
|
||||
* Return values are 1 for success (transition allowed) and 0 on error
|
||||
* (transition not allowed)
|
||||
*/
|
||||
static int ossl_statem_client13_read_transition(SSL *s, int mt)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
/*
|
||||
* Note: There is no case for TLS_ST_CW_CLNT_HELLO, because we haven't
|
||||
* yet negotiated TLSv1.3 at that point so that is handled by
|
||||
* ossl_statem_client_read_transition()
|
||||
*/
|
||||
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case TLS_ST_CW_CLNT_HELLO:
|
||||
/*
|
||||
* This must a ClientHello following a HelloRetryRequest, so the only
|
||||
* thing we can get now is a ServerHello.
|
||||
*/
|
||||
if (mt == SSL3_MT_SERVER_HELLO) {
|
||||
st->hand_state = TLS_ST_CR_SRVR_HELLO;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case TLS_ST_CR_SRVR_HELLO:
|
||||
if (mt == SSL3_MT_ENCRYPTED_EXTENSIONS) {
|
||||
st->hand_state = TLS_ST_CR_ENCRYPTED_EXTENSIONS;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case TLS_ST_CR_ENCRYPTED_EXTENSIONS:
|
||||
if (s->hit) {
|
||||
if (mt == SSL3_MT_FINISHED) {
|
||||
st->hand_state = TLS_ST_CR_FINISHED;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (mt == SSL3_MT_CERTIFICATE_REQUEST) {
|
||||
st->hand_state = TLS_ST_CR_CERT_REQ;
|
||||
return 1;
|
||||
}
|
||||
if (mt == SSL3_MT_CERTIFICATE) {
|
||||
st->hand_state = TLS_ST_CR_CERT;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TLS_ST_CR_CERT_REQ:
|
||||
if (mt == SSL3_MT_CERTIFICATE) {
|
||||
st->hand_state = TLS_ST_CR_CERT;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case TLS_ST_CR_CERT:
|
||||
if (mt == SSL3_MT_CERTIFICATE_VERIFY) {
|
||||
st->hand_state = TLS_ST_CR_CERT_VRFY;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case TLS_ST_CR_CERT_VRFY:
|
||||
if (mt == SSL3_MT_FINISHED) {
|
||||
st->hand_state = TLS_ST_CR_FINISHED;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case TLS_ST_OK:
|
||||
if (mt == SSL3_MT_NEWSESSION_TICKET) {
|
||||
st->hand_state = TLS_ST_CR_SESSION_TICKET;
|
||||
return 1;
|
||||
}
|
||||
if (mt == SSL3_MT_KEY_UPDATE) {
|
||||
st->hand_state = TLS_ST_CR_KEY_UPDATE;
|
||||
return 1;
|
||||
}
|
||||
if (mt == SSL3_MT_CERTIFICATE_REQUEST) {
|
||||
#if DTLS_MAX_VERSION != DTLS1_2_VERSION
|
||||
# error TODO(DTLS1.3): Restore digest for PHA before adding message.
|
||||
#endif
|
||||
if (!SSL_IS_DTLS(s) && s->post_handshake_auth == SSL_PHA_EXT_SENT) {
|
||||
s->post_handshake_auth = SSL_PHA_REQUESTED;
|
||||
/*
|
||||
* In TLS, this is called before the message is added to the
|
||||
* digest. In DTLS, this is expected to be called after adding
|
||||
* to the digest. Either move the digest restore, or add the
|
||||
* message here after the swap, or do it after the clientFinished?
|
||||
*/
|
||||
if (!tls13_restore_handshake_digest_for_pha(s)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
st->hand_state = TLS_ST_CR_CERT_REQ;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* No valid transition found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ossl_statem_client_read_transition() encapsulates the logic for the allowed
|
||||
* handshake state transitions when the client is reading messages from the
|
||||
* server. The message type that the server has sent is provided in |mt|. The
|
||||
* current state is in |s->statem.hand_state|.
|
||||
*
|
||||
* Return values are:
|
||||
* 1: Success (transition allowed)
|
||||
* 0: Error (transition not allowed)
|
||||
* Return values are 1 for success (transition allowed) and 0 on error
|
||||
* (transition not allowed)
|
||||
*/
|
||||
int ossl_statem_client_read_transition(SSL *s, int mt)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
int ske_expected;
|
||||
|
||||
/*
|
||||
* Note that after writing the first ClientHello we don't know what version
|
||||
* we are going to negotiate yet, so we don't take this branch until later.
|
||||
*/
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
if (!ossl_statem_client13_read_transition(s, mt))
|
||||
goto err;
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case TLS_ST_CW_CLNT_HELLO:
|
||||
if (mt == SSL3_MT_SERVER_HELLO) {
|
||||
st->hand_state = TLS_ST_CR_SRVR_HELLO;
|
||||
@@ -136,9 +229,21 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
|
||||
}
|
||||
break;
|
||||
|
||||
case TLS_ST_EARLY_DATA:
|
||||
/*
|
||||
* We've not actually selected TLSv1.3 yet, but we have sent early
|
||||
* data. The only thing allowed now is a ServerHello or a
|
||||
* HelloRetryRequest.
|
||||
*/
|
||||
if (mt == SSL3_MT_SERVER_HELLO) {
|
||||
st->hand_state = TLS_ST_CR_SRVR_HELLO;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case TLS_ST_CR_SRVR_HELLO:
|
||||
if (s->hit) {
|
||||
if (s->tlsext_ticket_expected) {
|
||||
if (s->ext.ticket_expected) {
|
||||
if (mt == SSL3_MT_NEWSESSION_TICKET) {
|
||||
st->hand_state = TLS_ST_CR_SESSION_TICKET;
|
||||
return 1;
|
||||
@@ -152,8 +257,8 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
|
||||
st->hand_state = DTLS_ST_CR_HELLO_VERIFY_REQUEST;
|
||||
return 1;
|
||||
} else if (s->version >= TLS1_VERSION
|
||||
&& s->tls_session_secret_cb != NULL
|
||||
&& s->session->tlsext_tick != NULL
|
||||
&& s->ext.session_secret_cb != NULL
|
||||
&& s->session->ext.tick != NULL
|
||||
&& mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
|
||||
/*
|
||||
* Normally, we can tell if the server is resuming the session
|
||||
@@ -195,9 +300,9 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
|
||||
case TLS_ST_CR_CERT:
|
||||
/*
|
||||
* The CertificateStatus message is optional even if
|
||||
* |tlsext_status_expected| is set
|
||||
* |ext.status_expected| is set
|
||||
*/
|
||||
if (s->tlsext_status_expected && mt == SSL3_MT_CERTIFICATE_STATUS) {
|
||||
if (s->ext.status_expected && mt == SSL3_MT_CERTIFICATE_STATUS) {
|
||||
st->hand_state = TLS_ST_CR_CERT_STATUS;
|
||||
return 1;
|
||||
}
|
||||
@@ -234,7 +339,7 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
|
||||
break;
|
||||
|
||||
case TLS_ST_CW_FINISHED:
|
||||
if (s->tlsext_ticket_expected) {
|
||||
if (s->ext.ticket_expected) {
|
||||
if (mt == SSL3_MT_NEWSESSION_TICKET) {
|
||||
st->hand_state = TLS_ST_CR_SESSION_TICKET;
|
||||
return 1;
|
||||
@@ -259,39 +364,186 @@ int ossl_statem_client_read_transition(SSL *s, int mt)
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
case TLS_ST_OK:
|
||||
if (mt == SSL3_MT_HELLO_REQUEST) {
|
||||
st->hand_state = TLS_ST_CR_HELLO_REQ;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
err:
|
||||
/* No valid transition found */
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL3_AD_UNEXPECTED_MESSAGE);
|
||||
SSLerr(SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION, SSL_R_UNEXPECTED_MESSAGE);
|
||||
SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE,
|
||||
SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION,
|
||||
SSL_R_UNEXPECTED_MESSAGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* client_write_transition() works out what handshake state to move to next
|
||||
* when the client is writing messages to be sent to the server.
|
||||
* ossl_statem_client13_write_transition() works out what handshake state to
|
||||
* move to next when the TLSv1.3 client is writing messages to be sent to the
|
||||
* server.
|
||||
*/
|
||||
static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
/*
|
||||
* Note: There are no cases for TLS_ST_BEFORE because we haven't negotiated
|
||||
* TLSv1.3 yet at that point. They are handled by
|
||||
* ossl_statem_client_write_transition().
|
||||
*/
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return WRITE_TRAN_ERROR;
|
||||
|
||||
case TLS_ST_CR_CERT_REQ:
|
||||
if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
|
||||
st->hand_state = TLS_ST_CW_CERT;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
}
|
||||
/* Shouldn't happen - same as default case */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return WRITE_TRAN_ERROR;
|
||||
|
||||
case TLS_ST_CR_FINISHED:
|
||||
if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY
|
||||
|| s->early_data_state == SSL_EARLY_DATA_FINISHED_WRITING)
|
||||
st->hand_state = TLS_ST_PENDING_EARLY_DATA_END;
|
||||
else if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
|
||||
&& s->hello_retry_request == SSL_HRR_NONE)
|
||||
st->hand_state = TLS_ST_CW_CHANGE;
|
||||
else
|
||||
st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
|
||||
: TLS_ST_CW_FINISHED;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_PENDING_EARLY_DATA_END:
|
||||
if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
|
||||
st->hand_state = TLS_ST_CW_END_OF_EARLY_DATA;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
}
|
||||
/* Fall through */
|
||||
|
||||
case TLS_ST_CW_END_OF_EARLY_DATA:
|
||||
case TLS_ST_CW_CHANGE:
|
||||
st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
|
||||
: TLS_ST_CW_FINISHED;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_CW_CERT:
|
||||
/* If a non-empty Certificate we also send CertificateVerify */
|
||||
st->hand_state = (s->s3->tmp.cert_req == 1) ? TLS_ST_CW_CERT_VRFY
|
||||
: TLS_ST_CW_FINISHED;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_CW_CERT_VRFY:
|
||||
st->hand_state = TLS_ST_CW_FINISHED;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_CR_KEY_UPDATE:
|
||||
if (s->key_update != SSL_KEY_UPDATE_NONE) {
|
||||
st->hand_state = TLS_ST_CW_KEY_UPDATE;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
}
|
||||
/* Fall through */
|
||||
|
||||
case TLS_ST_CW_KEY_UPDATE:
|
||||
case TLS_ST_CR_SESSION_TICKET:
|
||||
case TLS_ST_CW_FINISHED:
|
||||
st->hand_state = TLS_ST_OK;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_OK:
|
||||
if (s->key_update != SSL_KEY_UPDATE_NONE) {
|
||||
st->hand_state = TLS_ST_CW_KEY_UPDATE;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
}
|
||||
|
||||
/* Try to read from the server instead */
|
||||
return WRITE_TRAN_FINISHED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ossl_statem_client_write_transition() works out what handshake state to
|
||||
* move to next when the client is writing messages to be sent to the server.
|
||||
*/
|
||||
WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
/*
|
||||
* Note that immediately before/after a ClientHello we don't know what
|
||||
* version we are going to negotiate yet, so we don't take this branch until
|
||||
* later
|
||||
*/
|
||||
if (SSL_IS_TLS13(s))
|
||||
return ossl_statem_client13_write_transition(s);
|
||||
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return WRITE_TRAN_ERROR;
|
||||
|
||||
case TLS_ST_OK:
|
||||
/* Renegotiation - fall through */
|
||||
if (!s->renegotiate) {
|
||||
/*
|
||||
* We haven't requested a renegotiation ourselves so we must have
|
||||
* received a message from the server. Better read it.
|
||||
*/
|
||||
return WRITE_TRAN_FINISHED;
|
||||
}
|
||||
/* Renegotiation */
|
||||
/* fall thru */
|
||||
case TLS_ST_BEFORE:
|
||||
st->hand_state = TLS_ST_CW_CLNT_HELLO;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_CW_CLNT_HELLO:
|
||||
if (s->early_data_state == SSL_EARLY_DATA_CONNECTING) {
|
||||
/*
|
||||
* We are assuming this is a TLSv1.3 connection, although we haven't
|
||||
* actually selected a version yet.
|
||||
*/
|
||||
if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0)
|
||||
st->hand_state = TLS_ST_CW_CHANGE;
|
||||
else
|
||||
st->hand_state = TLS_ST_EARLY_DATA;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
}
|
||||
/*
|
||||
* No transition at the end of writing because we don't know what
|
||||
* we will be sent
|
||||
*/
|
||||
return WRITE_TRAN_FINISHED;
|
||||
|
||||
case TLS_ST_CR_SRVR_HELLO:
|
||||
/*
|
||||
* We only get here in TLSv1.3. We just received an HRR, so issue a
|
||||
* CCS unless middlebox compat mode is off, or we already issued one
|
||||
* because we did early data.
|
||||
*/
|
||||
if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
|
||||
&& s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING)
|
||||
st->hand_state = TLS_ST_CW_CHANGE;
|
||||
else
|
||||
st->hand_state = TLS_ST_CW_CLNT_HELLO;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_EARLY_DATA:
|
||||
return WRITE_TRAN_FINISHED;
|
||||
|
||||
case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
|
||||
st->hand_state = TLS_ST_CW_CLNT_HELLO;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
@@ -333,14 +585,20 @@ WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_CW_CHANGE:
|
||||
if (s->hello_retry_request == SSL_HRR_PENDING) {
|
||||
st->hand_state = TLS_ST_CW_CLNT_HELLO;
|
||||
} else if (s->early_data_state == SSL_EARLY_DATA_CONNECTING) {
|
||||
st->hand_state = TLS_ST_EARLY_DATA;
|
||||
} else {
|
||||
#if defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
st->hand_state = TLS_ST_CW_FINISHED;
|
||||
#else
|
||||
if (!SSL_IS_DTLS(s) && s->s3->next_proto_neg_seen)
|
||||
st->hand_state = TLS_ST_CW_NEXT_PROTO;
|
||||
else
|
||||
st->hand_state = TLS_ST_CW_FINISHED;
|
||||
#else
|
||||
if (!SSL_IS_DTLS(s) && s->s3->npn_seen)
|
||||
st->hand_state = TLS_ST_CW_NEXT_PROTO;
|
||||
else
|
||||
st->hand_state = TLS_ST_CW_FINISHED;
|
||||
#endif
|
||||
}
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
#if !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
@@ -352,7 +610,6 @@ WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
|
||||
case TLS_ST_CW_FINISHED:
|
||||
if (s->hit) {
|
||||
st->hand_state = TLS_ST_OK;
|
||||
ossl_statem_set_in_init(s, 0);
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
} else {
|
||||
return WRITE_TRAN_FINISHED;
|
||||
@@ -364,13 +621,24 @@ WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
} else {
|
||||
st->hand_state = TLS_ST_OK;
|
||||
ossl_statem_set_in_init(s, 0);
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
}
|
||||
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
return WRITE_TRAN_ERROR;
|
||||
case TLS_ST_CR_HELLO_REQ:
|
||||
/*
|
||||
* If we can renegotiate now then do so, otherwise wait for a more
|
||||
* convenient time.
|
||||
*/
|
||||
if (ssl3_renegotiate_check(s, 1)) {
|
||||
if (!tls_setup_handshake(s)) {
|
||||
/* SSLfatal() already called */
|
||||
return WRITE_TRAN_ERROR;
|
||||
}
|
||||
st->hand_state = TLS_ST_CW_CLNT_HELLO;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
}
|
||||
st->hand_state = TLS_ST_OK;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,12 +651,16 @@ WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst)
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
/* No pre work to be done */
|
||||
break;
|
||||
|
||||
case TLS_ST_CW_CLNT_HELLO:
|
||||
s->shutdown = 0;
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
/* every DTLS ClientHello resets Finished MAC */
|
||||
if (!ssl3_init_finished_mac(s)) {
|
||||
ossl_statem_set_error(s);
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -404,18 +676,31 @@ WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst)
|
||||
st->use_timer = 0;
|
||||
}
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
if (BIO_dgram_is_sctp(SSL_get_wbio(s)))
|
||||
if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
|
||||
/* Calls SSLfatal() as required */
|
||||
return dtls_wait_for_dry(s);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return WORK_FINISHED_CONTINUE;
|
||||
break;
|
||||
|
||||
case TLS_ST_PENDING_EARLY_DATA_END:
|
||||
/*
|
||||
* If we've been called by SSL_do_handshake()/SSL_write(), or we did not
|
||||
* attempt to write early data before calling SSL_read() then we press
|
||||
* on with the handshake. Otherwise we pause here.
|
||||
*/
|
||||
if (s->early_data_state == SSL_EARLY_DATA_FINISHED_WRITING
|
||||
|| s->early_data_state == SSL_EARLY_DATA_NONE)
|
||||
return WORK_FINISHED_CONTINUE;
|
||||
/* Fall through */
|
||||
|
||||
case TLS_ST_EARLY_DATA:
|
||||
return tls_finish_handshake(s, wst, 0, 1);
|
||||
|
||||
case TLS_ST_OK:
|
||||
return tls_finish_handshake(s, wst);
|
||||
|
||||
default:
|
||||
/* No pre work to be done */
|
||||
break;
|
||||
/* Calls SSLfatal() as required */
|
||||
return tls_finish_handshake(s, wst, 1, 1);
|
||||
}
|
||||
|
||||
return WORK_FINISHED_CONTINUE;
|
||||
@@ -432,9 +717,29 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
|
||||
s->init_num = 0;
|
||||
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
/* No post work to be done */
|
||||
break;
|
||||
|
||||
case TLS_ST_CW_CLNT_HELLO:
|
||||
if (wst == WORK_MORE_A && statem_flush(s) != 1)
|
||||
if (s->early_data_state == SSL_EARLY_DATA_CONNECTING
|
||||
&& s->max_early_data > 0) {
|
||||
/*
|
||||
* We haven't selected TLSv1.3 yet so we don't call the change
|
||||
* cipher state function associated with the SSL_METHOD. Instead
|
||||
* we call tls13_change_cipher_state() directly.
|
||||
*/
|
||||
if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0) {
|
||||
if (!tls13_change_cipher_state(s,
|
||||
SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
}
|
||||
/* else we're in compat mode so we delay flushing until after CCS */
|
||||
} else if (!statem_flush(s)) {
|
||||
return WORK_MORE_A;
|
||||
}
|
||||
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
/* Treat the next message as the first packet */
|
||||
@@ -442,12 +747,37 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
|
||||
}
|
||||
break;
|
||||
|
||||
case TLS_ST_CW_END_OF_EARLY_DATA:
|
||||
/*
|
||||
* We set the enc_write_ctx back to NULL because we may end up writing
|
||||
* in cleartext again if we get a HelloRetryRequest from the server.
|
||||
*/
|
||||
EVP_CIPHER_CTX_free(s->enc_write_ctx);
|
||||
s->enc_write_ctx = NULL;
|
||||
break;
|
||||
|
||||
case TLS_ST_CW_KEY_EXCH:
|
||||
if (tls_client_key_exchange_post_work(s) == 0)
|
||||
if (tls_client_key_exchange_post_work(s) == 0) {
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case TLS_ST_CW_CHANGE:
|
||||
if (SSL_IS_TLS13(s) || s->hello_retry_request == SSL_HRR_PENDING)
|
||||
break;
|
||||
if (s->early_data_state == SSL_EARLY_DATA_CONNECTING
|
||||
&& s->max_early_data > 0) {
|
||||
/*
|
||||
* We haven't selected TLSv1.3 yet so we don't call the change
|
||||
* cipher state function associated with the SSL_METHOD. Instead
|
||||
* we call tls13_change_cipher_state() directly.
|
||||
*/
|
||||
if (!tls13_change_cipher_state(s,
|
||||
SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE))
|
||||
return WORK_ERROR;
|
||||
break;
|
||||
}
|
||||
s->session->cipher = s->s3->tmp.new_cipher;
|
||||
#ifdef OPENSSL_NO_COMP
|
||||
s->session->compress_meth = 0;
|
||||
@@ -457,12 +787,16 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
|
||||
else
|
||||
s->session->compress_meth = s->s3->tmp.new_compression->id;
|
||||
#endif
|
||||
if (!s->method->ssl3_enc->setup_key_block(s))
|
||||
if (!s->method->ssl3_enc->setup_key_block(s)) {
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
|
||||
if (!s->method->ssl3_enc->change_cipher_state(s,
|
||||
SSL3_CHANGE_CIPHER_CLIENT_WRITE))
|
||||
SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
@@ -493,10 +827,29 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
|
||||
#endif
|
||||
if (statem_flush(s) != 1)
|
||||
return WORK_MORE_B;
|
||||
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
if (!tls13_save_handshake_digest_for_pha(s)) {
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
if (s->post_handshake_auth != SSL_PHA_REQUESTED) {
|
||||
if (!s->method->ssl3_enc->change_cipher_state(s,
|
||||
SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* No post work to be done */
|
||||
case TLS_ST_CW_KEY_UPDATE:
|
||||
if (statem_flush(s) != 1)
|
||||
return WORK_MORE_A;
|
||||
if (!tls13_update_key(s, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -504,63 +857,97 @@ WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a message to be sent from the client to the server.
|
||||
* Get the message construction function and message type for sending from the
|
||||
* client
|
||||
*
|
||||
* Valid return values are:
|
||||
* 1: Success
|
||||
* 0: Error
|
||||
*/
|
||||
int ossl_statem_client_construct_message(SSL *s)
|
||||
int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt,
|
||||
confunc_f *confunc, int *mt)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
switch (st->hand_state) {
|
||||
case TLS_ST_CW_CLNT_HELLO:
|
||||
return tls_construct_client_hello(s);
|
||||
|
||||
case TLS_ST_CW_CERT:
|
||||
return tls_construct_client_certificate(s);
|
||||
|
||||
case TLS_ST_CW_KEY_EXCH:
|
||||
return tls_construct_client_key_exchange(s);
|
||||
|
||||
case TLS_ST_CW_CERT_VRFY:
|
||||
return tls_construct_client_verify(s);
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE,
|
||||
SSL_R_BAD_HANDSHAKE_STATE);
|
||||
return 0;
|
||||
|
||||
case TLS_ST_CW_CHANGE:
|
||||
if (SSL_IS_DTLS(s))
|
||||
return dtls_construct_change_cipher_spec(s);
|
||||
*confunc = dtls_construct_change_cipher_spec;
|
||||
else
|
||||
return tls_construct_change_cipher_spec(s);
|
||||
*confunc = tls_construct_change_cipher_spec;
|
||||
*mt = SSL3_MT_CHANGE_CIPHER_SPEC;
|
||||
break;
|
||||
|
||||
case TLS_ST_CW_CLNT_HELLO:
|
||||
*confunc = tls_construct_client_hello;
|
||||
*mt = SSL3_MT_CLIENT_HELLO;
|
||||
break;
|
||||
|
||||
case TLS_ST_CW_END_OF_EARLY_DATA:
|
||||
*confunc = tls_construct_end_of_early_data;
|
||||
*mt = SSL3_MT_END_OF_EARLY_DATA;
|
||||
break;
|
||||
|
||||
case TLS_ST_PENDING_EARLY_DATA_END:
|
||||
*confunc = NULL;
|
||||
*mt = SSL3_MT_DUMMY;
|
||||
break;
|
||||
|
||||
case TLS_ST_CW_CERT:
|
||||
*confunc = tls_construct_client_certificate;
|
||||
*mt = SSL3_MT_CERTIFICATE;
|
||||
break;
|
||||
|
||||
case TLS_ST_CW_KEY_EXCH:
|
||||
*confunc = tls_construct_client_key_exchange;
|
||||
*mt = SSL3_MT_CLIENT_KEY_EXCHANGE;
|
||||
break;
|
||||
|
||||
case TLS_ST_CW_CERT_VRFY:
|
||||
*confunc = tls_construct_cert_verify;
|
||||
*mt = SSL3_MT_CERTIFICATE_VERIFY;
|
||||
break;
|
||||
|
||||
#if !defined(OPENSSL_NO_NEXTPROTONEG)
|
||||
case TLS_ST_CW_NEXT_PROTO:
|
||||
return tls_construct_next_proto(s);
|
||||
*confunc = tls_construct_next_proto;
|
||||
*mt = SSL3_MT_NEXT_PROTO;
|
||||
break;
|
||||
#endif
|
||||
case TLS_ST_CW_FINISHED:
|
||||
return tls_construct_finished(s,
|
||||
s->method->
|
||||
ssl3_enc->client_finished_label,
|
||||
s->method->
|
||||
ssl3_enc->client_finished_label_len);
|
||||
*confunc = tls_construct_finished;
|
||||
*mt = SSL3_MT_FINISHED;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
case TLS_ST_CW_KEY_UPDATE:
|
||||
*confunc = tls_construct_key_update;
|
||||
*mt = SSL3_MT_KEY_UPDATE;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the maximum allowed length for the current message that we are
|
||||
* reading. Excludes the message header.
|
||||
*/
|
||||
unsigned long ossl_statem_client_max_message_size(SSL *s)
|
||||
size_t ossl_statem_client_max_message_size(SSL *s)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
return 0;
|
||||
|
||||
case TLS_ST_CR_SRVR_HELLO:
|
||||
return SERVER_HELLO_MAX_LENGTH;
|
||||
|
||||
@@ -570,6 +957,9 @@ unsigned long ossl_statem_client_max_message_size(SSL *s)
|
||||
case TLS_ST_CR_CERT:
|
||||
return s->max_cert_list;
|
||||
|
||||
case TLS_ST_CR_CERT_VRFY:
|
||||
return SSL3_RT_MAX_PLAIN_LENGTH;
|
||||
|
||||
case TLS_ST_CR_CERT_STATUS:
|
||||
return SSL3_RT_MAX_PLAIN_LENGTH;
|
||||
|
||||
@@ -598,12 +988,12 @@ unsigned long ossl_statem_client_max_message_size(SSL *s)
|
||||
case TLS_ST_CR_FINISHED:
|
||||
return FINISHED_MAX_LENGTH;
|
||||
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
break;
|
||||
}
|
||||
case TLS_ST_CR_ENCRYPTED_EXTENSIONS:
|
||||
return ENCRYPTED_EXTENSIONS_MAX_LENGTH;
|
||||
|
||||
return 0;
|
||||
case TLS_ST_CR_KEY_UPDATE:
|
||||
return KEY_UPDATE_MAX_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -614,6 +1004,13 @@ MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt)
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return MSG_PROCESS_ERROR;
|
||||
|
||||
case TLS_ST_CR_SRVR_HELLO:
|
||||
return tls_process_server_hello(s, pkt);
|
||||
|
||||
@@ -623,6 +1020,9 @@ MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt)
|
||||
case TLS_ST_CR_CERT:
|
||||
return tls_process_server_certificate(s, pkt);
|
||||
|
||||
case TLS_ST_CR_CERT_VRFY:
|
||||
return tls_process_cert_verify(s, pkt);
|
||||
|
||||
case TLS_ST_CR_CERT_STATUS:
|
||||
return tls_process_cert_status(s, pkt);
|
||||
|
||||
@@ -644,12 +1044,15 @@ MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt)
|
||||
case TLS_ST_CR_FINISHED:
|
||||
return tls_process_finished(s, pkt);
|
||||
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
break;
|
||||
}
|
||||
case TLS_ST_CR_HELLO_REQ:
|
||||
return tls_process_hello_req(s, pkt);
|
||||
|
||||
return MSG_PROCESS_ERROR;
|
||||
case TLS_ST_CR_ENCRYPTED_EXTENSIONS:
|
||||
return tls_process_encrypted_extensions(s, pkt);
|
||||
|
||||
case TLS_ST_CR_KEY_UPDATE:
|
||||
return tls_process_key_update(s, pkt);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -661,49 +1064,52 @@ WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst)
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return WORK_ERROR;
|
||||
|
||||
case TLS_ST_CR_CERT_REQ:
|
||||
return tls_prepare_client_certificate(s, wst);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Shouldn't happen */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
|
||||
int tls_construct_client_hello(SSL *s)
|
||||
int tls_construct_client_hello(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
unsigned char *buf;
|
||||
unsigned char *p, *d;
|
||||
int i;
|
||||
int protverr;
|
||||
unsigned long l;
|
||||
int al = 0;
|
||||
unsigned char *p;
|
||||
size_t sess_id_len;
|
||||
int i, protverr;
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
int j;
|
||||
SSL_COMP *comp;
|
||||
#endif
|
||||
SSL_SESSION *sess = s->session;
|
||||
unsigned char *session_id;
|
||||
|
||||
buf = (unsigned char *)s->init_buf->data;
|
||||
if (!WPACKET_set_max_size(pkt, SSL3_RT_MAX_PLAIN_LENGTH)) {
|
||||
/* Should not happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Work out what SSL/TLS/DTLS version to use */
|
||||
protverr = ssl_set_client_hello_version(s);
|
||||
if (protverr != 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, protverr);
|
||||
goto err;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
|
||||
protverr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((sess == NULL) || !ssl_version_supported(s, sess->ssl_version) ||
|
||||
/*
|
||||
* In the case of EAP-FAST, we can have a pre-shared
|
||||
* "ticket" without a session ID.
|
||||
*/
|
||||
(!sess->session_id_length && !sess->tlsext_tick) ||
|
||||
(sess->not_resumable)) {
|
||||
if (!ssl_get_new_session(s, 0))
|
||||
goto err;
|
||||
if (sess == NULL
|
||||
|| !ssl_version_supported(s, sess->ssl_version)
|
||||
|| !SSL_SESSION_is_resumable(sess)) {
|
||||
if (s->hello_retry_request == SSL_HRR_NONE
|
||||
&& !ssl_get_new_session(s, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* else use the pre-loaded session */
|
||||
|
||||
@@ -722,14 +1128,16 @@ int tls_construct_client_hello(SSL *s)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
i = 1;
|
||||
} else {
|
||||
i = (s->hello_retry_request == SSL_HRR_NONE);
|
||||
}
|
||||
|
||||
if (i && ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random)) <= 0)
|
||||
goto err;
|
||||
|
||||
/* Do the message type and length last */
|
||||
d = p = ssl_handshake_start(s);
|
||||
if (i && ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random),
|
||||
DOWNGRADE_NONE) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-
|
||||
* version indicates the negotiated version: for example from
|
||||
@@ -760,297 +1168,186 @@ int tls_construct_client_hello(SSL *s)
|
||||
* TLS 1.0 and renegotiating with TLS 1.2. We do this by using
|
||||
* client_version in client hello and not resetting it to
|
||||
* the negotiated version.
|
||||
*
|
||||
* For TLS 1.3 we always set the ClientHello version to 1.2 and rely on the
|
||||
* supported_versions extension for the real supported versions.
|
||||
*/
|
||||
*(p++) = s->client_version >> 8;
|
||||
*(p++) = s->client_version & 0xff;
|
||||
|
||||
/* Random stuff */
|
||||
memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE);
|
||||
p += SSL3_RANDOM_SIZE;
|
||||
if (!WPACKET_put_bytes_u16(pkt, s->client_version)
|
||||
|| !WPACKET_memcpy(pkt, s->s3->client_random, SSL3_RANDOM_SIZE)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Session ID */
|
||||
if (s->new_session)
|
||||
i = 0;
|
||||
else
|
||||
i = s->session->session_id_length;
|
||||
*(p++) = i;
|
||||
if (i != 0) {
|
||||
if (i > (int)sizeof(s->session->session_id)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
session_id = s->session->session_id;
|
||||
if (s->new_session || s->session->ssl_version == TLS1_3_VERSION) {
|
||||
if (s->version == TLS1_3_VERSION
|
||||
&& (s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0) {
|
||||
sess_id_len = sizeof(s->tmp_session_id);
|
||||
s->tmp_session_id_len = sess_id_len;
|
||||
session_id = s->tmp_session_id;
|
||||
if (s->hello_retry_request == SSL_HRR_NONE
|
||||
&& ssl_randbytes(s, s->tmp_session_id,
|
||||
sess_id_len) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
sess_id_len = 0;
|
||||
}
|
||||
memcpy(p, s->session->session_id, i);
|
||||
p += i;
|
||||
} else {
|
||||
sess_id_len = s->session->session_id_length;
|
||||
if (s->version == TLS1_3_VERSION) {
|
||||
s->tmp_session_id_len = sess_id_len;
|
||||
memcpy(s->tmp_session_id, s->session->session_id, sess_id_len);
|
||||
}
|
||||
}
|
||||
if (sess_id_len > sizeof(s->session->session_id)
|
||||
|| !WPACKET_start_sub_packet_u8(pkt)
|
||||
|| (sess_id_len != 0 && !WPACKET_memcpy(pkt, session_id,
|
||||
sess_id_len))
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* cookie stuff for DTLS */
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
if (s->d1->cookie_len > sizeof(s->d1->cookie)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
if (s->d1->cookie_len > sizeof(s->d1->cookie)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, s->d1->cookie,
|
||||
s->d1->cookie_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
*(p++) = s->d1->cookie_len;
|
||||
memcpy(p, s->d1->cookie, s->d1->cookie_len);
|
||||
p += s->d1->cookie_len;
|
||||
}
|
||||
|
||||
/* Ciphers supported */
|
||||
i = ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), &(p[2]));
|
||||
if (i == 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, SSL_R_NO_CIPHERS_AVAILABLE);
|
||||
goto err;
|
||||
if (!WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
if (!WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
#ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH
|
||||
/*
|
||||
* Some servers hang if client hello > 256 bytes as hack workaround
|
||||
* chop number of supported ciphers to keep it well below this if we
|
||||
* use TLS v1.2
|
||||
*/
|
||||
if (TLS1_get_version(s) >= TLS1_2_VERSION
|
||||
&& i > OPENSSL_MAX_TLS1_2_CIPHER_LENGTH)
|
||||
i = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1;
|
||||
#endif
|
||||
s2n(i, p);
|
||||
p += i;
|
||||
|
||||
/* COMPRESSION */
|
||||
#ifdef OPENSSL_NO_COMP
|
||||
*(p++) = 1;
|
||||
#else
|
||||
|
||||
if (!ssl_allow_compression(s) || !s->ctx->comp_methods)
|
||||
j = 0;
|
||||
else
|
||||
j = sk_SSL_COMP_num(s->ctx->comp_methods);
|
||||
*(p++) = 1 + j;
|
||||
for (i = 0; i < j; i++) {
|
||||
comp = sk_SSL_COMP_value(s->ctx->comp_methods, i);
|
||||
*(p++) = comp->id;
|
||||
if (!WPACKET_start_sub_packet_u8(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
if (ssl_allow_compression(s)
|
||||
&& s->ctx->comp_methods
|
||||
&& (SSL_IS_DTLS(s) || s->s3->tmp.max_ver < TLS1_3_VERSION)) {
|
||||
int compnum = sk_SSL_COMP_num(s->ctx->comp_methods);
|
||||
for (i = 0; i < compnum; i++) {
|
||||
comp = sk_SSL_COMP_value(s->ctx->comp_methods, i);
|
||||
if (!WPACKET_put_bytes_u8(pkt, comp->id)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
*(p++) = 0; /* Add the NULL method */
|
||||
/* Add the NULL method */
|
||||
if (!WPACKET_put_bytes_u8(pkt, 0) || !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TLS extensions */
|
||||
if (ssl_prepare_clienthello_tlsext(s) <= 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
|
||||
goto err;
|
||||
}
|
||||
if ((p =
|
||||
ssl_add_clienthello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH,
|
||||
&al)) == NULL) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
l = p - d;
|
||||
if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_HELLO, l)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
if (!tls_construct_extensions(s, pkt, SSL_EXT_CLIENT_HELLO, NULL, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
err:
|
||||
ossl_statem_set_error(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt)
|
||||
{
|
||||
int al;
|
||||
unsigned int cookie_len;
|
||||
size_t cookie_len;
|
||||
PACKET cookiepkt;
|
||||
|
||||
if (!PACKET_forward(pkt, 2)
|
||||
|| !PACKET_get_length_prefixed_1(pkt, &cookiepkt)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_DTLS_PROCESS_HELLO_VERIFY, SSL_R_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
cookie_len = PACKET_remaining(&cookiepkt);
|
||||
if (cookie_len > sizeof(s->d1->cookie)) {
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_DTLS_PROCESS_HELLO_VERIFY, SSL_R_LENGTH_TOO_LONG);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
|
||||
SSL_R_LENGTH_TOO_LONG);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
if (!PACKET_copy_bytes(&cookiepkt, s->d1->cookie, cookie_len)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_DTLS_PROCESS_HELLO_VERIFY, SSL_R_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
s->d1->cookie_len = cookie_len;
|
||||
|
||||
return MSG_PROCESS_FINISHED_READING;
|
||||
f_err:
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
ossl_statem_set_error(s);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
|
||||
static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars)
|
||||
{
|
||||
STACK_OF(SSL_CIPHER) *sk;
|
||||
const SSL_CIPHER *c;
|
||||
PACKET session_id;
|
||||
size_t session_id_len;
|
||||
const unsigned char *cipherchars;
|
||||
int i, al = SSL_AD_INTERNAL_ERROR;
|
||||
unsigned int compression;
|
||||
unsigned int sversion;
|
||||
int protverr;
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
SSL_COMP *comp;
|
||||
#endif
|
||||
int i;
|
||||
|
||||
if (!PACKET_get_net_2(pkt, &sversion)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
protverr = ssl_choose_client_version(s, sversion);
|
||||
if (protverr != 0) {
|
||||
al = SSL_AD_PROTOCOL_VERSION;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, protverr);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
/* load the server hello data */
|
||||
/* load the server random */
|
||||
if (!PACKET_copy_bytes(pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
s->hit = 0;
|
||||
|
||||
/* Get the session-id. */
|
||||
if (!PACKET_get_length_prefixed_1(pkt, &session_id)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
}
|
||||
session_id_len = PACKET_remaining(&session_id);
|
||||
if (session_id_len > sizeof(s->session->session_id)
|
||||
|| session_id_len > SSL3_SESSION_ID_SIZE) {
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_SSL3_SESSION_ID_TOO_LONG);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
if (!PACKET_get_bytes(pkt, &cipherchars, TLS_CIPHER_LEN)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we can resume the session based on external pre-shared secret.
|
||||
* EAP-FAST (RFC 4851) supports two types of session resumption.
|
||||
* Resumption based on server-side state works with session IDs.
|
||||
* Resumption based on pre-shared Protected Access Credentials (PACs)
|
||||
* works by overriding the SessionTicket extension at the application
|
||||
* layer, and does not send a session ID. (We do not know whether EAP-FAST
|
||||
* servers would honour the session ID.) Therefore, the session ID alone
|
||||
* is not a reliable indicator of session resumption, so we first check if
|
||||
* we can resume, and later peek at the next handshake message to see if the
|
||||
* server wants to resume.
|
||||
*/
|
||||
if (s->version >= TLS1_VERSION && s->tls_session_secret_cb &&
|
||||
s->session->tlsext_tick) {
|
||||
const SSL_CIPHER *pref_cipher = NULL;
|
||||
s->session->master_key_length = sizeof(s->session->master_key);
|
||||
if (s->tls_session_secret_cb(s, s->session->master_key,
|
||||
&s->session->master_key_length,
|
||||
NULL, &pref_cipher,
|
||||
s->tls_session_secret_cb_arg)) {
|
||||
s->session->cipher = pref_cipher ?
|
||||
pref_cipher : ssl_get_cipher_by_char(s, cipherchars);
|
||||
} else {
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
}
|
||||
|
||||
if (session_id_len != 0 && session_id_len == s->session->session_id_length
|
||||
&& memcmp(PACKET_data(&session_id), s->session->session_id,
|
||||
session_id_len) == 0) {
|
||||
if (s->sid_ctx_length != s->session->sid_ctx_length
|
||||
|| memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) {
|
||||
/* actually a client application bug */
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
|
||||
goto f_err;
|
||||
}
|
||||
s->hit = 1;
|
||||
} else {
|
||||
/*
|
||||
* If we were trying for session-id reuse but the server
|
||||
* didn't echo the ID, make a new SSL_SESSION.
|
||||
* In the case of EAP-FAST and PAC, we do not send a session ID,
|
||||
* so the PAC-based session secret is always preserved. It'll be
|
||||
* overwritten if the server refuses resumption.
|
||||
*/
|
||||
if (s->session->session_id_length > 0) {
|
||||
s->ctx->stats.sess_miss++;
|
||||
if (!ssl_get_new_session(s, 0)) {
|
||||
goto f_err;
|
||||
}
|
||||
}
|
||||
|
||||
s->session->ssl_version = s->version;
|
||||
s->session->session_id_length = session_id_len;
|
||||
/* session_id_len could be 0 */
|
||||
if (session_id_len > 0)
|
||||
memcpy(s->session->session_id, PACKET_data(&session_id),
|
||||
session_id_len);
|
||||
}
|
||||
|
||||
/* Session version and negotiated protocol version should match */
|
||||
if (s->version != s->session->ssl_version) {
|
||||
al = SSL_AD_PROTOCOL_VERSION;
|
||||
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_SSL_SESSION_VERSION_MISMATCH);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
c = ssl_get_cipher_by_char(s, cipherchars);
|
||||
c = ssl_get_cipher_by_char(s, cipherchars, 0);
|
||||
if (c == NULL) {
|
||||
/* unknown cipher */
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_UNKNOWN_CIPHER_RETURNED);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
|
||||
SSL_R_UNKNOWN_CIPHER_RETURNED);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Now that we know the version, update the check to see if it's an allowed
|
||||
* version.
|
||||
*/
|
||||
s->s3->tmp.min_ver = s->version;
|
||||
s->s3->tmp.max_ver = s->version;
|
||||
/*
|
||||
* If it is a disabled cipher we either didn't send it in client hello,
|
||||
* or it's not allowed for the selected protocol. So we return an error.
|
||||
*/
|
||||
if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK, 1)) {
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_WRONG_CIPHER_RETURNED);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
|
||||
SSL_R_WRONG_CIPHER_RETURNED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sk = ssl_get_ciphers_by_id(s);
|
||||
i = sk_SSL_CIPHER_find(sk, c);
|
||||
if (i < 0) {
|
||||
/* we did not say we would use this cipher */
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_WRONG_CIPHER_RETURNED);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
|
||||
SSL_R_WRONG_CIPHER_RETURNED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SSL_IS_TLS13(s) && s->s3->tmp.new_cipher != NULL
|
||||
&& s->s3->tmp.new_cipher->id != c->id) {
|
||||
/* ServerHello selected a different ciphersuite to that in the HRR */
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
|
||||
SSL_R_WRONG_CIPHER_RETURNED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1058,76 +1355,339 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
|
||||
* and/or cipher_id values may not be set. Make sure that cipher_id is
|
||||
* set and use it for comparison.
|
||||
*/
|
||||
if (s->session->cipher)
|
||||
if (s->session->cipher != NULL)
|
||||
s->session->cipher_id = s->session->cipher->id;
|
||||
if (s->hit && (s->session->cipher_id != c->id)) {
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
|
||||
goto f_err;
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
/*
|
||||
* In TLSv1.3 it is valid for the server to select a different
|
||||
* ciphersuite as long as the hash is the same.
|
||||
*/
|
||||
if (ssl_md(c->algorithm2)
|
||||
!= ssl_md(s->session->cipher->algorithm2)) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_SET_CLIENT_CIPHERSUITE,
|
||||
SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Prior to TLSv1.3 resuming a session always meant using the same
|
||||
* ciphersuite.
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
|
||||
SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
s->s3->tmp.new_cipher = c;
|
||||
/* lets get the compression algorithm */
|
||||
/* COMPRESSION */
|
||||
if (!PACKET_get_1(pkt, &compression)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
goto f_err;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
|
||||
{
|
||||
PACKET session_id, extpkt;
|
||||
size_t session_id_len;
|
||||
const unsigned char *cipherchars;
|
||||
int hrr = 0;
|
||||
unsigned int compression;
|
||||
unsigned int sversion;
|
||||
unsigned int context;
|
||||
int discard;
|
||||
RAW_EXTENSION *extensions = NULL;
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
SSL_COMP *comp;
|
||||
#endif
|
||||
|
||||
if (!PACKET_get_net_2(pkt, &sversion)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* load the server random */
|
||||
if (s->version == TLS1_3_VERSION
|
||||
&& sversion == TLS1_2_VERSION
|
||||
&& PACKET_remaining(pkt) >= SSL3_RANDOM_SIZE
|
||||
&& memcmp(hrrrandom, PACKET_data(pkt), SSL3_RANDOM_SIZE) == 0) {
|
||||
s->hello_retry_request = SSL_HRR_PENDING;
|
||||
hrr = 1;
|
||||
if (!PACKET_forward(pkt, SSL3_RANDOM_SIZE)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (!PACKET_copy_bytes(pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the session-id. */
|
||||
if (!PACKET_get_length_prefixed_1(pkt, &session_id)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
session_id_len = PACKET_remaining(&session_id);
|
||||
if (session_id_len > sizeof(s->session->session_id)
|
||||
|| session_id_len > SSL3_SESSION_ID_SIZE) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_SSL3_SESSION_ID_TOO_LONG);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!PACKET_get_bytes(pkt, &cipherchars, TLS_CIPHER_LEN)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!PACKET_get_1(pkt, &compression)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* TLS extensions */
|
||||
if (PACKET_remaining(pkt) == 0 && !hrr) {
|
||||
PACKET_null_init(&extpkt);
|
||||
} else if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_BAD_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!hrr) {
|
||||
if (!tls_collect_extensions(s, &extpkt,
|
||||
SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_SERVER_HELLO,
|
||||
&extensions, NULL, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!ssl_choose_client_version(s, sversion, extensions)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (SSL_IS_TLS13(s) || hrr) {
|
||||
if (compression != 0) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_INVALID_COMPRESSION_ALGORITHM);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (session_id_len != s->tmp_session_id_len
|
||||
|| memcmp(PACKET_data(&session_id), s->tmp_session_id,
|
||||
session_id_len) != 0) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_INVALID_SESSION_ID);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (hrr) {
|
||||
if (!set_client_ciphersuite(s, cipherchars)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
return tls_process_as_hello_retry_request(s, &extpkt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we have chosen the version we need to check again that the extensions
|
||||
* are appropriate for this version.
|
||||
*/
|
||||
context = SSL_IS_TLS13(s) ? SSL_EXT_TLS1_3_SERVER_HELLO
|
||||
: SSL_EXT_TLS1_2_SERVER_HELLO;
|
||||
if (!tls_validate_all_contexts(s, context, extensions)) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_BAD_EXTENSION);
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->hit = 0;
|
||||
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
/*
|
||||
* In TLSv1.3 a ServerHello message signals a key change so the end of
|
||||
* the message must be on a record boundary.
|
||||
*/
|
||||
if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
|
||||
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
|
||||
SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_NOT_ON_RECORD_BOUNDARY);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* This will set s->hit if we are resuming */
|
||||
if (!tls_parse_extension(s, TLSEXT_IDX_psk,
|
||||
SSL_EXT_TLS1_3_SERVER_HELLO,
|
||||
extensions, NULL, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Check if we can resume the session based on external pre-shared
|
||||
* secret. EAP-FAST (RFC 4851) supports two types of session resumption.
|
||||
* Resumption based on server-side state works with session IDs.
|
||||
* Resumption based on pre-shared Protected Access Credentials (PACs)
|
||||
* works by overriding the SessionTicket extension at the application
|
||||
* layer, and does not send a session ID. (We do not know whether
|
||||
* EAP-FAST servers would honour the session ID.) Therefore, the session
|
||||
* ID alone is not a reliable indicator of session resumption, so we
|
||||
* first check if we can resume, and later peek at the next handshake
|
||||
* message to see if the server wants to resume.
|
||||
*/
|
||||
if (s->version >= TLS1_VERSION
|
||||
&& s->ext.session_secret_cb != NULL && s->session->ext.tick) {
|
||||
const SSL_CIPHER *pref_cipher = NULL;
|
||||
/*
|
||||
* s->session->master_key_length is a size_t, but this is an int for
|
||||
* backwards compat reasons
|
||||
*/
|
||||
int master_key_length;
|
||||
master_key_length = sizeof(s->session->master_key);
|
||||
if (s->ext.session_secret_cb(s, s->session->master_key,
|
||||
&master_key_length,
|
||||
NULL, &pref_cipher,
|
||||
s->ext.session_secret_cb_arg)
|
||||
&& master_key_length > 0) {
|
||||
s->session->master_key_length = master_key_length;
|
||||
s->session->cipher = pref_cipher ?
|
||||
pref_cipher : ssl_get_cipher_by_char(s, cipherchars, 0);
|
||||
} else {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (session_id_len != 0
|
||||
&& session_id_len == s->session->session_id_length
|
||||
&& memcmp(PACKET_data(&session_id), s->session->session_id,
|
||||
session_id_len) == 0)
|
||||
s->hit = 1;
|
||||
}
|
||||
|
||||
if (s->hit) {
|
||||
if (s->sid_ctx_length != s->session->sid_ctx_length
|
||||
|| memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) {
|
||||
/* actually a client application bug */
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If we were trying for session-id reuse but the server
|
||||
* didn't resume, make a new SSL_SESSION.
|
||||
* In the case of EAP-FAST and PAC, we do not send a session ID,
|
||||
* so the PAC-based session secret is always preserved. It'll be
|
||||
* overwritten if the server refuses resumption.
|
||||
*/
|
||||
if (s->session->session_id_length > 0
|
||||
|| (SSL_IS_TLS13(s)
|
||||
&& s->session->ext.tick_identity
|
||||
!= TLSEXT_PSK_BAD_IDENTITY)) {
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_miss, 1, &discard,
|
||||
s->session_ctx->lock);
|
||||
if (!ssl_get_new_session(s, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
s->session->ssl_version = s->version;
|
||||
/*
|
||||
* In TLSv1.2 and below we save the session id we were sent so we can
|
||||
* resume it later. In TLSv1.3 the session id we were sent is just an
|
||||
* echo of what we originally sent in the ClientHello and should not be
|
||||
* used for resumption.
|
||||
*/
|
||||
if (!SSL_IS_TLS13(s)) {
|
||||
s->session->session_id_length = session_id_len;
|
||||
/* session_id_len could be 0 */
|
||||
if (session_id_len > 0)
|
||||
memcpy(s->session->session_id, PACKET_data(&session_id),
|
||||
session_id_len);
|
||||
}
|
||||
}
|
||||
|
||||
/* Session version and negotiated protocol version should match */
|
||||
if (s->version != s->session->ssl_version) {
|
||||
SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_SSL_SESSION_VERSION_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* Now that we know the version, update the check to see if it's an allowed
|
||||
* version.
|
||||
*/
|
||||
s->s3->tmp.min_ver = s->version;
|
||||
s->s3->tmp.max_ver = s->version;
|
||||
|
||||
if (!set_client_ciphersuite(s, cipherchars)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifdef OPENSSL_NO_COMP
|
||||
if (compression != 0) {
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* If compression is disabled we'd better not try to resume a session
|
||||
* using compression.
|
||||
*/
|
||||
if (s->session->compress_meth != 0) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_INCONSISTENT_COMPRESSION);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_INCONSISTENT_COMPRESSION);
|
||||
goto err;
|
||||
}
|
||||
#else
|
||||
if (s->hit && compression != s->session->compress_meth) {
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
|
||||
goto err;
|
||||
}
|
||||
if (compression == 0)
|
||||
comp = NULL;
|
||||
else if (!ssl_allow_compression(s)) {
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_COMPRESSION_DISABLED);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_COMPRESSION_DISABLED);
|
||||
goto err;
|
||||
} else {
|
||||
comp = ssl3_comp_find(s->ctx->comp_methods, compression);
|
||||
}
|
||||
|
||||
if (compression != 0 && comp == NULL) {
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
|
||||
goto err;
|
||||
} else {
|
||||
s->s3->tmp.new_compression = comp;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* TLS extensions */
|
||||
if (!ssl_parse_serverhello_tlsext(s, pkt)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_PARSE_TLSEXT);
|
||||
if (!tls_parse_all_extensions(s, context, extensions, NULL, 0, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (PACKET_remaining(pkt) != 0) {
|
||||
/* wrong packet length */
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_BAD_PACKET_LENGTH);
|
||||
goto f_err;
|
||||
}
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
if (SSL_IS_DTLS(s) && s->hit) {
|
||||
unsigned char sctpauthkey[64];
|
||||
@@ -1143,8 +1703,11 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
|
||||
if (SSL_export_keying_material(s, sctpauthkey,
|
||||
sizeof(sctpauthkey),
|
||||
labelbuffer,
|
||||
sizeof(labelbuffer), NULL, 0, 0) <= 0)
|
||||
sizeof(labelbuffer), NULL, 0, 0) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
BIO_ctrl(SSL_get_wbio(s),
|
||||
BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
|
||||
@@ -1152,58 +1715,168 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In TLSv1.3 we have some post-processing to change cipher state, otherwise
|
||||
* we're done with this message
|
||||
*/
|
||||
if (SSL_IS_TLS13(s)
|
||||
&& (!s->method->ssl3_enc->setup_key_block(s)
|
||||
|| !s->method->ssl3_enc->change_cipher_state(s,
|
||||
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_READ))) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
OPENSSL_free(extensions);
|
||||
return MSG_PROCESS_CONTINUE_READING;
|
||||
f_err:
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
err:
|
||||
ossl_statem_set_error(s);
|
||||
OPENSSL_free(extensions);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s,
|
||||
PACKET *extpkt)
|
||||
{
|
||||
RAW_EXTENSION *extensions = NULL;
|
||||
|
||||
/*
|
||||
* If we were sending early_data then the enc_write_ctx is now invalid and
|
||||
* should not be used.
|
||||
*/
|
||||
EVP_CIPHER_CTX_free(s->enc_write_ctx);
|
||||
s->enc_write_ctx = NULL;
|
||||
|
||||
if (!tls_collect_extensions(s, extpkt, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
|
||||
&extensions, NULL, 1)
|
||||
|| !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
|
||||
extensions, NULL, 0, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
OPENSSL_free(extensions);
|
||||
extensions = NULL;
|
||||
|
||||
if (s->ext.tls13_cookie_len == 0
|
||||
#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
|
||||
&& s->s3->tmp.pkey != NULL
|
||||
#endif
|
||||
) {
|
||||
/*
|
||||
* We didn't receive a cookie or a new key_share so the next
|
||||
* ClientHello will not change
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST,
|
||||
SSL_R_NO_CHANGE_FOLLOWING_HRR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-initialise the Transcript Hash. We're going to prepopulate it with
|
||||
* a synthetic message_hash in place of ClientHello1.
|
||||
*/
|
||||
if (!create_synthetic_message_hash(s, NULL, 0, NULL, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add this message to the Transcript Hash. Normally this is done
|
||||
* automatically prior to the message processing stage. However due to the
|
||||
* need to create the synthetic message hash, we defer that step until now
|
||||
* for HRR messages.
|
||||
*/
|
||||
if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
|
||||
s->init_num + SSL3_HM_HEADER_LENGTH)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
return MSG_PROCESS_FINISHED_READING;
|
||||
err:
|
||||
OPENSSL_free(extensions);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
|
||||
{
|
||||
int al, i, ret = MSG_PROCESS_ERROR, exp_idx;
|
||||
int i;
|
||||
MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
|
||||
unsigned long cert_list_len, cert_len;
|
||||
X509 *x = NULL;
|
||||
const unsigned char *certstart, *certbytes;
|
||||
STACK_OF(X509) *sk = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
size_t chainidx, certidx;
|
||||
unsigned int context = 0;
|
||||
const SSL_CERT_LOOKUP *clu;
|
||||
|
||||
if ((sk = sk_X509_new_null()) == NULL) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_MALLOC_FAILURE);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!PACKET_get_net_3(pkt, &cert_list_len)
|
||||
|| PACKET_remaining(pkt) != cert_list_len) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, SSL_R_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
if ((SSL_IS_TLS13(s) && !PACKET_get_1(pkt, &context))
|
||||
|| context != 0
|
||||
|| !PACKET_get_net_3(pkt, &cert_list_len)
|
||||
|| PACKET_remaining(pkt) != cert_list_len
|
||||
|| PACKET_remaining(pkt) == 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
while (PACKET_remaining(pkt)) {
|
||||
for (chainidx = 0; PACKET_remaining(pkt); chainidx++) {
|
||||
if (!PACKET_get_net_3(pkt, &cert_len)
|
||||
|| !PACKET_get_bytes(pkt, &certbytes, cert_len)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
|
||||
SSL_R_CERT_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
|
||||
SSL_R_CERT_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
certstart = certbytes;
|
||||
x = d2i_X509(NULL, (const unsigned char **)&certbytes, cert_len);
|
||||
if (x == NULL) {
|
||||
al = SSL_AD_BAD_CERTIFICATE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_ASN1_LIB);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_BAD_CERTIFICATE,
|
||||
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_ASN1_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (certbytes != (certstart + cert_len)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
|
||||
SSL_R_CERT_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
|
||||
SSL_R_CERT_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
RAW_EXTENSION *rawexts = NULL;
|
||||
PACKET extensions;
|
||||
|
||||
if (!PACKET_get_length_prefixed_2(pkt, &extensions)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
|
||||
SSL_R_BAD_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
if (!tls_collect_extensions(s, &extensions,
|
||||
SSL_EXT_TLS1_3_CERTIFICATE, &rawexts,
|
||||
NULL, chainidx == 0)
|
||||
|| !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE,
|
||||
rawexts, x, chainidx,
|
||||
PACKET_remaining(pkt) == 0)) {
|
||||
OPENSSL_free(rawexts);
|
||||
/* SSLfatal already called */
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_free(rawexts);
|
||||
}
|
||||
|
||||
if (!sk_X509_push(sk, x)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_MALLOC_FAILURE);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
x = NULL;
|
||||
@@ -1225,16 +1898,16 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
|
||||
* set. The *documented* interface remains the same.
|
||||
*/
|
||||
if (s->verify_mode != SSL_VERIFY_NONE && i <= 0) {
|
||||
al = ssl_verify_alarm_type(s->verify_result);
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
|
||||
SSL_R_CERTIFICATE_VERIFY_FAILED);
|
||||
goto f_err;
|
||||
SSLfatal(s, ssl_verify_alarm_type(s->verify_result),
|
||||
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
|
||||
SSL_R_CERTIFICATE_VERIFY_FAILED);
|
||||
goto err;
|
||||
}
|
||||
ERR_clear_error(); /* but we keep s->verify_result */
|
||||
if (i > 1) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, i);
|
||||
al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, i);
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->session->peer_chain = sk;
|
||||
@@ -1249,54 +1922,58 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
|
||||
|
||||
if (pkey == NULL || EVP_PKEY_missing_parameters(pkey)) {
|
||||
x = NULL;
|
||||
al = SSL3_AL_FATAL;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
|
||||
SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
|
||||
SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
|
||||
goto err;
|
||||
}
|
||||
|
||||
i = ssl_cert_type(x, pkey);
|
||||
if (i < 0) {
|
||||
if ((clu = ssl_cert_lookup_by_pkey(pkey, &certidx)) == NULL) {
|
||||
x = NULL;
|
||||
al = SSL3_AL_FATAL;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
|
||||
SSL_R_UNKNOWN_CERTIFICATE_TYPE);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
|
||||
SSL_R_UNKNOWN_CERTIFICATE_TYPE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
|
||||
if (exp_idx >= 0 && i != exp_idx
|
||||
&& (exp_idx != SSL_PKEY_GOST_EC ||
|
||||
(i != SSL_PKEY_GOST12_512 && i != SSL_PKEY_GOST12_256
|
||||
&& i != SSL_PKEY_GOST01))) {
|
||||
x = NULL;
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
|
||||
SSL_R_WRONG_CERTIFICATE_TYPE);
|
||||
goto f_err;
|
||||
/*
|
||||
* Check certificate type is consistent with ciphersuite. For TLS 1.3
|
||||
* skip check since TLS 1.3 ciphersuites can be used with any certificate
|
||||
* type.
|
||||
*/
|
||||
if (!SSL_IS_TLS13(s)) {
|
||||
if ((clu->amask & s->s3->tmp.new_cipher->algorithm_auth) == 0) {
|
||||
x = NULL;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
|
||||
SSL_R_WRONG_CERTIFICATE_TYPE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
s->session->peer_type = i;
|
||||
s->session->peer_type = certidx;
|
||||
|
||||
X509_free(s->session->peer);
|
||||
X509_up_ref(x);
|
||||
s->session->peer = x;
|
||||
s->session->verify_result = s->verify_result;
|
||||
|
||||
x = NULL;
|
||||
ret = MSG_PROCESS_CONTINUE_READING;
|
||||
goto done;
|
||||
|
||||
f_err:
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
/* Save the current hash state for when we receive the CertificateVerify */
|
||||
if (SSL_IS_TLS13(s)
|
||||
&& !ssl_handshake_hash(s, s->cert_verify_hash,
|
||||
sizeof(s->cert_verify_hash),
|
||||
&s->cert_verify_hash_len)) {
|
||||
/* SSLfatal() already called */;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = MSG_PROCESS_CONTINUE_READING;
|
||||
|
||||
err:
|
||||
ossl_statem_set_error(s);
|
||||
done:
|
||||
X509_free(x);
|
||||
sk_X509_pop_free(sk, X509_free);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt, int *al)
|
||||
static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_PSK
|
||||
PACKET psk_identity_hint;
|
||||
@@ -1304,8 +1981,8 @@ static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt, int *al)
|
||||
/* PSK ciphersuites are preceded by an identity hint */
|
||||
|
||||
if (!PACKET_get_length_prefixed_2(pkt, &psk_identity_hint)) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE, SSL_R_LENGTH_MISMATCH);
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1316,8 +1993,9 @@ static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt, int *al)
|
||||
* identity.
|
||||
*/
|
||||
if (PACKET_remaining(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN) {
|
||||
*al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE, SSL_R_DATA_LENGTH_TOO_LONG);
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
|
||||
SSL_R_DATA_LENGTH_TOO_LONG);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1326,19 +2004,20 @@ static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt, int *al)
|
||||
s->session->psk_identity_hint = NULL;
|
||||
} else if (!PACKET_strndup(&psk_identity_hint,
|
||||
&s->session->psk_identity_hint)) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
#else
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
|
||||
static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
|
||||
{
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
PACKET prime, generator, salt, server_pub;
|
||||
@@ -1347,31 +2026,31 @@ static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
|
||||
|| !PACKET_get_length_prefixed_2(pkt, &generator)
|
||||
|| !PACKET_get_length_prefixed_1(pkt, &salt)
|
||||
|| !PACKET_get_length_prefixed_2(pkt, &server_pub)) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_SRP, SSL_R_LENGTH_MISMATCH);
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO(size_t): Convert BN_bin2bn() calls */
|
||||
if ((s->srp_ctx.N =
|
||||
BN_bin2bn(PACKET_data(&prime),
|
||||
PACKET_remaining(&prime), NULL)) == NULL
|
||||
(int)PACKET_remaining(&prime), NULL)) == NULL
|
||||
|| (s->srp_ctx.g =
|
||||
BN_bin2bn(PACKET_data(&generator),
|
||||
PACKET_remaining(&generator), NULL)) == NULL
|
||||
(int)PACKET_remaining(&generator), NULL)) == NULL
|
||||
|| (s->srp_ctx.s =
|
||||
BN_bin2bn(PACKET_data(&salt),
|
||||
PACKET_remaining(&salt), NULL)) == NULL
|
||||
(int)PACKET_remaining(&salt), NULL)) == NULL
|
||||
|| (s->srp_ctx.B =
|
||||
BN_bin2bn(PACKET_data(&server_pub),
|
||||
PACKET_remaining(&server_pub), NULL)) == NULL) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_SRP, ERR_R_BN_LIB);
|
||||
(int)PACKET_remaining(&server_pub), NULL)) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
|
||||
ERR_R_BN_LIB);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!srp_verify_server_param(s, al)) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_SRP, SSL_R_BAD_SRP_PARAMETERS);
|
||||
if (!srp_verify_server_param(s)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1381,13 +2060,13 @@ static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
|
||||
|
||||
return 1;
|
||||
#else
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_SRP, ERR_R_INTERNAL_ERROR);
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
|
||||
static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
|
||||
{
|
||||
#ifndef OPENSSL_NO_DH
|
||||
PACKET prime, generator, pub_key;
|
||||
@@ -1401,8 +2080,8 @@ static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
|
||||
if (!PACKET_get_length_prefixed_2(pkt, &prime)
|
||||
|| !PACKET_get_length_prefixed_2(pkt, &generator)
|
||||
|| !PACKET_get_length_prefixed_2(pkt, &pub_key)) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, SSL_R_LENGTH_MISMATCH);
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1410,57 +2089,59 @@ static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
|
||||
dh = DH_new();
|
||||
|
||||
if (peer_tmp == NULL || dh == NULL) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, ERR_R_MALLOC_FAILURE);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
p = BN_bin2bn(PACKET_data(&prime), PACKET_remaining(&prime), NULL);
|
||||
g = BN_bin2bn(PACKET_data(&generator), PACKET_remaining(&generator), NULL);
|
||||
bnpub_key = BN_bin2bn(PACKET_data(&pub_key), PACKET_remaining(&pub_key),
|
||||
NULL);
|
||||
/* TODO(size_t): Convert these calls */
|
||||
p = BN_bin2bn(PACKET_data(&prime), (int)PACKET_remaining(&prime), NULL);
|
||||
g = BN_bin2bn(PACKET_data(&generator), (int)PACKET_remaining(&generator),
|
||||
NULL);
|
||||
bnpub_key = BN_bin2bn(PACKET_data(&pub_key),
|
||||
(int)PACKET_remaining(&pub_key), NULL);
|
||||
if (p == NULL || g == NULL || bnpub_key == NULL) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, ERR_R_BN_LIB);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
|
||||
ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* test non-zero pubkey */
|
||||
if (BN_is_zero(bnpub_key)) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, SSL_R_BAD_DH_VALUE);
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_DHE,
|
||||
SSL_R_BAD_DH_VALUE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!DH_set0_pqg(dh, p, NULL, g)) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, ERR_R_BN_LIB);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
|
||||
ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
p = g = NULL;
|
||||
|
||||
if (DH_check_params(dh, &check_bits) == 0 || check_bits != 0) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, SSL_R_BAD_DH_VALUE);
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_DHE,
|
||||
SSL_R_BAD_DH_VALUE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!DH_set0_key(dh, bnpub_key, NULL)) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, ERR_R_BN_LIB);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
|
||||
ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
bnpub_key = NULL;
|
||||
|
||||
if (!ssl_security(s, SSL_SECOP_TMP_DH, DH_security_bits(dh), 0, dh)) {
|
||||
*al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, SSL_R_DH_KEY_TOO_SMALL);
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_SKE_DHE,
|
||||
SSL_R_DH_KEY_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_assign_DH(peer_tmp, dh) == 0) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, ERR_R_EVP_LIB);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
|
||||
ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -1485,87 +2166,55 @@ static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
|
||||
|
||||
return 0;
|
||||
#else
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_DHE, ERR_R_INTERNAL_ERROR);
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
|
||||
static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
|
||||
{
|
||||
#ifndef OPENSSL_NO_EC
|
||||
PACKET encoded_pt;
|
||||
const unsigned char *ecparams;
|
||||
int curve_nid;
|
||||
unsigned int curve_flags;
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
unsigned int curve_type, curve_id;
|
||||
|
||||
/*
|
||||
* Extract elliptic curve parameters and the server's ephemeral ECDH
|
||||
* public key. For now we only support named (not generic) curves and
|
||||
* public key. We only support named (not generic) curves and
|
||||
* ECParameters in this case is just three bytes.
|
||||
*/
|
||||
if (!PACKET_get_bytes(pkt, &ecparams, 3)) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, SSL_R_LENGTH_TOO_SHORT);
|
||||
if (!PACKET_get_1(pkt, &curve_type) || !PACKET_get_net_2(pkt, &curve_id)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
|
||||
SSL_R_LENGTH_TOO_SHORT);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Check curve is one of our preferences, if not server has sent an
|
||||
* invalid curve. ECParameters is 3 bytes.
|
||||
* Check curve is named curve type and one of our preferences, if not
|
||||
* server has sent an invalid curve.
|
||||
*/
|
||||
if (!tls1_check_curve(s, ecparams, 3)) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, SSL_R_WRONG_CURVE);
|
||||
if (curve_type != NAMED_CURVE_TYPE || !tls1_check_group_id(s, curve_id)) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_ECDHE,
|
||||
SSL_R_WRONG_CURVE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
curve_nid = tls1_ec_curve_id2nid(*(ecparams + 2), &curve_flags);
|
||||
|
||||
if (curve_nid == 0) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE,
|
||||
SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
|
||||
if ((s->s3->peer_tmp = ssl_generate_param_group(curve_id)) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
|
||||
SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((curve_flags & TLS_CURVE_TYPE) == TLS_CURVE_CUSTOM) {
|
||||
EVP_PKEY *key = EVP_PKEY_new();
|
||||
|
||||
if (key == NULL || !EVP_PKEY_set_type(key, curve_nid)) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, ERR_R_EVP_LIB);
|
||||
EVP_PKEY_free(key);
|
||||
return 0;
|
||||
}
|
||||
s->s3->peer_tmp = key;
|
||||
} else {
|
||||
/* Set up EVP_PKEY with named curve as parameters */
|
||||
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
|
||||
if (pctx == NULL
|
||||
|| EVP_PKEY_paramgen_init(pctx) <= 0
|
||||
|| EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, curve_nid) <= 0
|
||||
|| EVP_PKEY_paramgen(pctx, &s->s3->peer_tmp) <= 0) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, ERR_R_EVP_LIB);
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
return 0;
|
||||
}
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
pctx = NULL;
|
||||
}
|
||||
|
||||
if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, SSL_R_LENGTH_MISMATCH);
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
|
||||
PACKET_data(&encoded_pt),
|
||||
PACKET_remaining(&encoded_pt))) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, SSL_R_BAD_ECPOINT);
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_ECDHE,
|
||||
SSL_R_BAD_ECPOINT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1582,17 +2231,18 @@ static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey, int *al)
|
||||
|
||||
return 1;
|
||||
#else
|
||||
SSLerr(SSL_F_TLS_PROCESS_SKE_ECDHE, ERR_R_INTERNAL_ERROR);
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
|
||||
{
|
||||
int al = -1;
|
||||
long alg_k;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
EVP_MD_CTX *md_ctx = NULL;
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
PACKET save_param_start, signature;
|
||||
|
||||
alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
|
||||
@@ -1605,24 +2255,32 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
|
||||
#endif
|
||||
|
||||
if (alg_k & SSL_PSK) {
|
||||
if (!tls_process_ske_psk_preamble(s, pkt, &al))
|
||||
if (!tls_process_ske_psk_preamble(s, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Nothing else to do for plain PSK or RSAPSK */
|
||||
if (alg_k & (SSL_kPSK | SSL_kRSAPSK)) {
|
||||
} else if (alg_k & SSL_kSRP) {
|
||||
if (!tls_process_ske_srp(s, pkt, &pkey, &al))
|
||||
if (!tls_process_ske_srp(s, pkt, &pkey)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
|
||||
if (!tls_process_ske_dhe(s, pkt, &pkey, &al))
|
||||
if (!tls_process_ske_dhe(s, pkt, &pkey)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
|
||||
if (!tls_process_ske_ecdhe(s, pkt, &pkey, &al))
|
||||
if (!tls_process_ske_ecdhe(s, pkt, &pkey)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else if (alg_k) {
|
||||
al = SSL_AD_UNEXPECTED_MESSAGE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_UNEXPECTED_MESSAGE);
|
||||
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
|
||||
SSL_R_UNEXPECTED_MESSAGE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -1631,7 +2289,9 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
|
||||
PACKET params;
|
||||
int maxsig;
|
||||
const EVP_MD *md = NULL;
|
||||
EVP_MD_CTX *md_ctx;
|
||||
unsigned char *tbs;
|
||||
size_t tbslen;
|
||||
int rv;
|
||||
|
||||
/*
|
||||
* |pkt| now points to the beginning of the signature, so the difference
|
||||
@@ -1640,46 +2300,49 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
|
||||
if (!PACKET_get_sub_packet(&save_param_start, ¶ms,
|
||||
PACKET_remaining(&save_param_start) -
|
||||
PACKET_remaining(pkt))) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (SSL_USE_SIGALGS(s)) {
|
||||
const unsigned char *sigalgs;
|
||||
int rv;
|
||||
if (!PACKET_get_bytes(pkt, &sigalgs, 2)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_TOO_SHORT);
|
||||
unsigned int sigalg;
|
||||
|
||||
if (!PACKET_get_net_2(pkt, &sigalg)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
|
||||
SSL_R_LENGTH_TOO_SHORT);
|
||||
goto err;
|
||||
}
|
||||
rv = tls12_check_peer_sigalg(&md, s, sigalgs, pkey);
|
||||
if (rv == -1) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
goto err;
|
||||
} else if (rv == 0) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
if (tls12_check_peer_sigalg(s, sigalg, pkey) <=0) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else if (!tls1_set_peer_legacy_sigalg(s, pkey)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
#ifdef SSL_DEBUG
|
||||
if (SSL_USE_SIGALGS(s))
|
||||
fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
|
||||
#endif
|
||||
} else if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
|
||||
md = EVP_md5_sha1();
|
||||
} else {
|
||||
md = EVP_sha1();
|
||||
}
|
||||
|
||||
if (!PACKET_get_length_prefixed_2(pkt, &signature)
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_LENGTH_MISMATCH);
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
maxsig = EVP_PKEY_size(pkey);
|
||||
if (maxsig < 0) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -1688,222 +2351,243 @@ MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
|
||||
*/
|
||||
if (PACKET_remaining(&signature) > (size_t)maxsig) {
|
||||
/* wrong packet length */
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE,
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
|
||||
SSL_R_WRONG_SIGNATURE_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
md_ctx = EVP_MD_CTX_new();
|
||||
if (md_ctx == NULL) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_VerifyInit_ex(md_ctx, md, NULL) <= 0
|
||||
|| EVP_VerifyUpdate(md_ctx, &(s->s3->client_random[0]),
|
||||
SSL3_RANDOM_SIZE) <= 0
|
||||
|| EVP_VerifyUpdate(md_ctx, &(s->s3->server_random[0]),
|
||||
SSL3_RANDOM_SIZE) <= 0
|
||||
|| EVP_VerifyUpdate(md_ctx, PACKET_data(¶ms),
|
||||
PACKET_remaining(¶ms)) <= 0) {
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
|
||||
if (EVP_DigestVerifyInit(md_ctx, &pctx, md, NULL, pkey) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
|
||||
ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (EVP_VerifyFinal(md_ctx, PACKET_data(&signature),
|
||||
PACKET_remaining(&signature), pkey) <= 0) {
|
||||
/* bad signature */
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
al = SSL_AD_DECRYPT_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_BAD_SIGNATURE);
|
||||
if (SSL_USE_PSS(s)) {
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
|
||||
|| EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
|
||||
RSA_PSS_SALTLEN_DIGEST) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
tbslen = construct_key_exchange_tbs(s, &tbs, PACKET_data(¶ms),
|
||||
PACKET_remaining(¶ms));
|
||||
if (tbslen == 0) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
rv = EVP_DigestVerify(md_ctx, PACKET_data(&signature),
|
||||
PACKET_remaining(&signature), tbs, tbslen);
|
||||
OPENSSL_free(tbs);
|
||||
if (rv <= 0) {
|
||||
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
|
||||
SSL_R_BAD_SIGNATURE);
|
||||
goto err;
|
||||
}
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
md_ctx = NULL;
|
||||
} else {
|
||||
/* aNULL, aSRP or PSK do not need public keys */
|
||||
if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
|
||||
&& !(alg_k & SSL_PSK)) {
|
||||
/* Might be wrong key type, check it */
|
||||
if (ssl3_check_cert_and_algorithm(s)) {
|
||||
/* Otherwise this shouldn't happen */
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
|
||||
} else {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
|
||||
SSL_R_BAD_DATA);
|
||||
}
|
||||
/* else this shouldn't happen, SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
/* still data left over */
|
||||
if (PACKET_remaining(pkt) != 0) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_KEY_EXCHANGE, SSL_R_EXTRA_DATA_IN_MESSAGE);
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
|
||||
SSL_R_EXTRA_DATA_IN_MESSAGE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return MSG_PROCESS_CONTINUE_READING;
|
||||
err:
|
||||
if (al != -1)
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
ossl_statem_set_error(s);
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
|
||||
{
|
||||
int ret = MSG_PROCESS_ERROR;
|
||||
unsigned int list_len, ctype_num, i, name_len;
|
||||
X509_NAME *xn = NULL;
|
||||
const unsigned char *data;
|
||||
const unsigned char *namestart, *namebytes;
|
||||
STACK_OF(X509_NAME) *ca_sk = NULL;
|
||||
size_t i;
|
||||
|
||||
if ((ca_sk = sk_X509_NAME_new(ca_dn_cmp)) == NULL) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
/* Clear certificate validity flags */
|
||||
for (i = 0; i < SSL_PKEY_NUM; i++)
|
||||
s->s3->tmp.valid_flags[i] = 0;
|
||||
|
||||
/* get the certificate types */
|
||||
if (!PACKET_get_1(pkt, &ctype_num)
|
||||
|| !PACKET_get_bytes(pkt, &data, ctype_num)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_free(s->cert->ctypes);
|
||||
s->cert->ctypes = NULL;
|
||||
if (ctype_num > SSL3_CT_NUMBER) {
|
||||
/* If we exceed static buffer copy all to cert structure */
|
||||
s->cert->ctypes = OPENSSL_malloc(ctype_num);
|
||||
if (s->cert->ctypes == NULL) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
memcpy(s->cert->ctypes, data, ctype_num);
|
||||
s->cert->ctype_num = (size_t)ctype_num;
|
||||
ctype_num = SSL3_CT_NUMBER;
|
||||
}
|
||||
for (i = 0; i < ctype_num; i++)
|
||||
s->s3->tmp.ctype[i] = data[i];
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
PACKET reqctx, extensions;
|
||||
RAW_EXTENSION *rawexts = NULL;
|
||||
|
||||
if (SSL_USE_SIGALGS(s)) {
|
||||
if (!PACKET_get_net_2(pkt, &list_len)
|
||||
|| !PACKET_get_bytes(pkt, &data, list_len)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
/* Free and zero certificate types: it is not present in TLS 1.3 */
|
||||
OPENSSL_free(s->s3->tmp.ctype);
|
||||
s->s3->tmp.ctype = NULL;
|
||||
s->s3->tmp.ctype_len = 0;
|
||||
OPENSSL_free(s->pha_context);
|
||||
s->pha_context = NULL;
|
||||
|
||||
if (!PACKET_get_length_prefixed_1(pkt, &reqctx) ||
|
||||
!PACKET_memdup(&reqctx, &s->pha_context, &s->pha_context_len)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
/* Clear certificate digests and validity flags */
|
||||
for (i = 0; i < SSL_PKEY_NUM; i++) {
|
||||
s->s3->tmp.md[i] = NULL;
|
||||
s->s3->tmp.valid_flags[i] = 0;
|
||||
if (!PACKET_get_length_prefixed_2(pkt, &extensions)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
|
||||
SSL_R_BAD_LENGTH);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
if ((list_len & 1) || !tls1_save_sigalgs(s, data, list_len)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
|
||||
SSL_R_SIGNATURE_ALGORITHMS_ERROR);
|
||||
goto err;
|
||||
if (!tls_collect_extensions(s, &extensions,
|
||||
SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
|
||||
&rawexts, NULL, 1)
|
||||
|| !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
|
||||
rawexts, NULL, 0, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
OPENSSL_free(rawexts);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
OPENSSL_free(rawexts);
|
||||
if (!tls1_process_sigalgs(s)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
|
||||
SSL_R_BAD_LENGTH);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
} else {
|
||||
ssl_set_default_md(s);
|
||||
PACKET ctypes;
|
||||
|
||||
/* get the certificate types */
|
||||
if (!PACKET_get_length_prefixed_1(pkt, &ctypes)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
if (!PACKET_memdup(&ctypes, &s->s3->tmp.ctype, &s->s3->tmp.ctype_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
if (SSL_USE_SIGALGS(s)) {
|
||||
PACKET sigalgs;
|
||||
|
||||
if (!PACKET_get_length_prefixed_2(pkt, &sigalgs)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Despite this being for certificates, preserve compatibility
|
||||
* with pre-TLS 1.3 and use the regular sigalgs field.
|
||||
*/
|
||||
if (!tls1_save_sigalgs(s, &sigalgs, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
|
||||
SSL_R_SIGNATURE_ALGORITHMS_ERROR);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
if (!tls1_process_sigalgs(s)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the CA RDNs */
|
||||
if (!parse_ca_names(s, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* get the CA RDNs */
|
||||
if (!PACKET_get_net_2(pkt, &list_len)
|
||||
|| PACKET_remaining(pkt) != list_len) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (PACKET_remaining(pkt)) {
|
||||
if (!PACKET_get_net_2(pkt, &name_len)
|
||||
|| !PACKET_get_bytes(pkt, &namebytes, name_len)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
namestart = namebytes;
|
||||
|
||||
if ((xn = d2i_X509_NAME(NULL, (const unsigned char **)&namebytes,
|
||||
name_len)) == NULL) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_ASN1_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (namebytes != (namestart + name_len)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
|
||||
SSL_R_CA_DN_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
if (!sk_X509_NAME_push(ca_sk, xn)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
xn = NULL;
|
||||
if (PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
/* we should setup a certificate to return.... */
|
||||
s->s3->tmp.cert_req = 1;
|
||||
s->s3->tmp.ctype_num = ctype_num;
|
||||
sk_X509_NAME_pop_free(s->s3->tmp.ca_names, X509_NAME_free);
|
||||
s->s3->tmp.ca_names = ca_sk;
|
||||
ca_sk = NULL;
|
||||
|
||||
ret = MSG_PROCESS_CONTINUE_PROCESSING;
|
||||
goto done;
|
||||
err:
|
||||
ossl_statem_set_error(s);
|
||||
done:
|
||||
X509_NAME_free(xn);
|
||||
sk_X509_NAME_pop_free(ca_sk, X509_NAME_free);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
|
||||
{
|
||||
return (X509_NAME_cmp(*a, *b));
|
||||
return MSG_PROCESS_CONTINUE_PROCESSING;
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
|
||||
{
|
||||
int al;
|
||||
unsigned int ticklen;
|
||||
unsigned long ticket_lifetime_hint;
|
||||
unsigned long ticket_lifetime_hint, age_add = 0;
|
||||
unsigned int sess_len;
|
||||
RAW_EXTENSION *exts = NULL;
|
||||
PACKET nonce;
|
||||
|
||||
if (!PACKET_get_net_4(pkt, &ticket_lifetime_hint)
|
||||
|| (SSL_IS_TLS13(s)
|
||||
&& (!PACKET_get_net_4(pkt, &age_add)
|
||||
|| !PACKET_get_length_prefixed_1(pkt, &nonce)
|
||||
|| !PACKET_memdup(&nonce, &s->session->ext.tick_nonce,
|
||||
&s->session->ext.tick_nonce_len)))
|
||||
|| !PACKET_get_net_2(pkt, &ticklen)
|
||||
|| PACKET_remaining(pkt) != ticklen) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
|| (!SSL_IS_TLS13(s) && PACKET_remaining(pkt) != ticklen)
|
||||
|| (SSL_IS_TLS13(s)
|
||||
&& (ticklen == 0 || PACKET_remaining(pkt) < ticklen))) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Server is allowed to change its mind and send an empty ticket. */
|
||||
/*
|
||||
* Server is allowed to change its mind (in <=TLSv1.2) and send an empty
|
||||
* ticket. We already checked this TLSv1.3 case above, so it should never
|
||||
* be 0 here in that instance
|
||||
*/
|
||||
if (ticklen == 0)
|
||||
return MSG_PROCESS_CONTINUE_READING;
|
||||
|
||||
if (s->session->session_id_length > 0) {
|
||||
/*
|
||||
* Sessions must be immutable once they go into the session cache. Otherwise
|
||||
* we can get multi-thread problems. Therefore we don't "update" sessions,
|
||||
* we replace them with a duplicate. In TLSv1.3 we need to do this every
|
||||
* time a NewSessionTicket arrives because those messages arrive
|
||||
* post-handshake and the session may have already gone into the session
|
||||
* cache.
|
||||
*/
|
||||
if (SSL_IS_TLS13(s) || s->session->session_id_length > 0) {
|
||||
int i = s->session_ctx->session_cache_mode;
|
||||
SSL_SESSION *new_sess;
|
||||
/*
|
||||
* We reused an existing session, so we need to replace it with a new
|
||||
* one
|
||||
*/
|
||||
if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (i & SSL_SESS_CACHE_CLIENT) {
|
||||
/*
|
||||
* Remove the old session from the cache. We carry on if this fails
|
||||
@@ -1911,32 +2595,52 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
|
||||
SSL_CTX_remove_session(s->session_ctx, s->session);
|
||||
}
|
||||
|
||||
if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
SSL_SESSION_free(s->session);
|
||||
s->session = new_sess;
|
||||
}
|
||||
|
||||
OPENSSL_free(s->session->tlsext_tick);
|
||||
s->session->tlsext_ticklen = 0;
|
||||
/*
|
||||
* Technically the cast to long here is not guaranteed by the C standard -
|
||||
* but we use it elsewhere, so this should be ok.
|
||||
*/
|
||||
s->session->time = (long)time(NULL);
|
||||
|
||||
s->session->tlsext_tick = OPENSSL_malloc(ticklen);
|
||||
if (s->session->tlsext_tick == NULL) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
|
||||
OPENSSL_free(s->session->ext.tick);
|
||||
s->session->ext.tick = NULL;
|
||||
s->session->ext.ticklen = 0;
|
||||
|
||||
s->session->ext.tick = OPENSSL_malloc(ticklen);
|
||||
if (s->session->ext.tick == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (!PACKET_copy_bytes(pkt, s->session->tlsext_tick, ticklen)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, SSL_R_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
if (!PACKET_copy_bytes(pkt, s->session->ext.tick, ticklen)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->session->ext.tick_lifetime_hint = ticket_lifetime_hint;
|
||||
s->session->ext.tick_age_add = age_add;
|
||||
s->session->ext.ticklen = ticklen;
|
||||
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
PACKET extpkt;
|
||||
|
||||
if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
|
||||
|| PACKET_remaining(pkt) != 0
|
||||
|| !tls_collect_extensions(s, &extpkt,
|
||||
SSL_EXT_TLS1_3_NEW_SESSION_TICKET,
|
||||
&exts, NULL, 1)
|
||||
|| !tls_parse_all_extensions(s,
|
||||
SSL_EXT_TLS1_3_NEW_SESSION_TICKET,
|
||||
exts, NULL, 0, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
s->session->tlsext_tick_lifetime_hint = ticket_lifetime_hint;
|
||||
s->session->tlsext_ticklen = ticklen;
|
||||
/*
|
||||
* There are two ways to detect a resumed ticket session. One is to set
|
||||
* an appropriate session ID and then the server must return a match in
|
||||
@@ -1948,123 +2652,159 @@ MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
|
||||
* elsewhere in OpenSSL. The session ID is set to the SHA256 (or SHA1 is
|
||||
* SHA256 is disabled) hash of the ticket.
|
||||
*/
|
||||
if (!EVP_Digest(s->session->tlsext_tick, ticklen,
|
||||
s->session->session_id, &s->session->session_id_length,
|
||||
/*
|
||||
* TODO(size_t): we use sess_len here because EVP_Digest expects an int
|
||||
* but s->session->session_id_length is a size_t
|
||||
*/
|
||||
if (!EVP_Digest(s->session->ext.tick, ticklen,
|
||||
s->session->session_id, &sess_len,
|
||||
EVP_sha256(), NULL)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_NEW_SESSION_TICKET, ERR_R_EVP_LIB);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
|
||||
ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
s->session->session_id_length = sess_len;
|
||||
|
||||
/* This is a standalone message in TLSv1.3, so there is no more to read */
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
OPENSSL_free(exts);
|
||||
ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
|
||||
return MSG_PROCESS_FINISHED_READING;
|
||||
}
|
||||
|
||||
return MSG_PROCESS_CONTINUE_READING;
|
||||
f_err:
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
err:
|
||||
ossl_statem_set_error(s);
|
||||
OPENSSL_free(exts);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt)
|
||||
/*
|
||||
* In TLSv1.3 this is called from the extensions code, otherwise it is used to
|
||||
* parse a separate message. Returns 1 on success or 0 on failure
|
||||
*/
|
||||
int tls_process_cert_status_body(SSL *s, PACKET *pkt)
|
||||
{
|
||||
int al;
|
||||
unsigned long resplen;
|
||||
size_t resplen;
|
||||
unsigned int type;
|
||||
|
||||
if (!PACKET_get_1(pkt, &type)
|
||||
|| type != TLSEXT_STATUSTYPE_ocsp) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERT_STATUS, SSL_R_UNSUPPORTED_STATUS_TYPE);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
|
||||
SSL_R_UNSUPPORTED_STATUS_TYPE);
|
||||
return 0;
|
||||
}
|
||||
if (!PACKET_get_net_3(pkt, &resplen)
|
||||
if (!PACKET_get_net_3_len(pkt, &resplen)
|
||||
|| PACKET_remaining(pkt) != resplen) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
s->tlsext_ocsp_resp = OPENSSL_malloc(resplen);
|
||||
if (s->tlsext_ocsp_resp == NULL) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERT_STATUS, ERR_R_MALLOC_FAILURE);
|
||||
goto f_err;
|
||||
s->ext.ocsp.resp = OPENSSL_malloc(resplen);
|
||||
if (s->ext.ocsp.resp == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (!PACKET_copy_bytes(pkt, s->tlsext_ocsp_resp, resplen)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
if (!PACKET_copy_bytes(pkt, s->ext.ocsp.resp, resplen)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
s->tlsext_ocsp_resplen = resplen;
|
||||
return MSG_PROCESS_CONTINUE_READING;
|
||||
f_err:
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
ossl_statem_set_error(s);
|
||||
return MSG_PROCESS_ERROR;
|
||||
s->ext.ocsp.resp_len = resplen;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt)
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt)
|
||||
{
|
||||
if (PACKET_remaining(pkt) > 0) {
|
||||
/* should contain no data */
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_DONE, SSL_R_LENGTH_MISMATCH);
|
||||
ossl_statem_set_error(s);
|
||||
if (!tls_process_cert_status_body(s, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
|
||||
if (SRP_Calc_A_param(s) <= 0) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_DONE, SSL_R_SRP_A_CALC);
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
ossl_statem_set_error(s);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return MSG_PROCESS_CONTINUE_READING;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform miscellaneous checks and processing after we have received the
|
||||
* server's initial flight. In TLS1.3 this is after the Server Finished message.
|
||||
* In <=TLS1.2 this is after the ServerDone message. Returns 1 on success or 0
|
||||
* on failure.
|
||||
*/
|
||||
int tls_process_initial_server_flight(SSL *s)
|
||||
{
|
||||
/*
|
||||
* at this point we check that we have the required stuff from
|
||||
* the server
|
||||
*/
|
||||
if (!ssl3_check_cert_and_algorithm(s)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
|
||||
ossl_statem_set_error(s);
|
||||
return MSG_PROCESS_ERROR;
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call the ocsp status callback if needed. The |tlsext_ocsp_resp| and
|
||||
* |tlsext_ocsp_resplen| values will be set if we actually received a status
|
||||
* Call the ocsp status callback if needed. The |ext.ocsp.resp| and
|
||||
* |ext.ocsp.resp_len| values will be set if we actually received a status
|
||||
* message, or NULL and -1 otherwise
|
||||
*/
|
||||
if (s->tlsext_status_type != -1 && s->ctx->tlsext_status_cb != NULL) {
|
||||
int ret;
|
||||
ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
|
||||
if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing
|
||||
&& s->ctx->ext.status_cb != NULL) {
|
||||
int ret = s->ctx->ext.status_cb(s, s->ctx->ext.status_arg);
|
||||
|
||||
if (ret == 0) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL,
|
||||
SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE);
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_DONE,
|
||||
SSL_R_INVALID_STATUS_RESPONSE);
|
||||
return MSG_PROCESS_ERROR;
|
||||
SSLfatal(s, SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE,
|
||||
SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT,
|
||||
SSL_R_INVALID_STATUS_RESPONSE);
|
||||
return 0;
|
||||
}
|
||||
if (ret < 0) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_DONE, ERR_R_MALLOC_FAILURE);
|
||||
return MSG_PROCESS_ERROR;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#ifndef OPENSSL_NO_CT
|
||||
if (s->ct_validation_callback != NULL) {
|
||||
/* Note we validate the SCTs whether or not we abort on error */
|
||||
if (!ssl_validate_ct(s) && (s->verify_mode & SSL_VERIFY_PEER)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt)
|
||||
{
|
||||
if (PACKET_remaining(pkt) > 0) {
|
||||
/* should contain no data */
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_DONE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
|
||||
if (SRP_Calc_A_param(s) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_DONE,
|
||||
SSL_R_SRP_A_CALC);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!tls_process_initial_server_flight(s)) {
|
||||
/* SSLfatal() already called */
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
return MSG_PROCESS_FINISHED_READING;
|
||||
}
|
||||
|
||||
static int tls_construct_cke_psk_preamble(SSL *s, unsigned char **p,
|
||||
size_t *pskhdrlen, int *al)
|
||||
static int tls_construct_cke_psk_preamble(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_PSK
|
||||
int ret = 0;
|
||||
@@ -2081,8 +2821,8 @@ static int tls_construct_cke_psk_preamble(SSL *s, unsigned char **p,
|
||||
size_t psklen = 0;
|
||||
|
||||
if (s->psk_client_callback == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, SSL_R_PSK_NO_CLIENT_CB);
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
|
||||
SSL_R_PSK_NO_CLIENT_CB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -2093,28 +2833,28 @@ static int tls_construct_cke_psk_preamble(SSL *s, unsigned char **p,
|
||||
psk, sizeof(psk));
|
||||
|
||||
if (psklen > PSK_MAX_PSK_LEN) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
|
||||
*al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
} else if (psklen == 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
|
||||
SSL_R_PSK_IDENTITY_NOT_FOUND);
|
||||
*al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
|
||||
SSL_R_PSK_IDENTITY_NOT_FOUND);
|
||||
goto err;
|
||||
}
|
||||
|
||||
identitylen = strlen(identity);
|
||||
if (identitylen > PSK_MAX_IDENTITY_LEN) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
|
||||
*al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
tmppsk = OPENSSL_memdup(psk, psklen);
|
||||
tmpidentity = OPENSSL_strdup(identity);
|
||||
if (tmppsk == NULL || tmpidentity == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_MALLOC_FAILURE);
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -2125,10 +2865,12 @@ static int tls_construct_cke_psk_preamble(SSL *s, unsigned char **p,
|
||||
OPENSSL_free(s->session->psk_identity);
|
||||
s->session->psk_identity = tmpidentity;
|
||||
tmpidentity = NULL;
|
||||
s2n(identitylen, *p);
|
||||
memcpy(*p, identity, identitylen);
|
||||
*pskhdrlen = 2 + identitylen;
|
||||
*p += identitylen;
|
||||
|
||||
if (!WPACKET_sub_memcpy_u16(pkt, identity, identitylen)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
@@ -2140,16 +2882,16 @@ static int tls_construct_cke_psk_preamble(SSL *s, unsigned char **p,
|
||||
|
||||
return ret;
|
||||
#else
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_construct_cke_rsa(SSL *s, unsigned char **p, int *len, int *al)
|
||||
static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
unsigned char *q;
|
||||
unsigned char *encdata = NULL;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
size_t enclen;
|
||||
@@ -2160,58 +2902,68 @@ static int tls_construct_cke_rsa(SSL *s, unsigned char **p, int *len, int *al)
|
||||
/*
|
||||
* We should always have a server certificate with SSL_kRSA.
|
||||
*/
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pkey = X509_get0_pubkey(s->session->peer);
|
||||
if (EVP_PKEY_get0_RSA(pkey) == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pmslen = SSL_MAX_MASTER_KEY_LENGTH;
|
||||
pms = OPENSSL_malloc(pmslen);
|
||||
if (pms == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_MALLOC_FAILURE);
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pms[0] = s->client_version >> 8;
|
||||
pms[1] = s->client_version & 0xff;
|
||||
if (RAND_bytes(pms + 2, pmslen - 2) <= 0) {
|
||||
/* TODO(size_t): Convert this function */
|
||||
if (ssl_randbytes(s, pms + 2, (int)(pmslen - 2)) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
q = *p;
|
||||
/* Fix buf for TLS and beyond */
|
||||
if (s->version > SSL3_VERSION)
|
||||
*p += 2;
|
||||
if (s->version > SSL3_VERSION && !WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
pctx = EVP_PKEY_CTX_new(pkey, NULL);
|
||||
if (pctx == NULL || EVP_PKEY_encrypt_init(pctx) <= 0
|
||||
|| EVP_PKEY_encrypt(pctx, NULL, &enclen, pms, pmslen) <= 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_EVP_LIB);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
|
||||
ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (EVP_PKEY_encrypt(pctx, *p, &enclen, pms, pmslen) <= 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, SSL_R_BAD_RSA_ENCRYPT);
|
||||
if (!WPACKET_allocate_bytes(pkt, enclen, &encdata)
|
||||
|| EVP_PKEY_encrypt(pctx, encdata, &enclen, pms, pmslen) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
|
||||
SSL_R_BAD_RSA_ENCRYPT);
|
||||
goto err;
|
||||
}
|
||||
*len = enclen;
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
pctx = NULL;
|
||||
# ifdef PKCS1_CHECK
|
||||
if (s->options & SSL_OP_PKCS1_CHECK_1)
|
||||
(*p)[1]++;
|
||||
if (s->options & SSL_OP_PKCS1_CHECK_2)
|
||||
tmp_buf[0] = 0x70;
|
||||
# endif
|
||||
|
||||
/* Fix buf for TLS and beyond */
|
||||
if (s->version > SSL3_VERSION) {
|
||||
s2n(*len, q);
|
||||
*len += 2;
|
||||
if (s->version > SSL3_VERSION && !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Log the premaster secret, if logging is enabled. */
|
||||
if (!ssl_log_rsa_client_key_exchange(s, encdata, enclen, pms, pmslen)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->s3->tmp.pms = pms;
|
||||
@@ -2224,75 +2976,94 @@ static int tls_construct_cke_rsa(SSL *s, unsigned char **p, int *len, int *al)
|
||||
|
||||
return 0;
|
||||
#else
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_RSA, ERR_R_INTERNAL_ERROR);
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_construct_cke_dhe(SSL *s, unsigned char **p, int *len, int *al)
|
||||
static int tls_construct_cke_dhe(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_DH
|
||||
DH *dh_clnt = NULL;
|
||||
const BIGNUM *pub_key;
|
||||
EVP_PKEY *ckey = NULL, *skey = NULL;
|
||||
unsigned char *keybytes = NULL;
|
||||
|
||||
skey = s->s3->peer_tmp;
|
||||
if (skey == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_DHE, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ckey = ssl_generate_pkey(skey);
|
||||
if (ckey == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_DHE, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
dh_clnt = EVP_PKEY_get0_DH(ckey);
|
||||
|
||||
if (dh_clnt == NULL || ssl_derive(s, ckey, skey) == 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_DHE, ERR_R_INTERNAL_ERROR);
|
||||
EVP_PKEY_free(ckey);
|
||||
return 0;
|
||||
if (dh_clnt == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ssl_derive(s, ckey, skey, 0) == 0) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* send off the data */
|
||||
DH_get0_key(dh_clnt, &pub_key, NULL);
|
||||
*len = BN_num_bytes(pub_key);
|
||||
s2n(*len, *p);
|
||||
BN_bn2bin(pub_key, *p);
|
||||
*len += 2;
|
||||
if (!WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(pub_key),
|
||||
&keybytes)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
BN_bn2bin(pub_key, keybytes);
|
||||
EVP_PKEY_free(ckey);
|
||||
|
||||
return 1;
|
||||
err:
|
||||
EVP_PKEY_free(ckey);
|
||||
return 0;
|
||||
#else
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_DHE, ERR_R_INTERNAL_ERROR);
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_construct_cke_ecdhe(SSL *s, unsigned char **p, int *len, int *al)
|
||||
static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_EC
|
||||
unsigned char *encodedPoint = NULL;
|
||||
int encoded_pt_len = 0;
|
||||
size_t encoded_pt_len = 0;
|
||||
EVP_PKEY *ckey = NULL, *skey = NULL;
|
||||
int ret = 0;
|
||||
|
||||
skey = s->s3->peer_tmp;
|
||||
if (skey == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ckey = ssl_generate_pkey(skey);
|
||||
if (ckey == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ssl_derive(s, ckey, skey) == 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_EVP_LIB);
|
||||
if (ssl_derive(s, ckey, skey, 0) == 0) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -2300,37 +3071,30 @@ static int tls_construct_cke_ecdhe(SSL *s, unsigned char **p, int *len, int *al)
|
||||
encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(ckey, &encodedPoint);
|
||||
|
||||
if (encoded_pt_len == 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_EC_LIB);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
|
||||
ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
EVP_PKEY_free(ckey);
|
||||
ckey = NULL;
|
||||
if (!WPACKET_sub_memcpy_u8(pkt, encodedPoint, encoded_pt_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
*len = encoded_pt_len;
|
||||
|
||||
/* length of encoded point */
|
||||
**p = *len;
|
||||
*p += 1;
|
||||
/* copy the point */
|
||||
memcpy(*p, encodedPoint, *len);
|
||||
/* increment len to account for length field */
|
||||
*len += 1;
|
||||
|
||||
OPENSSL_free(encodedPoint);
|
||||
|
||||
return 1;
|
||||
ret = 1;
|
||||
err:
|
||||
OPENSSL_free(encodedPoint);
|
||||
EVP_PKEY_free(ckey);
|
||||
return 0;
|
||||
return ret;
|
||||
#else
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_construct_cke_gost(SSL *s, unsigned char **p, int *len, int *al)
|
||||
static int tls_construct_cke_gost(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
/* GOST key exchange message creation */
|
||||
@@ -2352,16 +3116,15 @@ static int tls_construct_cke_gost(SSL *s, unsigned char **p, int *len, int *al)
|
||||
*/
|
||||
peer_cert = s->session->peer;
|
||||
if (!peer_cert) {
|
||||
*al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST,
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CONSTRUCT_CKE_GOST,
|
||||
SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pkey_ctx = EVP_PKEY_CTX_new(X509_get0_pubkey(peer_cert), NULL);
|
||||
if (pkey_ctx == NULL) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_MALLOC_FAILURE);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
@@ -2374,16 +3137,18 @@ static int tls_construct_cke_gost(SSL *s, unsigned char **p, int *len, int *al)
|
||||
pmslen = 32;
|
||||
pms = OPENSSL_malloc(pmslen);
|
||||
if (pms == NULL) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_MALLOC_FAILURE);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0
|
||||
/* Generate session key */
|
||||
|| RAND_bytes(pms, pmslen) <= 0) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR);
|
||||
/* Generate session key
|
||||
* TODO(size_t): Convert this function
|
||||
*/
|
||||
|| ssl_randbytes(s, pms, (int)pmslen) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
};
|
||||
/*
|
||||
@@ -2398,38 +3163,36 @@ static int tls_construct_cke_gost(SSL *s, unsigned char **p, int *len, int *al)
|
||||
|| EVP_DigestUpdate(ukm_hash, s->s3->server_random,
|
||||
SSL3_RANDOM_SIZE) <= 0
|
||||
|| EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len) <= 0) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
EVP_MD_CTX_free(ukm_hash);
|
||||
ukm_hash = NULL;
|
||||
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
|
||||
EVP_PKEY_CTRL_SET_IV, 8, shared_ukm) < 0) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, SSL_R_LIBRARY_BUG);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
|
||||
SSL_R_LIBRARY_BUG);
|
||||
goto err;
|
||||
}
|
||||
/* Make GOST keytransport blob message */
|
||||
/*
|
||||
* Encapsulate it into sequence
|
||||
*/
|
||||
*((*p)++) = V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED;
|
||||
msglen = 255;
|
||||
if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, SSL_R_LIBRARY_BUG);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
|
||||
SSL_R_LIBRARY_BUG);
|
||||
goto err;
|
||||
}
|
||||
if (msglen >= 0x80) {
|
||||
*((*p)++) = 0x81;
|
||||
*((*p)++) = msglen & 0xff;
|
||||
*len = msglen + 3;
|
||||
} else {
|
||||
*((*p)++) = msglen & 0xff;
|
||||
*len = msglen + 2;
|
||||
|
||||
if (!WPACKET_put_bytes_u8(pkt, V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)
|
||||
|| (msglen >= 0x80 && !WPACKET_put_bytes_u8(pkt, 0x81))
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, tmp, msglen)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
memcpy(*p, tmp, msglen);
|
||||
|
||||
EVP_PKEY_CTX_free(pkey_ctx);
|
||||
s->s3->tmp.pms = pms;
|
||||
@@ -2442,98 +3205,85 @@ static int tls_construct_cke_gost(SSL *s, unsigned char **p, int *len, int *al)
|
||||
EVP_MD_CTX_free(ukm_hash);
|
||||
return 0;
|
||||
#else
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_GOST, ERR_R_INTERNAL_ERROR);
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_construct_cke_srp(SSL *s, unsigned char **p, int *len, int *al)
|
||||
static int tls_construct_cke_srp(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
if (s->srp_ctx.A != NULL) {
|
||||
/* send off the data */
|
||||
*len = BN_num_bytes(s->srp_ctx.A);
|
||||
s2n(*len, *p);
|
||||
BN_bn2bin(s->srp_ctx.A, *p);
|
||||
*len += 2;
|
||||
} else {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_SRP, ERR_R_INTERNAL_ERROR);
|
||||
unsigned char *abytes = NULL;
|
||||
|
||||
if (s->srp_ctx.A == NULL
|
||||
|| !WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(s->srp_ctx.A),
|
||||
&abytes)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
BN_bn2bin(s->srp_ctx.A, abytes);
|
||||
|
||||
OPENSSL_free(s->session->srp_username);
|
||||
s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
|
||||
if (s->session->srp_username == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_SRP, ERR_R_MALLOC_FAILURE);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
#else
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CKE_SRP, ERR_R_INTERNAL_ERROR);
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int tls_construct_client_key_exchange(SSL *s)
|
||||
int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
unsigned char *p;
|
||||
int len;
|
||||
size_t pskhdrlen = 0;
|
||||
unsigned long alg_k;
|
||||
int al = -1;
|
||||
|
||||
alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
|
||||
|
||||
p = ssl_handshake_start(s);
|
||||
|
||||
/*
|
||||
* All of the construct functions below call SSLfatal() if necessary so
|
||||
* no need to do so here.
|
||||
*/
|
||||
if ((alg_k & SSL_PSK)
|
||||
&& !tls_construct_cke_psk_preamble(s, &p, &pskhdrlen, &al))
|
||||
&& !tls_construct_cke_psk_preamble(s, pkt))
|
||||
goto err;
|
||||
|
||||
if (alg_k & SSL_kPSK) {
|
||||
len = 0;
|
||||
} else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
|
||||
if (!tls_construct_cke_rsa(s, &p, &len, &al))
|
||||
if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
|
||||
if (!tls_construct_cke_rsa(s, pkt))
|
||||
goto err;
|
||||
} else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
|
||||
if (!tls_construct_cke_dhe(s, &p, &len, &al))
|
||||
if (!tls_construct_cke_dhe(s, pkt))
|
||||
goto err;
|
||||
} else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
|
||||
if (!tls_construct_cke_ecdhe(s, &p, &len, &al))
|
||||
if (!tls_construct_cke_ecdhe(s, pkt))
|
||||
goto err;
|
||||
} else if (alg_k & SSL_kGOST) {
|
||||
if (!tls_construct_cke_gost(s, &p, &len, &al))
|
||||
if (!tls_construct_cke_gost(s, pkt))
|
||||
goto err;
|
||||
} else if (alg_k & SSL_kSRP) {
|
||||
if (!tls_construct_cke_srp(s, &p, &len, &al))
|
||||
if (!tls_construct_cke_srp(s, pkt))
|
||||
goto err;
|
||||
} else {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
len += pskhdrlen;
|
||||
|
||||
if (!ssl_set_handshake_header(s, SSL3_MT_CLIENT_KEY_EXCHANGE, len)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
|
||||
} else if (!(alg_k & SSL_kPSK)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 1;
|
||||
err:
|
||||
if (al != -1)
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
|
||||
s->s3->tmp.pms = NULL;
|
||||
#ifndef OPENSSL_NO_PSK
|
||||
OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
|
||||
s->s3->tmp.psk = NULL;
|
||||
#endif
|
||||
ossl_statem_set_error(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2549,8 +3299,7 @@ int tls_client_key_exchange_post_work(SSL *s)
|
||||
/* Check for SRP */
|
||||
if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
|
||||
if (!srp_generate_client_master_secret(s)) {
|
||||
SSLerr(SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
return 1;
|
||||
@@ -2558,13 +3307,12 @@ int tls_client_key_exchange_post_work(SSL *s)
|
||||
#endif
|
||||
|
||||
if (pms == NULL && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
SSLerr(SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_MALLOC_FAILURE);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if (!ssl_generate_master_secret(s, pms, pmslen, 1)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
SSLerr(SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_INTERNAL_ERROR);
|
||||
/* SSLfatal() already called */
|
||||
/* ssl_generate_master_secret frees the pms even on error */
|
||||
pms = NULL;
|
||||
pmslen = 0;
|
||||
@@ -2587,8 +3335,12 @@ int tls_client_key_exchange_post_work(SSL *s)
|
||||
|
||||
if (SSL_export_keying_material(s, sctpauthkey,
|
||||
sizeof(sctpauthkey), labelbuffer,
|
||||
sizeof(labelbuffer), NULL, 0, 0) <= 0)
|
||||
sizeof(labelbuffer), NULL, 0, 0) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
|
||||
sizeof(sctpauthkey), sctpauthkey);
|
||||
@@ -2602,79 +3354,6 @@ int tls_client_key_exchange_post_work(SSL *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tls_construct_client_verify(SSL *s)
|
||||
{
|
||||
unsigned char *p;
|
||||
EVP_PKEY *pkey;
|
||||
const EVP_MD *md = s->s3->tmp.md[s->cert->key - s->cert->pkeys];
|
||||
EVP_MD_CTX *mctx;
|
||||
unsigned u = 0;
|
||||
unsigned long n = 0;
|
||||
long hdatalen = 0;
|
||||
void *hdata;
|
||||
|
||||
mctx = EVP_MD_CTX_new();
|
||||
if (mctx == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
p = ssl_handshake_start(s);
|
||||
pkey = s->cert->key->privatekey;
|
||||
|
||||
hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
|
||||
if (hdatalen <= 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (SSL_USE_SIGALGS(s)) {
|
||||
if (!tls12_get_sigandhash(p, pkey, md)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
p += 2;
|
||||
n = 2;
|
||||
}
|
||||
#ifdef SSL_DEBUG
|
||||
fprintf(stderr, "Using client alg %s\n", EVP_MD_name(md));
|
||||
#endif
|
||||
if (!EVP_SignInit_ex(mctx, md, NULL)
|
||||
|| !EVP_SignUpdate(mctx, hdata, hdatalen)
|
||||
|| (s->version == SSL3_VERSION
|
||||
&& !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
|
||||
s->session->master_key_length,
|
||||
s->session->master_key))
|
||||
|| !EVP_SignFinal(mctx, p + 2, &u, pkey)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
{
|
||||
int pktype = EVP_PKEY_id(pkey);
|
||||
if (pktype == NID_id_GostR3410_2001
|
||||
|| pktype == NID_id_GostR3410_2012_256
|
||||
|| pktype == NID_id_GostR3410_2012_512)
|
||||
BUF_reverse(p + 2, NULL, u);
|
||||
}
|
||||
#endif
|
||||
|
||||
s2n(u, p);
|
||||
n += u + 2;
|
||||
/* Digest cached records and discard handshake buffer */
|
||||
if (!ssl3_digest_cached_records(s, 0))
|
||||
goto err;
|
||||
if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_VERIFY, n)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
EVP_MD_CTX_free(mctx);
|
||||
return 1;
|
||||
err:
|
||||
EVP_MD_CTX_free(mctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check a certificate can be used for client authentication. Currently check
|
||||
* cert exists, if we have a suitable digest for TLS 1.2 if static DH client
|
||||
@@ -2682,10 +3361,8 @@ int tls_construct_client_verify(SSL *s)
|
||||
*/
|
||||
static int ssl3_check_client_certificate(SSL *s)
|
||||
{
|
||||
if (!s->cert || !s->cert->key->x509 || !s->cert->key->privatekey)
|
||||
return 0;
|
||||
/* If no suitable signature algorithm can't use certificate */
|
||||
if (SSL_USE_SIGALGS(s) && !s->s3->tmp.md[s->cert->key - s->cert->pkeys])
|
||||
if (!tls_choose_sigalg(s, 0) || s->s3->tmp.sigalg == NULL)
|
||||
return 0;
|
||||
/*
|
||||
* If strict mode check suitability of chain before using it. This also
|
||||
@@ -2712,14 +3389,19 @@ WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst)
|
||||
return WORK_MORE_A;
|
||||
}
|
||||
if (i == 0) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
ossl_statem_set_error(s);
|
||||
return 0;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE,
|
||||
SSL_R_CALLBACK_FAILED);
|
||||
return WORK_ERROR;
|
||||
}
|
||||
s->rwstate = SSL_NOTHING;
|
||||
}
|
||||
if (ssl3_check_client_certificate(s))
|
||||
if (ssl3_check_client_certificate(s)) {
|
||||
if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
|
||||
return WORK_FINISHED_STOP;
|
||||
}
|
||||
return WORK_FINISHED_CONTINUE;
|
||||
}
|
||||
|
||||
/* Fall through to WORK_MORE_B */
|
||||
wst = WORK_MORE_B;
|
||||
@@ -2758,131 +3440,194 @@ WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst)
|
||||
} else {
|
||||
s->s3->tmp.cert_req = 2;
|
||||
if (!ssl3_digest_cached_records(s, 0)) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
ossl_statem_set_error(s);
|
||||
return 0;
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (s->post_handshake_auth == SSL_PHA_REQUESTED)
|
||||
return WORK_FINISHED_STOP;
|
||||
return WORK_FINISHED_CONTINUE;
|
||||
}
|
||||
|
||||
/* Shouldn't ever get here */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return WORK_ERROR;
|
||||
}
|
||||
|
||||
int tls_construct_client_certificate(SSL *s)
|
||||
int tls_construct_client_certificate(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
if (!ssl3_output_cert_chain(s,
|
||||
(s->s3->tmp.cert_req ==
|
||||
2) ? NULL : s->cert->key)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
ossl_statem_set_error(s);
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
if (s->pha_context == NULL) {
|
||||
/* no context available, add 0-length context */
|
||||
if (!WPACKET_put_bytes_u8(pkt, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
} else if (!WPACKET_sub_memcpy_u8(pkt, s->pha_context, s->pha_context_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!ssl3_output_cert_chain(s, pkt,
|
||||
(s->s3->tmp.cert_req == 2) ? NULL
|
||||
: s->cert->key)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SSL_IS_TLS13(s)
|
||||
&& SSL_IS_FIRST_HANDSHAKE(s)
|
||||
&& (!s->method->ssl3_enc->change_cipher_state(s,
|
||||
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {
|
||||
/*
|
||||
* This is a fatal error, which leaves enc_write_ctx in an inconsistent
|
||||
* state and thus ssl3_send_alert may crash.
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE,
|
||||
SSL_R_CANNOT_CHANGE_CIPHER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define has_bits(i,m) (((i)&(m)) == (m))
|
||||
|
||||
int ssl3_check_cert_and_algorithm(SSL *s)
|
||||
{
|
||||
int i;
|
||||
#ifndef OPENSSL_NO_EC
|
||||
int idx;
|
||||
#endif
|
||||
const SSL_CERT_LOOKUP *clu;
|
||||
size_t idx;
|
||||
long alg_k, alg_a;
|
||||
EVP_PKEY *pkey = NULL;
|
||||
int al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
|
||||
alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
|
||||
alg_a = s->s3->tmp.new_cipher->algorithm_auth;
|
||||
|
||||
/* we don't have a certificate */
|
||||
if ((alg_a & SSL_aNULL) || (alg_k & SSL_kPSK))
|
||||
return (1);
|
||||
if (!(alg_a & SSL_aCERT))
|
||||
return 1;
|
||||
|
||||
/* This is the passed certificate */
|
||||
clu = ssl_cert_lookup_by_pkey(X509_get0_pubkey(s->session->peer), &idx);
|
||||
|
||||
/* Check certificate is recognised and suitable for cipher */
|
||||
if (clu == NULL || (alg_a & clu->amask) == 0) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
|
||||
SSL_R_MISSING_SIGNING_CERT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
idx = s->session->peer_type;
|
||||
if (idx == SSL_PKEY_ECC) {
|
||||
if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s) == 0) {
|
||||
/* check failed */
|
||||
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_BAD_ECC_CERT);
|
||||
goto f_err;
|
||||
} else {
|
||||
if (clu->amask & SSL_aECDSA) {
|
||||
if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s))
|
||||
return 1;
|
||||
}
|
||||
} else if (alg_a & SSL_aECDSA) {
|
||||
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
|
||||
SSL_R_MISSING_ECDSA_SIGNING_CERT);
|
||||
goto f_err;
|
||||
}
|
||||
#endif
|
||||
pkey = X509_get0_pubkey(s->session->peer);
|
||||
i = X509_certificate_type(s->session->peer, pkey);
|
||||
|
||||
/* Check that we have a certificate if we require one */
|
||||
if ((alg_a & SSL_aRSA) && !has_bits(i, EVP_PK_RSA | EVP_PKT_SIGN)) {
|
||||
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
|
||||
SSL_R_MISSING_RSA_SIGNING_CERT);
|
||||
goto f_err;
|
||||
}
|
||||
#ifndef OPENSSL_NO_DSA
|
||||
else if ((alg_a & SSL_aDSS) && !has_bits(i, EVP_PK_DSA | EVP_PKT_SIGN)) {
|
||||
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
|
||||
SSL_R_MISSING_DSA_SIGNING_CERT);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_BAD_ECC_CERT);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
if (alg_k & (SSL_kRSA | SSL_kRSAPSK) &&
|
||||
!has_bits(i, EVP_PK_RSA | EVP_PKT_ENC)) {
|
||||
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
|
||||
SSL_R_MISSING_RSA_ENCRYPTING_CERT);
|
||||
goto f_err;
|
||||
if (alg_k & (SSL_kRSA | SSL_kRSAPSK) && idx != SSL_PKEY_RSA) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
|
||||
SSL_R_MISSING_RSA_ENCRYPTING_CERT);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DH
|
||||
if ((alg_k & SSL_kDHE) && (s->s3->peer_tmp == NULL)) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, ERR_R_INTERNAL_ERROR);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (1);
|
||||
f_err:
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
return (0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
int tls_construct_next_proto(SSL *s)
|
||||
int tls_construct_next_proto(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
unsigned int len, padding_len;
|
||||
unsigned char *d;
|
||||
size_t len, padding_len;
|
||||
unsigned char *padding = NULL;
|
||||
|
||||
len = s->next_proto_negotiated_len;
|
||||
len = s->ext.npn_len;
|
||||
padding_len = 32 - ((len + 2) % 32);
|
||||
d = (unsigned char *)s->init_buf->data;
|
||||
d[4] = len;
|
||||
memcpy(d + 5, s->next_proto_negotiated, len);
|
||||
d[5 + len] = padding_len;
|
||||
memset(d + 6 + len, 0, padding_len);
|
||||
*(d++) = SSL3_MT_NEXT_PROTO;
|
||||
l2n3(2 + len + padding_len, d);
|
||||
s->init_num = 4 + 2 + len + padding_len;
|
||||
s->init_off = 0;
|
||||
|
||||
if (!WPACKET_sub_memcpy_u8(pkt, s->ext.npn, len)
|
||||
|| !WPACKET_sub_allocate_bytes_u8(pkt, padding_len, &padding)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_NEXT_PROTO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(padding, 0, padding_len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_hello_req(SSL *s, PACKET *pkt)
|
||||
{
|
||||
if (PACKET_remaining(pkt) > 0) {
|
||||
/* should contain no data */
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_HELLO_REQ,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
|
||||
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
|
||||
return MSG_PROCESS_FINISHED_READING;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a historical discrepancy (not in the RFC) maintained for
|
||||
* compatibility reasons. If a TLS client receives a HelloRequest it will
|
||||
* attempt an abbreviated handshake. However if a DTLS client receives a
|
||||
* HelloRequest it will do a full handshake. Either behaviour is reasonable
|
||||
* but doing one for TLS and another for DTLS is odd.
|
||||
*/
|
||||
if (SSL_IS_DTLS(s))
|
||||
SSL_renegotiate(s);
|
||||
else
|
||||
SSL_renegotiate_abbreviated(s);
|
||||
|
||||
return MSG_PROCESS_FINISHED_READING;
|
||||
}
|
||||
|
||||
static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt)
|
||||
{
|
||||
PACKET extensions;
|
||||
RAW_EXTENSION *rawexts = NULL;
|
||||
|
||||
if (!PACKET_as_length_prefixed_2(pkt, &extensions)
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!tls_collect_extensions(s, &extensions,
|
||||
SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, &rawexts,
|
||||
NULL, 1)
|
||||
|| !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
|
||||
rawexts, NULL, 0, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
OPENSSL_free(rawexts);
|
||||
return MSG_PROCESS_CONTINUE_READING;
|
||||
|
||||
err:
|
||||
OPENSSL_free(rawexts);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
|
||||
{
|
||||
int i = 0;
|
||||
@@ -2900,47 +3645,123 @@ int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
|
||||
return i;
|
||||
}
|
||||
|
||||
int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, unsigned char *p)
|
||||
int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, WPACKET *pkt)
|
||||
{
|
||||
int i, j = 0;
|
||||
const SSL_CIPHER *c;
|
||||
unsigned char *q;
|
||||
int i;
|
||||
size_t totlen = 0, len, maxlen, maxverok = 0;
|
||||
int empty_reneg_info_scsv = !s->renegotiate;
|
||||
|
||||
/* Set disabled masks for this session */
|
||||
ssl_set_client_disabled(s);
|
||||
if (!ssl_set_client_disabled(s)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
|
||||
SSL_R_NO_PROTOCOLS_AVAILABLE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sk == NULL)
|
||||
return (0);
|
||||
q = p;
|
||||
if (sk == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH
|
||||
# if OPENSSL_MAX_TLS1_2_CIPHER_LENGTH < 6
|
||||
# error Max cipher length too short
|
||||
# endif
|
||||
/*
|
||||
* Some servers hang if client hello > 256 bytes as hack workaround
|
||||
* chop number of supported ciphers to keep it well below this if we
|
||||
* use TLS v1.2
|
||||
*/
|
||||
if (TLS1_get_version(s) >= TLS1_2_VERSION)
|
||||
maxlen = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1;
|
||||
else
|
||||
#endif
|
||||
/* Maximum length that can be stored in 2 bytes. Length must be even */
|
||||
maxlen = 0xfffe;
|
||||
|
||||
if (empty_reneg_info_scsv)
|
||||
maxlen -= 2;
|
||||
if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV)
|
||||
maxlen -= 2;
|
||||
|
||||
for (i = 0; i < sk_SSL_CIPHER_num(sk) && totlen < maxlen; i++) {
|
||||
const SSL_CIPHER *c;
|
||||
|
||||
for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
|
||||
c = sk_SSL_CIPHER_value(sk, i);
|
||||
/* Skip disabled ciphers */
|
||||
if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0))
|
||||
continue;
|
||||
j = s->method->put_cipher_by_char(c, p);
|
||||
p += j;
|
||||
|
||||
if (!s->method->put_cipher_by_char(c, pkt, &len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sanity check that the maximum version we offer has ciphers enabled */
|
||||
if (!maxverok) {
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
if (DTLS_VERSION_GE(c->max_dtls, s->s3->tmp.max_ver)
|
||||
&& DTLS_VERSION_LE(c->min_dtls, s->s3->tmp.max_ver))
|
||||
maxverok = 1;
|
||||
} else {
|
||||
if (c->max_tls >= s->s3->tmp.max_ver
|
||||
&& c->min_tls <= s->s3->tmp.max_ver)
|
||||
maxverok = 1;
|
||||
}
|
||||
}
|
||||
|
||||
totlen += len;
|
||||
}
|
||||
/*
|
||||
* If p == q, no ciphers; caller indicates an error. Otherwise, add
|
||||
* applicable SCSVs.
|
||||
*/
|
||||
if (p != q) {
|
||||
|
||||
if (totlen == 0 || !maxverok) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
|
||||
SSL_R_NO_CIPHERS_AVAILABLE);
|
||||
|
||||
if (!maxverok)
|
||||
ERR_add_error_data(1, "No ciphers enabled for max supported "
|
||||
"SSL/TLS version");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (totlen != 0) {
|
||||
if (empty_reneg_info_scsv) {
|
||||
static SSL_CIPHER scsv = {
|
||||
0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
0, NULL, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
j = s->method->put_cipher_by_char(&scsv, p);
|
||||
p += j;
|
||||
if (!s->method->put_cipher_by_char(&scsv, pkt, &len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV) {
|
||||
static SSL_CIPHER scsv = {
|
||||
0, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
0, NULL, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
j = s->method->put_cipher_by_char(&scsv, p);
|
||||
p += j;
|
||||
if (!s->method->put_cipher_by_char(&scsv, pkt, &len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (p - q);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_end_of_early_data(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
if (s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY
|
||||
&& s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA,
|
||||
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
|
||||
return 1;
|
||||
}
|
||||
+232
-191
@@ -12,6 +12,7 @@
|
||||
#include <stdio.h>
|
||||
#include "../ssl_locl.h"
|
||||
#include "statem_locl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/evp.h>
|
||||
@@ -32,7 +33,6 @@
|
||||
|
||||
#define RSMBLY_BITMASK_IS_COMPLETE(bitmask, msg_len, is_complete) { \
|
||||
long ii; \
|
||||
OPENSSL_assert((msg_len) > 0); \
|
||||
is_complete = 1; \
|
||||
if (bitmask[(((msg_len) - 1) >> 3)] != bitmask_end_values[((msg_len) & 7)]) is_complete = 0; \
|
||||
if (is_complete) for (ii = (((msg_len) - 1) >> 3) - 1; ii >= 0 ; ii--) \
|
||||
@@ -43,18 +43,17 @@ static unsigned char bitmask_start_values[] =
|
||||
static unsigned char bitmask_end_values[] =
|
||||
{ 0xff, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f };
|
||||
|
||||
static void dtls1_fix_message_header(SSL *s, unsigned long frag_off,
|
||||
unsigned long frag_len);
|
||||
static void dtls1_fix_message_header(SSL *s, size_t frag_off,
|
||||
size_t frag_len);
|
||||
static unsigned char *dtls1_write_message_header(SSL *s, unsigned char *p);
|
||||
static void dtls1_set_message_header_int(SSL *s, unsigned char mt,
|
||||
unsigned long len,
|
||||
size_t len,
|
||||
unsigned short seq_num,
|
||||
unsigned long frag_off,
|
||||
unsigned long frag_len);
|
||||
static int dtls_get_reassembled_message(SSL *s, long *len);
|
||||
size_t frag_off,
|
||||
size_t frag_len);
|
||||
static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len);
|
||||
|
||||
static hm_fragment *dtls1_hm_fragment_new(unsigned long frag_len,
|
||||
int reassembly)
|
||||
static hm_fragment *dtls1_hm_fragment_new(size_t frag_len, int reassembly)
|
||||
{
|
||||
hm_fragment *frag = NULL;
|
||||
unsigned char *buf = NULL;
|
||||
@@ -111,9 +110,10 @@ void dtls1_hm_fragment_free(hm_fragment *frag)
|
||||
int dtls1_do_write(SSL *s, int type)
|
||||
{
|
||||
int ret;
|
||||
unsigned int curr_mtu;
|
||||
size_t written;
|
||||
size_t curr_mtu;
|
||||
int retry = 1;
|
||||
unsigned int len, frag_off, mac_size, blocksize, used_len;
|
||||
size_t len, frag_off, mac_size, blocksize, used_len;
|
||||
|
||||
if (!dtls1_query_mtu(s))
|
||||
return -1;
|
||||
@@ -122,9 +122,11 @@ int dtls1_do_write(SSL *s, int type)
|
||||
/* should have something reasonable now */
|
||||
return -1;
|
||||
|
||||
if (s->init_off == 0 && type == SSL3_RT_HANDSHAKE)
|
||||
OPENSSL_assert(s->init_num ==
|
||||
(int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH);
|
||||
if (s->init_off == 0 && type == SSL3_RT_HANDSHAKE) {
|
||||
if (!ossl_assert(s->init_num ==
|
||||
s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (s->write_hash) {
|
||||
if (s->enc_write_ctx
|
||||
@@ -235,7 +237,8 @@ int dtls1_do_write(SSL *s, int type)
|
||||
data[s->init_off]);
|
||||
}
|
||||
|
||||
ret = dtls1_write_bytes(s, type, &s->init_buf->data[s->init_off], len);
|
||||
ret = dtls1_write_bytes(s, type, &s->init_buf->data[s->init_off], len,
|
||||
&written);
|
||||
if (ret < 0) {
|
||||
/*
|
||||
* might need to update MTU here, but we don't know which
|
||||
@@ -253,7 +256,7 @@ int dtls1_do_write(SSL *s, int type)
|
||||
} else
|
||||
return -1;
|
||||
} else {
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -261,7 +264,8 @@ int dtls1_do_write(SSL *s, int type)
|
||||
* bad if this assert fails, only part of the handshake message
|
||||
* got sent. but why would this happen?
|
||||
*/
|
||||
OPENSSL_assert(len == (unsigned int)ret);
|
||||
if (!ossl_assert(len == written))
|
||||
return -1;
|
||||
|
||||
if (type == SSL3_RT_HANDSHAKE && !s->d1->retransmitting) {
|
||||
/*
|
||||
@@ -271,7 +275,7 @@ int dtls1_do_write(SSL *s, int type)
|
||||
unsigned char *p =
|
||||
(unsigned char *)&s->init_buf->data[s->init_off];
|
||||
const struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
|
||||
int xlen;
|
||||
size_t xlen;
|
||||
|
||||
if (frag_off == 0 && s->version != DTLS1_BAD_VER) {
|
||||
/*
|
||||
@@ -284,17 +288,17 @@ int dtls1_do_write(SSL *s, int type)
|
||||
l2n3(0, p);
|
||||
l2n3(msg_hdr->msg_len, p);
|
||||
p -= DTLS1_HM_HEADER_LENGTH;
|
||||
xlen = ret;
|
||||
xlen = written;
|
||||
} else {
|
||||
p += DTLS1_HM_HEADER_LENGTH;
|
||||
xlen = ret - DTLS1_HM_HEADER_LENGTH;
|
||||
xlen = written - DTLS1_HM_HEADER_LENGTH;
|
||||
}
|
||||
|
||||
if (!ssl3_finish_mac(s, p, xlen))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret == s->init_num) {
|
||||
if (written == s->init_num) {
|
||||
if (s->msg_callback)
|
||||
s->msg_callback(1, s->version, type, s->init_buf->data,
|
||||
(size_t)(s->init_off + s->init_num), s,
|
||||
@@ -303,12 +307,12 @@ int dtls1_do_write(SSL *s, int type)
|
||||
s->init_off = 0; /* done writing this message */
|
||||
s->init_num = 0;
|
||||
|
||||
return (1);
|
||||
return 1;
|
||||
}
|
||||
s->init_off += ret;
|
||||
s->init_num -= ret;
|
||||
ret -= DTLS1_HM_HEADER_LENGTH;
|
||||
frag_off += ret;
|
||||
s->init_off += written;
|
||||
s->init_num -= written;
|
||||
written -= DTLS1_HM_HEADER_LENGTH;
|
||||
frag_off += written;
|
||||
|
||||
/*
|
||||
* We save the fragment offset for the next fragment so we have it
|
||||
@@ -319,32 +323,34 @@ int dtls1_do_write(SSL *s, int type)
|
||||
dtls1_fix_message_header(s, frag_off, 0);
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dtls_get_message(SSL *s, int *mt, unsigned long *len)
|
||||
int dtls_get_message(SSL *s, int *mt, size_t *len)
|
||||
{
|
||||
struct hm_header_st *msg_hdr;
|
||||
unsigned char *p;
|
||||
unsigned long msg_len;
|
||||
int ok;
|
||||
long tmplen;
|
||||
size_t msg_len;
|
||||
size_t tmplen;
|
||||
int errtype;
|
||||
|
||||
msg_hdr = &s->d1->r_msg_hdr;
|
||||
memset(msg_hdr, 0, sizeof(*msg_hdr));
|
||||
|
||||
again:
|
||||
ok = dtls_get_reassembled_message(s, &tmplen);
|
||||
if (tmplen == DTLS1_HM_BAD_FRAGMENT || tmplen == DTLS1_HM_FRAGMENT_RETRY) {
|
||||
/* bad fragment received */
|
||||
goto again;
|
||||
} else if (tmplen <= 0 && !ok) {
|
||||
if (!dtls_get_reassembled_message(s, &errtype, &tmplen)) {
|
||||
if (errtype == DTLS1_HM_BAD_FRAGMENT
|
||||
|| errtype == DTLS1_HM_FRAGMENT_RETRY) {
|
||||
/* bad fragment received */
|
||||
goto again;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
*mt = s->s3->tmp.message_type;
|
||||
|
||||
p = (unsigned char *)s->init_buf->data;
|
||||
*len = s->init_num;
|
||||
|
||||
if (*mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
|
||||
if (s->msg_callback) {
|
||||
@@ -354,7 +360,6 @@ int dtls_get_message(SSL *s, int *mt, unsigned long *len)
|
||||
/*
|
||||
* This isn't a real handshake message so skip the processing below.
|
||||
*/
|
||||
*len = (unsigned long)tmplen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -391,7 +396,6 @@ int dtls_get_message(SSL *s, int *mt, unsigned long *len)
|
||||
s->d1->handshake_read_seq++;
|
||||
|
||||
s->init_msg = s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
|
||||
*len = s->init_num;
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -401,11 +405,10 @@ int dtls_get_message(SSL *s, int *mt, unsigned long *len)
|
||||
* permitted in a DTLS handshake message for |s|. The minimum is 16KB, but
|
||||
* may be greater if the maximum certificate list size requires it.
|
||||
*/
|
||||
static unsigned long dtls1_max_handshake_message_len(const SSL *s)
|
||||
static size_t dtls1_max_handshake_message_len(const SSL *s)
|
||||
{
|
||||
unsigned long max_len =
|
||||
DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
|
||||
if (max_len < (unsigned long)s->max_cert_list)
|
||||
size_t max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
|
||||
if (max_len < s->max_cert_list)
|
||||
return s->max_cert_list;
|
||||
return max_len;
|
||||
}
|
||||
@@ -421,8 +424,9 @@ static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr)
|
||||
/* sanity checking */
|
||||
if ((frag_off + frag_len) > msg_len
|
||||
|| msg_len > dtls1_max_handshake_message_len(s)) {
|
||||
SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
||||
return SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_PREPROCESS_FRAGMENT,
|
||||
SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->d1->r_msg_hdr.frag_off == 0) { /* first fragment */
|
||||
@@ -431,8 +435,9 @@ static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr)
|
||||
* dtls_max_handshake_message_len(s) above
|
||||
*/
|
||||
if (!BUF_MEM_grow_clean(s->init_buf, msg_len + DTLS1_HM_HEADER_LENGTH)) {
|
||||
SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, ERR_R_BUF_LIB);
|
||||
return SSL_AD_INTERNAL_ERROR;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_PREPROCESS_FRAGMENT,
|
||||
ERR_R_BUF_LIB);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->s3->tmp.message_size = msg_len;
|
||||
@@ -445,14 +450,19 @@ static int dtls1_preprocess_fragment(SSL *s, struct hm_header_st *msg_hdr)
|
||||
* They must be playing with us! BTW, failure to enforce upper limit
|
||||
* would open possibility for buffer overrun.
|
||||
*/
|
||||
SSLerr(SSL_F_DTLS1_PREPROCESS_FRAGMENT, SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
||||
return SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS1_PREPROCESS_FRAGMENT,
|
||||
SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0; /* no error */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dtls1_retrieve_buffered_fragment(SSL *s, int *ok)
|
||||
/*
|
||||
* Returns 1 if there is a buffered fragment available, 0 if not, or -1 on a
|
||||
* fatal error.
|
||||
*/
|
||||
static int dtls1_retrieve_buffered_fragment(SSL *s, size_t *len)
|
||||
{
|
||||
/*-
|
||||
* (0) check whether the desired fragment is available
|
||||
@@ -462,9 +472,7 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, int *ok)
|
||||
*/
|
||||
pitem *item;
|
||||
hm_fragment *frag;
|
||||
int al;
|
||||
|
||||
*ok = 0;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
item = pqueue_peek(s->d1->buffered_messages);
|
||||
@@ -488,12 +496,13 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, int *ok)
|
||||
return 0;
|
||||
|
||||
if (s->d1->handshake_read_seq == frag->msg_header.seq) {
|
||||
unsigned long frag_len = frag->msg_header.frag_len;
|
||||
size_t frag_len = frag->msg_header.frag_len;
|
||||
pqueue_pop(s->d1->buffered_messages);
|
||||
|
||||
al = dtls1_preprocess_fragment(s, &frag->msg_header);
|
||||
/* Calls SSLfatal() as required */
|
||||
ret = dtls1_preprocess_fragment(s, &frag->msg_header);
|
||||
|
||||
if (al == 0) { /* no alert */
|
||||
if (ret) {
|
||||
unsigned char *p =
|
||||
(unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
|
||||
memcpy(&p[frag->msg_header.frag_off], frag->fragment,
|
||||
@@ -503,34 +512,36 @@ static int dtls1_retrieve_buffered_fragment(SSL *s, int *ok)
|
||||
dtls1_hm_fragment_free(frag);
|
||||
pitem_free(item);
|
||||
|
||||
if (al == 0) {
|
||||
*ok = 1;
|
||||
return frag_len;
|
||||
if (ret) {
|
||||
*len = frag_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
/* Fatal error */
|
||||
s->init_num = 0;
|
||||
*ok = 0;
|
||||
return -1;
|
||||
} else
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr, int *ok)
|
||||
dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr)
|
||||
{
|
||||
hm_fragment *frag = NULL;
|
||||
pitem *item = NULL;
|
||||
int i = -1, is_complete;
|
||||
unsigned char seq64be[8];
|
||||
unsigned long frag_len = msg_hdr->frag_len;
|
||||
size_t frag_len = msg_hdr->frag_len;
|
||||
size_t readbytes;
|
||||
|
||||
if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len ||
|
||||
msg_hdr->msg_len > dtls1_max_handshake_message_len(s))
|
||||
goto err;
|
||||
|
||||
if (frag_len == 0)
|
||||
if (frag_len == 0) {
|
||||
return DTLS1_HM_FRAGMENT_RETRY;
|
||||
}
|
||||
|
||||
/* Try to find item in queue */
|
||||
memset(seq64be, 0, sizeof(seq64be));
|
||||
@@ -567,10 +578,10 @@ dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr, int *ok)
|
||||
devnull,
|
||||
frag_len >
|
||||
sizeof(devnull) ? sizeof(devnull) :
|
||||
frag_len, 0);
|
||||
frag_len, 0, &readbytes);
|
||||
if (i <= 0)
|
||||
goto err;
|
||||
frag_len -= i;
|
||||
frag_len -= readbytes;
|
||||
}
|
||||
return DTLS1_HM_FRAGMENT_RETRY;
|
||||
}
|
||||
@@ -578,8 +589,8 @@ dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr, int *ok)
|
||||
/* read the body of the fragment (header has already been read */
|
||||
i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
|
||||
frag->fragment + msg_hdr->frag_off,
|
||||
frag_len, 0);
|
||||
if ((unsigned long)i != frag_len)
|
||||
frag_len, 0, &readbytes);
|
||||
if (i <= 0 || readbytes != frag_len)
|
||||
i = -1;
|
||||
if (i <= 0)
|
||||
goto err;
|
||||
@@ -587,6 +598,8 @@ dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr, int *ok)
|
||||
RSMBLY_BITMASK_MARK(frag->reassembly, (long)msg_hdr->frag_off,
|
||||
(long)(msg_hdr->frag_off + frag_len));
|
||||
|
||||
if (!ossl_assert(msg_hdr->msg_len > 0))
|
||||
goto err;
|
||||
RSMBLY_BITMASK_IS_COMPLETE(frag->reassembly, (long)msg_hdr->msg_len,
|
||||
is_complete);
|
||||
|
||||
@@ -609,7 +622,8 @@ dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr, int *ok)
|
||||
* would have returned it and control would never have reached this
|
||||
* branch.
|
||||
*/
|
||||
OPENSSL_assert(item != NULL);
|
||||
if (!ossl_assert(item != NULL))
|
||||
goto err;
|
||||
}
|
||||
|
||||
return DTLS1_HM_FRAGMENT_RETRY;
|
||||
@@ -617,19 +631,18 @@ dtls1_reassemble_fragment(SSL *s, const struct hm_header_st *msg_hdr, int *ok)
|
||||
err:
|
||||
if (item == NULL)
|
||||
dtls1_hm_fragment_free(frag);
|
||||
*ok = 0;
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st *msg_hdr,
|
||||
int *ok)
|
||||
dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st *msg_hdr)
|
||||
{
|
||||
int i = -1;
|
||||
hm_fragment *frag = NULL;
|
||||
pitem *item = NULL;
|
||||
unsigned char seq64be[8];
|
||||
unsigned long frag_len = msg_hdr->frag_len;
|
||||
size_t frag_len = msg_hdr->frag_len;
|
||||
size_t readbytes;
|
||||
|
||||
if ((msg_hdr->frag_off + frag_len) > msg_hdr->msg_len)
|
||||
goto err;
|
||||
@@ -662,14 +675,15 @@ dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st *msg_hdr,
|
||||
devnull,
|
||||
frag_len >
|
||||
sizeof(devnull) ? sizeof(devnull) :
|
||||
frag_len, 0);
|
||||
frag_len, 0, &readbytes);
|
||||
if (i <= 0)
|
||||
goto err;
|
||||
frag_len -= i;
|
||||
frag_len -= readbytes;
|
||||
}
|
||||
} else {
|
||||
if (frag_len != msg_hdr->msg_len)
|
||||
return dtls1_reassemble_fragment(s, msg_hdr, ok);
|
||||
if (frag_len != msg_hdr->msg_len) {
|
||||
return dtls1_reassemble_fragment(s, msg_hdr);
|
||||
}
|
||||
|
||||
if (frag_len > dtls1_max_handshake_message_len(s))
|
||||
goto err;
|
||||
@@ -685,8 +699,9 @@ dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st *msg_hdr,
|
||||
* read the body of the fragment (header has already been read
|
||||
*/
|
||||
i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
|
||||
frag->fragment, frag_len, 0);
|
||||
if ((unsigned long)i != frag_len)
|
||||
frag->fragment, frag_len, 0,
|
||||
&readbytes);
|
||||
if (i<=0 || readbytes != frag_len)
|
||||
i = -1;
|
||||
if (i <= 0)
|
||||
goto err;
|
||||
@@ -705,7 +720,8 @@ dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st *msg_hdr,
|
||||
* have been processed with |dtls1_reassemble_fragment|, above, or
|
||||
* the record will have been discarded.
|
||||
*/
|
||||
OPENSSL_assert(item != NULL);
|
||||
if (!ossl_assert(item != NULL))
|
||||
goto err;
|
||||
}
|
||||
|
||||
return DTLS1_HM_FRAGMENT_RETRY;
|
||||
@@ -713,56 +729,61 @@ dtls1_process_out_of_seq_message(SSL *s, const struct hm_header_st *msg_hdr,
|
||||
err:
|
||||
if (item == NULL)
|
||||
dtls1_hm_fragment_free(frag);
|
||||
*ok = 0;
|
||||
return i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dtls_get_reassembled_message(SSL *s, long *len)
|
||||
static int dtls_get_reassembled_message(SSL *s, int *errtype, size_t *len)
|
||||
{
|
||||
unsigned char wire[DTLS1_HM_HEADER_LENGTH];
|
||||
unsigned long mlen, frag_off, frag_len;
|
||||
int i, al, recvd_type;
|
||||
size_t mlen, frag_off, frag_len;
|
||||
int i, ret, recvd_type;
|
||||
struct hm_header_st msg_hdr;
|
||||
int ok;
|
||||
size_t readbytes;
|
||||
|
||||
*errtype = 0;
|
||||
|
||||
redo:
|
||||
/* see if we have the required fragment already */
|
||||
if ((frag_len = dtls1_retrieve_buffered_fragment(s, &ok)) || ok) {
|
||||
if (ok)
|
||||
s->init_num = frag_len;
|
||||
ret = dtls1_retrieve_buffered_fragment(s, &frag_len);
|
||||
if (ret < 0) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
if (ret > 0) {
|
||||
s->init_num = frag_len;
|
||||
*len = frag_len;
|
||||
return ok;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* read handshake message header */
|
||||
i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type, wire,
|
||||
DTLS1_HM_HEADER_LENGTH, 0);
|
||||
DTLS1_HM_HEADER_LENGTH, 0, &readbytes);
|
||||
if (i <= 0) { /* nbio, or an error */
|
||||
s->rwstate = SSL_READING;
|
||||
*len = i;
|
||||
*len = 0;
|
||||
return 0;
|
||||
}
|
||||
if (recvd_type == SSL3_RT_CHANGE_CIPHER_SPEC) {
|
||||
if (wire[0] != SSL3_MT_CCS) {
|
||||
al = SSL_AD_UNEXPECTED_MESSAGE;
|
||||
SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
|
||||
SSL_R_BAD_CHANGE_CIPHER_SPEC);
|
||||
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
|
||||
SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
|
||||
SSL_R_BAD_CHANGE_CIPHER_SPEC);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
memcpy(s->init_buf->data, wire, i);
|
||||
s->init_num = i - 1;
|
||||
memcpy(s->init_buf->data, wire, readbytes);
|
||||
s->init_num = readbytes - 1;
|
||||
s->init_msg = s->init_buf->data + 1;
|
||||
s->s3->tmp.message_type = SSL3_MT_CHANGE_CIPHER_SPEC;
|
||||
s->s3->tmp.message_size = i - 1;
|
||||
*len = i - 1;
|
||||
s->s3->tmp.message_size = readbytes - 1;
|
||||
*len = readbytes - 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Handshake fails if message header is incomplete */
|
||||
if (i != DTLS1_HM_HEADER_LENGTH) {
|
||||
al = SSL_AD_UNEXPECTED_MESSAGE;
|
||||
SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
|
||||
if (readbytes != DTLS1_HM_HEADER_LENGTH) {
|
||||
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
|
||||
SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_UNEXPECTED_MESSAGE);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
@@ -778,8 +799,8 @@ static int dtls_get_reassembled_message(SSL *s, long *len)
|
||||
* Fragments must not span records.
|
||||
*/
|
||||
if (frag_len > RECORD_LAYER_get_rrec_length(&s->rlayer)) {
|
||||
al = SSL3_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
@@ -790,17 +811,19 @@ static int dtls_get_reassembled_message(SSL *s, long *len)
|
||||
* although we're still expecting seq 0 (ClientHello)
|
||||
*/
|
||||
if (msg_hdr.seq != s->d1->handshake_read_seq) {
|
||||
*len = dtls1_process_out_of_seq_message(s, &msg_hdr, &ok);
|
||||
return ok;
|
||||
*errtype = dtls1_process_out_of_seq_message(s, &msg_hdr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (frag_len && frag_len < mlen) {
|
||||
*len = dtls1_reassemble_fragment(s, &msg_hdr, &ok);
|
||||
return ok;
|
||||
*errtype = dtls1_reassemble_fragment(s, &msg_hdr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s->server && s->d1->r_msg_hdr.frag_off == 0 &&
|
||||
wire[0] == SSL3_MT_HELLO_REQUEST) {
|
||||
if (!s->server
|
||||
&& s->d1->r_msg_hdr.frag_off == 0
|
||||
&& s->statem.hand_state != TLS_ST_OK
|
||||
&& wire[0] == SSL3_MT_HELLO_REQUEST) {
|
||||
/*
|
||||
* The server may always send 'Hello Request' messages -- we are
|
||||
* doing a handshake anyway now, so ignore them if their format is
|
||||
@@ -816,22 +839,24 @@ static int dtls_get_reassembled_message(SSL *s, long *len)
|
||||
goto redo;
|
||||
} else { /* Incorrectly formatted Hello request */
|
||||
|
||||
al = SSL_AD_UNEXPECTED_MESSAGE;
|
||||
SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
|
||||
SSL_R_UNEXPECTED_MESSAGE);
|
||||
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
|
||||
SSL_F_DTLS_GET_REASSEMBLED_MESSAGE,
|
||||
SSL_R_UNEXPECTED_MESSAGE);
|
||||
goto f_err;
|
||||
}
|
||||
}
|
||||
|
||||
if ((al = dtls1_preprocess_fragment(s, &msg_hdr)))
|
||||
if (!dtls1_preprocess_fragment(s, &msg_hdr)) {
|
||||
/* SSLfatal() already called */
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
if (frag_len > 0) {
|
||||
unsigned char *p =
|
||||
(unsigned char *)s->init_buf->data + DTLS1_HM_HEADER_LENGTH;
|
||||
|
||||
i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
|
||||
&p[frag_off], frag_len, 0);
|
||||
&p[frag_off], frag_len, 0, &readbytes);
|
||||
|
||||
/*
|
||||
* This shouldn't ever fail due to NBIO because we already checked
|
||||
@@ -839,19 +864,20 @@ static int dtls_get_reassembled_message(SSL *s, long *len)
|
||||
*/
|
||||
if (i <= 0) {
|
||||
s->rwstate = SSL_READING;
|
||||
*len = i;
|
||||
*len = 0;
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
i = 0;
|
||||
} else {
|
||||
readbytes = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* XDTLS: an incorrectly formatted fragment should cause the handshake
|
||||
* to fail
|
||||
*/
|
||||
if (i != (int)frag_len) {
|
||||
al = SSL3_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL3_AD_ILLEGAL_PARAMETER);
|
||||
if (readbytes != frag_len) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_DTLS_GET_REASSEMBLED_MESSAGE, SSL_R_BAD_LENGTH);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
@@ -865,9 +891,8 @@ static int dtls_get_reassembled_message(SSL *s, long *len)
|
||||
return 1;
|
||||
|
||||
f_err:
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
s->init_num = 0;
|
||||
*len = -1;
|
||||
*len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -880,65 +905,36 @@ static int dtls_get_reassembled_message(SSL *s, long *len)
|
||||
* ssl->session->read_compression assign
|
||||
* ssl->session->read_hash assign
|
||||
*/
|
||||
int dtls_construct_change_cipher_spec(SSL *s)
|
||||
int dtls_construct_change_cipher_spec(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
p = (unsigned char *)s->init_buf->data;
|
||||
*p++ = SSL3_MT_CCS;
|
||||
s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
|
||||
s->init_num = DTLS1_CCS_HEADER_LENGTH;
|
||||
|
||||
if (s->version == DTLS1_BAD_VER) {
|
||||
s->d1->next_handshake_write_seq++;
|
||||
s2n(s->d1->handshake_write_seq, p);
|
||||
s->init_num += 2;
|
||||
}
|
||||
|
||||
s->init_off = 0;
|
||||
|
||||
dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
|
||||
s->d1->handshake_write_seq, 0, 0);
|
||||
|
||||
/* buffer the message to handle re-xmits */
|
||||
if (!dtls1_buffer_message(s, 1)) {
|
||||
SSLerr(SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
if (!WPACKET_put_bytes_u16(pkt, s->d1->handshake_write_seq)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_DTLS_CONSTRUCT_CHANGE_CIPHER_SPEC,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
/*
|
||||
* Wait for a dry event. Should only be called at a point in the handshake
|
||||
* where we are not expecting any data from the peer (except possibly an alert).
|
||||
*/
|
||||
WORK_STATE dtls_wait_for_dry(SSL *s)
|
||||
{
|
||||
int ret;
|
||||
long len;
|
||||
|
||||
/* read app data until dry event */
|
||||
ret = BIO_dgram_sctp_wait_for_dry(SSL_get_wbio(s));
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS_WAIT_FOR_DRY,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return WORK_ERROR;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
/*
|
||||
* We're not expecting any more messages from the peer at this point -
|
||||
* but we could get an alert. If an alert is waiting then we will never
|
||||
* return successfully. Therefore we attempt to read a message. This
|
||||
* should never succeed but will process any waiting alerts.
|
||||
*/
|
||||
if (dtls_get_reassembled_message(s, &len)) {
|
||||
/* The call succeeded! This should never happen */
|
||||
SSLerr(SSL_F_DTLS_WAIT_FOR_DRY, SSL_R_UNEXPECTED_MESSAGE);
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
|
||||
ossl_statem_set_error(s);
|
||||
return WORK_ERROR;
|
||||
}
|
||||
|
||||
s->s3->in_read_app_data = 2;
|
||||
s->rwstate = SSL_READING;
|
||||
BIO_clear_retry_flags(SSL_get_rbio(s));
|
||||
@@ -952,24 +948,20 @@ WORK_STATE dtls_wait_for_dry(SSL *s)
|
||||
int dtls1_read_failed(SSL *s, int code)
|
||||
{
|
||||
if (code > 0) {
|
||||
SSLerr(SSL_F_DTLS1_READ_FAILED, ERR_R_INTERNAL_ERROR);
|
||||
return 1;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_DTLS1_READ_FAILED, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dtls1_is_timer_expired(s)) {
|
||||
if (!dtls1_is_timer_expired(s) || ossl_statem_in_error(s)) {
|
||||
/*
|
||||
* not a timeout, none of our business, let higher layers handle
|
||||
* this. in fact it's probably an error
|
||||
*/
|
||||
return code;
|
||||
}
|
||||
#ifndef OPENSSL_NO_HEARTBEATS
|
||||
/* done, no need to send a retransmit */
|
||||
if (!SSL_in_init(s) && !s->tlsext_hb_pending)
|
||||
#else
|
||||
/* done, no need to send a retransmit */
|
||||
if (!SSL_in_init(s))
|
||||
#endif
|
||||
{
|
||||
BIO_set_flags(SSL_get_rbio(s), BIO_FLAGS_READ);
|
||||
return code;
|
||||
@@ -1025,7 +1017,8 @@ int dtls1_buffer_message(SSL *s, int is_ccs)
|
||||
* this function is called immediately after a message has been
|
||||
* serialized
|
||||
*/
|
||||
OPENSSL_assert(s->init_off == 0);
|
||||
if (!ossl_assert(s->init_off == 0))
|
||||
return 0;
|
||||
|
||||
frag = dtls1_hm_fragment_new(s->init_num, 0);
|
||||
if (frag == NULL)
|
||||
@@ -1035,13 +1028,15 @@ int dtls1_buffer_message(SSL *s, int is_ccs)
|
||||
|
||||
if (is_ccs) {
|
||||
/* For DTLS1_BAD_VER the header length is non-standard */
|
||||
OPENSSL_assert(s->d1->w_msg_hdr.msg_len +
|
||||
((s->version ==
|
||||
DTLS1_BAD_VER) ? 3 : DTLS1_CCS_HEADER_LENGTH)
|
||||
== (unsigned int)s->init_num);
|
||||
if (!ossl_assert(s->d1->w_msg_hdr.msg_len +
|
||||
((s->version ==
|
||||
DTLS1_BAD_VER) ? 3 : DTLS1_CCS_HEADER_LENGTH)
|
||||
== (unsigned int)s->init_num))
|
||||
return 0;
|
||||
} else {
|
||||
OPENSSL_assert(s->d1->w_msg_hdr.msg_len +
|
||||
DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num);
|
||||
if (!ossl_assert(s->d1->w_msg_hdr.msg_len +
|
||||
DTLS1_HM_HEADER_LENGTH == (unsigned int)s->init_num))
|
||||
return 0;
|
||||
}
|
||||
|
||||
frag->msg_header.msg_len = s->d1->w_msg_hdr.msg_len;
|
||||
@@ -1089,11 +1084,6 @@ int dtls1_retransmit_message(SSL *s, unsigned short seq, int *found)
|
||||
unsigned char seq64be[8];
|
||||
struct dtls1_retransmit_state saved_state;
|
||||
|
||||
/*-
|
||||
OPENSSL_assert(s->init_num == 0);
|
||||
OPENSSL_assert(s->init_off == 0);
|
||||
*/
|
||||
|
||||
/* XDTLS: the requested message ought to be found, otherwise error */
|
||||
memset(seq64be, 0, sizeof(seq64be));
|
||||
seq64be[6] = (unsigned char)(seq >> 8);
|
||||
@@ -1101,7 +1091,8 @@ int dtls1_retransmit_message(SSL *s, unsigned short seq, int *found)
|
||||
|
||||
item = pqueue_find(s->d1->sent_messages, seq64be);
|
||||
if (item == NULL) {
|
||||
SSLerr(SSL_F_DTLS1_RETRANSMIT_MESSAGE, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_DTLS1_RETRANSMIT_MESSAGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
*found = 0;
|
||||
return 0;
|
||||
}
|
||||
@@ -1158,8 +1149,8 @@ int dtls1_retransmit_message(SSL *s, unsigned short seq, int *found)
|
||||
}
|
||||
|
||||
void dtls1_set_message_header(SSL *s,
|
||||
unsigned char mt, unsigned long len,
|
||||
unsigned long frag_off, unsigned long frag_len)
|
||||
unsigned char mt, size_t len,
|
||||
size_t frag_off, size_t frag_len)
|
||||
{
|
||||
if (frag_off == 0) {
|
||||
s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
|
||||
@@ -1173,8 +1164,8 @@ void dtls1_set_message_header(SSL *s,
|
||||
/* don't actually do the writing, wait till the MTU has been retrieved */
|
||||
static void
|
||||
dtls1_set_message_header_int(SSL *s, unsigned char mt,
|
||||
unsigned long len, unsigned short seq_num,
|
||||
unsigned long frag_off, unsigned long frag_len)
|
||||
size_t len, unsigned short seq_num,
|
||||
size_t frag_off, size_t frag_len)
|
||||
{
|
||||
struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
|
||||
|
||||
@@ -1186,7 +1177,7 @@ dtls1_set_message_header_int(SSL *s, unsigned char mt,
|
||||
}
|
||||
|
||||
static void
|
||||
dtls1_fix_message_header(SSL *s, unsigned long frag_off, unsigned long frag_len)
|
||||
dtls1_fix_message_header(SSL *s, size_t frag_off, size_t frag_len)
|
||||
{
|
||||
struct hm_header_st *msg_hdr = &s->d1->w_msg_hdr;
|
||||
|
||||
@@ -1218,3 +1209,53 @@ void dtls1_get_message_header(unsigned char *data, struct hm_header_st *msg_hdr)
|
||||
n2l3(data, msg_hdr->frag_off);
|
||||
n2l3(data, msg_hdr->frag_len);
|
||||
}
|
||||
|
||||
int dtls1_set_handshake_header(SSL *s, WPACKET *pkt, int htype)
|
||||
{
|
||||
unsigned char *header;
|
||||
|
||||
if (htype == SSL3_MT_CHANGE_CIPHER_SPEC) {
|
||||
s->d1->handshake_write_seq = s->d1->next_handshake_write_seq;
|
||||
dtls1_set_message_header_int(s, SSL3_MT_CCS, 0,
|
||||
s->d1->handshake_write_seq, 0, 0);
|
||||
if (!WPACKET_put_bytes_u8(pkt, SSL3_MT_CCS))
|
||||
return 0;
|
||||
} else {
|
||||
dtls1_set_message_header(s, htype, 0, 0, 0);
|
||||
/*
|
||||
* We allocate space at the start for the message header. This gets
|
||||
* filled in later
|
||||
*/
|
||||
if (!WPACKET_allocate_bytes(pkt, DTLS1_HM_HEADER_LENGTH, &header)
|
||||
|| !WPACKET_start_sub_packet(pkt))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int dtls1_close_construct_packet(SSL *s, WPACKET *pkt, int htype)
|
||||
{
|
||||
size_t msglen;
|
||||
|
||||
if ((htype != SSL3_MT_CHANGE_CIPHER_SPEC && !WPACKET_close(pkt))
|
||||
|| !WPACKET_get_length(pkt, &msglen)
|
||||
|| msglen > INT_MAX)
|
||||
return 0;
|
||||
|
||||
if (htype != SSL3_MT_CHANGE_CIPHER_SPEC) {
|
||||
s->d1->w_msg_hdr.msg_len = msglen - DTLS1_HM_HEADER_LENGTH;
|
||||
s->d1->w_msg_hdr.frag_len = msglen - DTLS1_HM_HEADER_LENGTH;
|
||||
}
|
||||
s->init_num = (int)msglen;
|
||||
s->init_off = 0;
|
||||
|
||||
if (htype != DTLS1_MT_HELLO_VERIFY_REQUEST) {
|
||||
/* Buffer the message to handle re-xmits */
|
||||
if (!dtls1_buffer_message(s, htype == SSL3_MT_CHANGE_CIPHER_SPEC
|
||||
? 1 : 0))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
+1431
-233
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -7,22 +8,24 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
* ECC cipher suite support in OpenSSL originally developed by
|
||||
* SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "../ssl_locl.h"
|
||||
#include "statem_locl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
/* Fixed value used in the ServerHello random field to identify an HRR */
|
||||
const unsigned char hrrrandom[] = {
|
||||
0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02,
|
||||
0x1e, 0x65, 0xb8, 0x91, 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e,
|
||||
0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c
|
||||
};
|
||||
|
||||
/*
|
||||
* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or
|
||||
* SSL3_RT_CHANGE_CIPHER_SPEC)
|
||||
@@ -30,71 +33,619 @@
|
||||
int ssl3_do_write(SSL *s, int type)
|
||||
{
|
||||
int ret;
|
||||
size_t written = 0;
|
||||
|
||||
ret = ssl3_write_bytes(s, type, &s->init_buf->data[s->init_off],
|
||||
s->init_num);
|
||||
s->init_num, &written);
|
||||
if (ret < 0)
|
||||
return (-1);
|
||||
return -1;
|
||||
if (type == SSL3_RT_HANDSHAKE)
|
||||
/*
|
||||
* should not be done for 'Hello Request's, but in that case we'll
|
||||
* ignore the result anyway
|
||||
* TLS1.3 KeyUpdate and NewSessionTicket do not need to be added
|
||||
*/
|
||||
if (!ssl3_finish_mac(s,
|
||||
(unsigned char *)&s->init_buf->data[s->init_off],
|
||||
ret))
|
||||
return -1;
|
||||
|
||||
if (ret == s->init_num) {
|
||||
if (!SSL_IS_TLS13(s) || (s->statem.hand_state != TLS_ST_SW_SESSION_TICKET
|
||||
&& s->statem.hand_state != TLS_ST_CW_KEY_UPDATE
|
||||
&& s->statem.hand_state != TLS_ST_SW_KEY_UPDATE))
|
||||
if (!ssl3_finish_mac(s,
|
||||
(unsigned char *)&s->init_buf->data[s->init_off],
|
||||
written))
|
||||
return -1;
|
||||
if (written == s->init_num) {
|
||||
if (s->msg_callback)
|
||||
s->msg_callback(1, s->version, type, s->init_buf->data,
|
||||
(size_t)(s->init_off + s->init_num), s,
|
||||
s->msg_callback_arg);
|
||||
return (1);
|
||||
return 1;
|
||||
}
|
||||
s->init_off += ret;
|
||||
s->init_num -= ret;
|
||||
return (0);
|
||||
s->init_off += written;
|
||||
s->init_num -= written;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tls_construct_finished(SSL *s, const char *sender, int slen)
|
||||
int tls_close_construct_packet(SSL *s, WPACKET *pkt, int htype)
|
||||
{
|
||||
unsigned char *p;
|
||||
int i;
|
||||
unsigned long l;
|
||||
size_t msglen;
|
||||
|
||||
p = ssl_handshake_start(s);
|
||||
|
||||
i = s->method->ssl3_enc->final_finish_mac(s,
|
||||
sender, slen,
|
||||
s->s3->tmp.finish_md);
|
||||
if (i <= 0)
|
||||
if ((htype != SSL3_MT_CHANGE_CIPHER_SPEC && !WPACKET_close(pkt))
|
||||
|| !WPACKET_get_length(pkt, &msglen)
|
||||
|| msglen > INT_MAX)
|
||||
return 0;
|
||||
s->s3->tmp.finish_md_len = i;
|
||||
memcpy(p, s->s3->tmp.finish_md, i);
|
||||
l = i;
|
||||
s->init_num = (int)msglen;
|
||||
s->init_off = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_setup_handshake(SSL *s)
|
||||
{
|
||||
if (!ssl3_init_finished_mac(s)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Reset any extension flags */
|
||||
memset(s->ext.extflags, 0, sizeof(s->ext.extflags));
|
||||
|
||||
if (s->server) {
|
||||
STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(s);
|
||||
int i, ver_min, ver_max, ok = 0;
|
||||
|
||||
/*
|
||||
* Sanity check that the maximum version we accept has ciphers
|
||||
* enabled. For clients we do this check during construction of the
|
||||
* ClientHello.
|
||||
*/
|
||||
if (ssl_get_min_max_version(s, &ver_min, &ver_max) != 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_SETUP_HANDSHAKE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
|
||||
const SSL_CIPHER *c = sk_SSL_CIPHER_value(ciphers, i);
|
||||
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
if (DTLS_VERSION_GE(ver_max, c->min_dtls) &&
|
||||
DTLS_VERSION_LE(ver_max, c->max_dtls))
|
||||
ok = 1;
|
||||
} else if (ver_max >= c->min_tls && ver_max <= c->max_tls) {
|
||||
ok = 1;
|
||||
}
|
||||
if (ok)
|
||||
break;
|
||||
}
|
||||
if (!ok) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_SETUP_HANDSHAKE,
|
||||
SSL_R_NO_CIPHERS_AVAILABLE);
|
||||
ERR_add_error_data(1, "No ciphers enabled for max supported "
|
||||
"SSL/TLS version");
|
||||
return 0;
|
||||
}
|
||||
if (SSL_IS_FIRST_HANDSHAKE(s)) {
|
||||
/* N.B. s->session_ctx == s->ctx here */
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_accept, 1, &i,
|
||||
s->session_ctx->lock);
|
||||
} else {
|
||||
/* N.B. s->ctx may not equal s->session_ctx */
|
||||
CRYPTO_atomic_add(&s->ctx->stats.sess_accept_renegotiate, 1, &i,
|
||||
s->ctx->lock);
|
||||
|
||||
s->s3->tmp.cert_request = 0;
|
||||
}
|
||||
} else {
|
||||
int discard;
|
||||
if (SSL_IS_FIRST_HANDSHAKE(s))
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_connect, 1, &discard,
|
||||
s->session_ctx->lock);
|
||||
else
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_connect_renegotiate,
|
||||
1, &discard, s->session_ctx->lock);
|
||||
|
||||
/* mark client_random uninitialized */
|
||||
memset(s->s3->client_random, 0, sizeof(s->s3->client_random));
|
||||
s->hit = 0;
|
||||
|
||||
s->s3->tmp.cert_req = 0;
|
||||
|
||||
if (SSL_IS_DTLS(s))
|
||||
s->statem.use_timer = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Size of the to-be-signed TLS13 data, without the hash size itself:
|
||||
* 64 bytes of value 32, 33 context bytes, 1 byte separator
|
||||
*/
|
||||
#define TLS13_TBS_START_SIZE 64
|
||||
#define TLS13_TBS_PREAMBLE_SIZE (TLS13_TBS_START_SIZE + 33 + 1)
|
||||
|
||||
static int get_cert_verify_tbs_data(SSL *s, unsigned char *tls13tbs,
|
||||
void **hdata, size_t *hdatalen)
|
||||
{
|
||||
static const char *servercontext = "TLS 1.3, server CertificateVerify";
|
||||
static const char *clientcontext = "TLS 1.3, client CertificateVerify";
|
||||
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
size_t hashlen;
|
||||
|
||||
/* Set the first 64 bytes of to-be-signed data to octet 32 */
|
||||
memset(tls13tbs, 32, TLS13_TBS_START_SIZE);
|
||||
/* This copies the 33 bytes of context plus the 0 separator byte */
|
||||
if (s->statem.hand_state == TLS_ST_CR_CERT_VRFY
|
||||
|| s->statem.hand_state == TLS_ST_SW_CERT_VRFY)
|
||||
strcpy((char *)tls13tbs + TLS13_TBS_START_SIZE, servercontext);
|
||||
else
|
||||
strcpy((char *)tls13tbs + TLS13_TBS_START_SIZE, clientcontext);
|
||||
|
||||
/*
|
||||
* If we're currently reading then we need to use the saved handshake
|
||||
* hash value. We can't use the current handshake hash state because
|
||||
* that includes the CertVerify itself.
|
||||
*/
|
||||
if (s->statem.hand_state == TLS_ST_CR_CERT_VRFY
|
||||
|| s->statem.hand_state == TLS_ST_SR_CERT_VRFY) {
|
||||
memcpy(tls13tbs + TLS13_TBS_PREAMBLE_SIZE, s->cert_verify_hash,
|
||||
s->cert_verify_hash_len);
|
||||
hashlen = s->cert_verify_hash_len;
|
||||
} else if (!ssl_handshake_hash(s, tls13tbs + TLS13_TBS_PREAMBLE_SIZE,
|
||||
EVP_MAX_MD_SIZE, &hashlen)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
*hdata = tls13tbs;
|
||||
*hdatalen = TLS13_TBS_PREAMBLE_SIZE + hashlen;
|
||||
} else {
|
||||
size_t retlen;
|
||||
|
||||
retlen = BIO_get_mem_data(s->s3->handshake_buffer, hdata);
|
||||
if (retlen <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_GET_CERT_VERIFY_TBS_DATA,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
*hdatalen = retlen;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
EVP_PKEY *pkey = NULL;
|
||||
const EVP_MD *md = NULL;
|
||||
EVP_MD_CTX *mctx = NULL;
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
size_t hdatalen = 0, siglen = 0;
|
||||
void *hdata;
|
||||
unsigned char *sig = NULL;
|
||||
unsigned char tls13tbs[TLS13_TBS_PREAMBLE_SIZE + EVP_MAX_MD_SIZE];
|
||||
const SIGALG_LOOKUP *lu = s->s3->tmp.sigalg;
|
||||
|
||||
if (lu == NULL || s->s3->tmp.cert == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
pkey = s->s3->tmp.cert->privatekey;
|
||||
|
||||
if (pkey == NULL || !tls1_lookup_md(lu, &md)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
mctx = EVP_MD_CTX_new();
|
||||
if (mctx == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Get the data to be signed */
|
||||
if (!get_cert_verify_tbs_data(s, tls13tbs, &hdata, &hdatalen)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
siglen = EVP_PKEY_size(pkey);
|
||||
sig = OPENSSL_malloc(siglen);
|
||||
if (sig == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_DigestSignInit(mctx, &pctx, md, NULL, pkey) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
|
||||
ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (lu->sig == EVP_PKEY_RSA_PSS) {
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
|
||||
|| EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
|
||||
RSA_PSS_SALTLEN_DIGEST) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
|
||||
ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (s->version == SSL3_VERSION) {
|
||||
if (EVP_DigestSignUpdate(mctx, hdata, hdatalen) <= 0
|
||||
|| !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
|
||||
(int)s->session->master_key_length,
|
||||
s->session->master_key)
|
||||
|| EVP_DigestSignFinal(mctx, sig, &siglen) <= 0) {
|
||||
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
|
||||
ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
} else if (EVP_DigestSign(mctx, sig, &siglen, hdata, hdatalen) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
|
||||
ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
{
|
||||
int pktype = lu->sig;
|
||||
|
||||
if (pktype == NID_id_GostR3410_2001
|
||||
|| pktype == NID_id_GostR3410_2012_256
|
||||
|| pktype == NID_id_GostR3410_2012_512)
|
||||
BUF_reverse(sig, NULL, siglen);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!WPACKET_sub_memcpy_u16(pkt, sig, siglen)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_VERIFY,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Digest cached records and discard handshake buffer */
|
||||
if (!ssl3_digest_cached_records(s, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
OPENSSL_free(sig);
|
||||
EVP_MD_CTX_free(mctx);
|
||||
return 1;
|
||||
err:
|
||||
OPENSSL_free(sig);
|
||||
EVP_MD_CTX_free(mctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
|
||||
{
|
||||
EVP_PKEY *pkey = NULL;
|
||||
const unsigned char *data;
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
unsigned char *gost_data = NULL;
|
||||
#endif
|
||||
MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
|
||||
int j;
|
||||
unsigned int len;
|
||||
X509 *peer;
|
||||
const EVP_MD *md = NULL;
|
||||
size_t hdatalen = 0;
|
||||
void *hdata;
|
||||
unsigned char tls13tbs[TLS13_TBS_PREAMBLE_SIZE + EVP_MAX_MD_SIZE];
|
||||
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
|
||||
if (mctx == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
peer = s->session->peer;
|
||||
pkey = X509_get0_pubkey(peer);
|
||||
if (pkey == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ssl_cert_lookup_by_pkey(pkey, NULL) == NULL) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_CERT_VERIFY,
|
||||
SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (SSL_USE_SIGALGS(s)) {
|
||||
unsigned int sigalg;
|
||||
|
||||
if (!PACKET_get_net_2(pkt, &sigalg)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
|
||||
SSL_R_BAD_PACKET);
|
||||
goto err;
|
||||
}
|
||||
if (tls12_check_peer_sigalg(s, sigalg, pkey) <= 0) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
#ifdef SSL_DEBUG
|
||||
fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
|
||||
#endif
|
||||
} else if (!tls1_set_peer_legacy_sigalg(s, pkey)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Check for broken implementations of GOST ciphersuites */
|
||||
/*
|
||||
* If key is GOST and len is exactly 64 or 128, it is signature without
|
||||
* length field (CryptoPro implementations at least till TLS 1.2)
|
||||
*/
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
if (!SSL_USE_SIGALGS(s)
|
||||
&& ((PACKET_remaining(pkt) == 64
|
||||
&& (EVP_PKEY_id(pkey) == NID_id_GostR3410_2001
|
||||
|| EVP_PKEY_id(pkey) == NID_id_GostR3410_2012_256))
|
||||
|| (PACKET_remaining(pkt) == 128
|
||||
&& EVP_PKEY_id(pkey) == NID_id_GostR3410_2012_512))) {
|
||||
len = PACKET_remaining(pkt);
|
||||
} else
|
||||
#endif
|
||||
if (!PACKET_get_net_2(pkt, &len)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
j = EVP_PKEY_size(pkey);
|
||||
if (((int)len > j) || ((int)PACKET_remaining(pkt) > j)
|
||||
|| (PACKET_remaining(pkt) == 0)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
|
||||
SSL_R_WRONG_SIGNATURE_SIZE);
|
||||
goto err;
|
||||
}
|
||||
if (!PACKET_get_bytes(pkt, &data, len)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!get_cert_verify_tbs_data(s, tls13tbs, &hdata, &hdatalen)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifdef SSL_DEBUG
|
||||
fprintf(stderr, "Using client verify alg %s\n", EVP_MD_name(md));
|
||||
#endif
|
||||
if (EVP_DigestVerifyInit(mctx, &pctx, md, NULL, pkey) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
|
||||
ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
{
|
||||
int pktype = EVP_PKEY_id(pkey);
|
||||
if (pktype == NID_id_GostR3410_2001
|
||||
|| pktype == NID_id_GostR3410_2012_256
|
||||
|| pktype == NID_id_GostR3410_2012_512) {
|
||||
if ((gost_data = OPENSSL_malloc(len)) == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
BUF_reverse(gost_data, data, len);
|
||||
data = gost_data;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SSL_USE_PSS(s)) {
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
|
||||
|| EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
|
||||
RSA_PSS_SALTLEN_DIGEST) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
|
||||
ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (s->version == SSL3_VERSION) {
|
||||
if (EVP_DigestVerifyUpdate(mctx, hdata, hdatalen) <= 0
|
||||
|| !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
|
||||
(int)s->session->master_key_length,
|
||||
s->session->master_key)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
|
||||
ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (EVP_DigestVerifyFinal(mctx, data, len) <= 0) {
|
||||
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
|
||||
SSL_R_BAD_SIGNATURE);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
j = EVP_DigestVerify(mctx, data, len, hdata, hdatalen);
|
||||
if (j <= 0) {
|
||||
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CERT_VERIFY,
|
||||
SSL_R_BAD_SIGNATURE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ret = MSG_PROCESS_CONTINUE_READING;
|
||||
err:
|
||||
BIO_free(s->s3->handshake_buffer);
|
||||
s->s3->handshake_buffer = NULL;
|
||||
EVP_MD_CTX_free(mctx);
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
OPENSSL_free(gost_data);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tls_construct_finished(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
size_t finish_md_len;
|
||||
const char *sender;
|
||||
size_t slen;
|
||||
|
||||
/* This is a real handshake so make sure we clean it up at the end */
|
||||
if (!s->server && s->post_handshake_auth != SSL_PHA_REQUESTED)
|
||||
s->statem.cleanuphand = 1;
|
||||
|
||||
/*
|
||||
* We only change the keys if we didn't already do this when we sent the
|
||||
* client certificate
|
||||
*/
|
||||
if (SSL_IS_TLS13(s)
|
||||
&& !s->server
|
||||
&& s->s3->tmp.cert_req == 0
|
||||
&& (!s->method->ssl3_enc->change_cipher_state(s,
|
||||
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {;
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->server) {
|
||||
sender = s->method->ssl3_enc->server_finished_label;
|
||||
slen = s->method->ssl3_enc->server_finished_label_len;
|
||||
} else {
|
||||
sender = s->method->ssl3_enc->client_finished_label;
|
||||
slen = s->method->ssl3_enc->client_finished_label_len;
|
||||
}
|
||||
|
||||
finish_md_len = s->method->ssl3_enc->final_finish_mac(s,
|
||||
sender, slen,
|
||||
s->s3->tmp.finish_md);
|
||||
if (finish_md_len == 0) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->s3->tmp.finish_md_len = finish_md_len;
|
||||
|
||||
if (!WPACKET_memcpy(pkt, s->s3->tmp.finish_md, finish_md_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_FINISHED,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Log the master secret, if logging is enabled. We don't log it for
|
||||
* TLSv1.3: there's a different key schedule for that.
|
||||
*/
|
||||
if (!SSL_IS_TLS13(s) && !ssl_log_secret(s, MASTER_SECRET_LABEL,
|
||||
s->session->master_key,
|
||||
s->session->master_key_length)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the finished so we can use it for renegotiation checks
|
||||
*/
|
||||
if (!s->server) {
|
||||
OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
|
||||
memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md, i);
|
||||
s->s3->previous_client_finished_len = i;
|
||||
} else {
|
||||
OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
|
||||
memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md, i);
|
||||
s->s3->previous_server_finished_len = i;
|
||||
}
|
||||
|
||||
if (!ssl_set_handshake_header(s, SSL3_MT_FINISHED, l)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_FINISHED, ERR_R_INTERNAL_ERROR);
|
||||
if (!ossl_assert(finish_md_len <= EVP_MAX_MD_SIZE)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_FINISHED,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (!s->server) {
|
||||
memcpy(s->s3->previous_client_finished, s->s3->tmp.finish_md,
|
||||
finish_md_len);
|
||||
s->s3->previous_client_finished_len = finish_md_len;
|
||||
} else {
|
||||
memcpy(s->s3->previous_server_finished, s->s3->tmp.finish_md,
|
||||
finish_md_len);
|
||||
s->s3->previous_server_finished_len = finish_md_len;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_key_update(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
if (!WPACKET_put_bytes_u8(pkt, s->key_update)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_KEY_UPDATE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->key_update = SSL_KEY_UPDATE_NONE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt)
|
||||
{
|
||||
unsigned int updatetype;
|
||||
|
||||
s->key_update_count++;
|
||||
if (s->key_update_count > MAX_KEY_UPDATE_MESSAGES) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_KEY_UPDATE,
|
||||
SSL_R_TOO_MANY_KEY_UPDATES);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* A KeyUpdate message signals a key change so the end of the message must
|
||||
* be on a record boundary.
|
||||
*/
|
||||
if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
|
||||
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_KEY_UPDATE,
|
||||
SSL_R_NOT_ON_RECORD_BOUNDARY);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
if (!PACKET_get_1(pkt, &updatetype)
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_UPDATE,
|
||||
SSL_R_BAD_KEY_UPDATE);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are only two defined key update types. Fail if we get a value we
|
||||
* didn't recognise.
|
||||
*/
|
||||
if (updatetype != SSL_KEY_UPDATE_NOT_REQUESTED
|
||||
&& updatetype != SSL_KEY_UPDATE_REQUESTED) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_KEY_UPDATE,
|
||||
SSL_R_BAD_KEY_UPDATE);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we get a request for us to update our sending keys too then, we need
|
||||
* to additionally send a KeyUpdate message. However that message should
|
||||
* not also request an update (otherwise we get into an infinite loop).
|
||||
*/
|
||||
if (updatetype == SSL_KEY_UPDATE_REQUESTED)
|
||||
s->key_update = SSL_KEY_UPDATE_NOT_REQUESTED;
|
||||
|
||||
if (!tls13_update_key(s, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
return MSG_PROCESS_FINISHED_READING;
|
||||
}
|
||||
|
||||
/*
|
||||
* ssl3_take_mac calculates the Finished MAC for the handshakes messages seen
|
||||
* to far.
|
||||
@@ -102,7 +653,7 @@ int tls_construct_finished(SSL *s, const char *sender, int slen)
|
||||
int ssl3_take_mac(SSL *s)
|
||||
{
|
||||
const char *sender;
|
||||
int slen;
|
||||
size_t slen;
|
||||
|
||||
if (!s->server) {
|
||||
sender = s->method->ssl3_enc->server_finished_label;
|
||||
@@ -117,7 +668,7 @@ int ssl3_take_mac(SSL *s)
|
||||
s->s3->tmp.peer_finish_md);
|
||||
|
||||
if (s->s3->tmp.peer_finish_md_len == 0) {
|
||||
SSLerr(SSL_F_SSL3_TAKE_MAC, ERR_R_INTERNAL_ERROR);
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -126,8 +677,7 @@ int ssl3_take_mac(SSL *s)
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt)
|
||||
{
|
||||
int al;
|
||||
long remain;
|
||||
size_t remain;
|
||||
|
||||
remain = PACKET_remaining(pkt);
|
||||
/*
|
||||
@@ -140,32 +690,32 @@ MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt)
|
||||
&& remain != DTLS1_CCS_HEADER_LENGTH + 1)
|
||||
|| (s->version != DTLS1_BAD_VER
|
||||
&& remain != DTLS1_CCS_HEADER_LENGTH - 1)) {
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
|
||||
SSL_R_BAD_CHANGE_CIPHER_SPEC);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
|
||||
SSL_R_BAD_CHANGE_CIPHER_SPEC);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
} else {
|
||||
if (remain != 0) {
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
|
||||
SSL_R_BAD_CHANGE_CIPHER_SPEC);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
|
||||
SSL_R_BAD_CHANGE_CIPHER_SPEC);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check we have a cipher to change to */
|
||||
if (s->s3->tmp.new_cipher == NULL) {
|
||||
al = SSL_AD_UNEXPECTED_MESSAGE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
|
||||
SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, SSL_R_CCS_RECEIVED_EARLY);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
s->s3->change_cipher_spec = 1;
|
||||
if (!ssl3_do_change_cipher_spec(s)) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CHANGE_CIPHER_SPEC,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
@@ -185,127 +735,334 @@ MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt)
|
||||
}
|
||||
|
||||
return MSG_PROCESS_CONTINUE_READING;
|
||||
f_err:
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
ossl_statem_set_error(s);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)
|
||||
{
|
||||
int al, i;
|
||||
size_t md_len;
|
||||
|
||||
|
||||
/* This is a real handshake so make sure we clean it up at the end */
|
||||
if (s->server) {
|
||||
if (s->post_handshake_auth != SSL_PHA_REQUESTED)
|
||||
s->statem.cleanuphand = 1;
|
||||
if (SSL_IS_TLS13(s) && !tls13_save_handshake_digest_for_pha(s)) {
|
||||
/* SSLfatal() already called */
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* In TLSv1.3 a Finished message signals a key change so the end of the
|
||||
* message must be on a record boundary.
|
||||
*/
|
||||
if (SSL_IS_TLS13(s) && RECORD_LAYER_processed_read_pending(&s->rlayer)) {
|
||||
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_FINISHED,
|
||||
SSL_R_NOT_ON_RECORD_BOUNDARY);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
/* If this occurs, we have missed a message */
|
||||
if (!s->s3->change_cipher_spec) {
|
||||
al = SSL_AD_UNEXPECTED_MESSAGE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_GOT_A_FIN_BEFORE_A_CCS);
|
||||
goto f_err;
|
||||
if (!SSL_IS_TLS13(s) && !s->s3->change_cipher_spec) {
|
||||
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_FINISHED,
|
||||
SSL_R_GOT_A_FIN_BEFORE_A_CCS);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
s->s3->change_cipher_spec = 0;
|
||||
|
||||
i = s->s3->tmp.peer_finish_md_len;
|
||||
md_len = s->s3->tmp.peer_finish_md_len;
|
||||
|
||||
if ((unsigned long)i != PACKET_remaining(pkt)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_BAD_DIGEST_LENGTH);
|
||||
goto f_err;
|
||||
if (md_len != PACKET_remaining(pkt)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_FINISHED,
|
||||
SSL_R_BAD_DIGEST_LENGTH);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
if (CRYPTO_memcmp(PACKET_data(pkt), s->s3->tmp.peer_finish_md, i) != 0) {
|
||||
al = SSL_AD_DECRYPT_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_FINISHED, SSL_R_DIGEST_CHECK_FAILED);
|
||||
goto f_err;
|
||||
if (CRYPTO_memcmp(PACKET_data(pkt), s->s3->tmp.peer_finish_md,
|
||||
md_len) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_FINISHED,
|
||||
SSL_R_DIGEST_CHECK_FAILED);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the finished so we can use it for renegotiation checks
|
||||
*/
|
||||
if (!ossl_assert(md_len <= EVP_MAX_MD_SIZE)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_FINISHED,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
if (s->server) {
|
||||
OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
|
||||
memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md, i);
|
||||
s->s3->previous_client_finished_len = i;
|
||||
memcpy(s->s3->previous_client_finished, s->s3->tmp.peer_finish_md,
|
||||
md_len);
|
||||
s->s3->previous_client_finished_len = md_len;
|
||||
} else {
|
||||
OPENSSL_assert(i <= EVP_MAX_MD_SIZE);
|
||||
memcpy(s->s3->previous_server_finished, s->s3->tmp.peer_finish_md, i);
|
||||
s->s3->previous_server_finished_len = i;
|
||||
memcpy(s->s3->previous_server_finished, s->s3->tmp.peer_finish_md,
|
||||
md_len);
|
||||
s->s3->previous_server_finished_len = md_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* In TLS1.3 we also have to change cipher state and do any final processing
|
||||
* of the initial server flight (if we are a client)
|
||||
*/
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
if (s->server) {
|
||||
if (s->post_handshake_auth != SSL_PHA_REQUESTED &&
|
||||
!s->method->ssl3_enc->change_cipher_state(s,
|
||||
SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_READ)) {
|
||||
/* SSLfatal() already called */
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
} else {
|
||||
if (!s->method->ssl3_enc->generate_master_secret(s,
|
||||
s->master_secret, s->handshake_secret, 0,
|
||||
&s->session->master_key_length)) {
|
||||
/* SSLfatal() already called */
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
if (!s->method->ssl3_enc->change_cipher_state(s,
|
||||
SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_READ)) {
|
||||
/* SSLfatal() already called */
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
if (!tls_process_initial_server_flight(s)) {
|
||||
/* SSLfatal() already called */
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MSG_PROCESS_FINISHED_READING;
|
||||
f_err:
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
ossl_statem_set_error(s);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
int tls_construct_change_cipher_spec(SSL *s)
|
||||
int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
p = (unsigned char *)s->init_buf->data;
|
||||
*p = SSL3_MT_CCS;
|
||||
s->init_num = 1;
|
||||
s->init_off = 0;
|
||||
if (!WPACKET_put_bytes_u8(pkt, SSL3_MT_CCS)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CHANGE_CIPHER_SPEC, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned long ssl3_output_cert_chain(SSL *s, CERT_PKEY *cpk)
|
||||
/* Add a certificate to the WPACKET */
|
||||
static int ssl_add_cert_to_wpacket(SSL *s, WPACKET *pkt, X509 *x, int chain)
|
||||
{
|
||||
unsigned char *p;
|
||||
unsigned long l = 3 + SSL_HM_HEADER_LENGTH(s);
|
||||
int len;
|
||||
unsigned char *outbytes;
|
||||
|
||||
if (!ssl_add_cert_chain(s, cpk, &l))
|
||||
return 0;
|
||||
|
||||
l -= 3 + SSL_HM_HEADER_LENGTH(s);
|
||||
p = ssl_handshake_start(s);
|
||||
l2n3(l, p);
|
||||
l += 3;
|
||||
|
||||
if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE, l)) {
|
||||
SSLerr(SSL_F_SSL3_OUTPUT_CERT_CHAIN, ERR_R_INTERNAL_ERROR);
|
||||
len = i2d_X509(x, NULL);
|
||||
if (len < 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_TO_WPACKET,
|
||||
ERR_R_BUF_LIB);
|
||||
return 0;
|
||||
}
|
||||
return l + SSL_HM_HEADER_LENGTH(s);
|
||||
if (!WPACKET_sub_allocate_bytes_u24(pkt, len, &outbytes)
|
||||
|| i2d_X509(x, &outbytes) != len) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_TO_WPACKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SSL_IS_TLS13(s)
|
||||
&& !tls_construct_extensions(s, pkt, SSL_EXT_TLS1_3_CERTIFICATE, x,
|
||||
chain)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst)
|
||||
/* Add certificate chain to provided WPACKET */
|
||||
static int ssl_add_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
|
||||
{
|
||||
void (*cb) (const SSL *ssl, int type, int val) = NULL;
|
||||
int i, chain_count;
|
||||
X509 *x;
|
||||
STACK_OF(X509) *extra_certs;
|
||||
STACK_OF(X509) *chain = NULL;
|
||||
X509_STORE *chain_store;
|
||||
|
||||
/* clean a few things up */
|
||||
ssl3_cleanup_key_block(s);
|
||||
if (cpk == NULL || cpk->x509 == NULL)
|
||||
return 1;
|
||||
|
||||
if (!SSL_IS_DTLS(s)) {
|
||||
x = cpk->x509;
|
||||
|
||||
/*
|
||||
* If we have a certificate specific chain use it, else use parent ctx.
|
||||
*/
|
||||
if (cpk->chain != NULL)
|
||||
extra_certs = cpk->chain;
|
||||
else
|
||||
extra_certs = s->ctx->extra_certs;
|
||||
|
||||
if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || extra_certs)
|
||||
chain_store = NULL;
|
||||
else if (s->cert->chain_store)
|
||||
chain_store = s->cert->chain_store;
|
||||
else
|
||||
chain_store = s->ctx->cert_store;
|
||||
|
||||
if (chain_store != NULL) {
|
||||
X509_STORE_CTX *xs_ctx = X509_STORE_CTX_new();
|
||||
|
||||
if (xs_ctx == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (!X509_STORE_CTX_init(xs_ctx, chain_store, x, NULL)) {
|
||||
X509_STORE_CTX_free(xs_ctx);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN,
|
||||
ERR_R_X509_LIB);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* We don't do this in DTLS because we may still need the init_buf
|
||||
* in case there are any unexpected retransmits
|
||||
* It is valid for the chain not to be complete (because normally we
|
||||
* don't include the root cert in the chain). Therefore we deliberately
|
||||
* ignore the error return from this call. We're not actually verifying
|
||||
* the cert - we're just building as much of the chain as we can
|
||||
*/
|
||||
BUF_MEM_free(s->init_buf);
|
||||
s->init_buf = NULL;
|
||||
(void)X509_verify_cert(xs_ctx);
|
||||
/* Don't leave errors in the queue */
|
||||
ERR_clear_error();
|
||||
chain = X509_STORE_CTX_get0_chain(xs_ctx);
|
||||
i = ssl_security_cert_chain(s, chain, NULL, 0);
|
||||
if (i != 1) {
|
||||
#if 0
|
||||
/* Dummy error calls so mkerr generates them */
|
||||
SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_EE_KEY_TOO_SMALL);
|
||||
SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_KEY_TOO_SMALL);
|
||||
SSLerr(SSL_F_SSL_ADD_CERT_CHAIN, SSL_R_CA_MD_TOO_WEAK);
|
||||
#endif
|
||||
X509_STORE_CTX_free(xs_ctx);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i);
|
||||
return 0;
|
||||
}
|
||||
chain_count = sk_X509_num(chain);
|
||||
for (i = 0; i < chain_count; i++) {
|
||||
x = sk_X509_value(chain, i);
|
||||
|
||||
if (!ssl_add_cert_to_wpacket(s, pkt, x, i)) {
|
||||
/* SSLfatal() already called */
|
||||
X509_STORE_CTX_free(xs_ctx);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
X509_STORE_CTX_free(xs_ctx);
|
||||
} else {
|
||||
i = ssl_security_cert_chain(s, extra_certs, x, 0);
|
||||
if (i != 1) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_ADD_CERT_CHAIN, i);
|
||||
return 0;
|
||||
}
|
||||
if (!ssl_add_cert_to_wpacket(s, pkt, x, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < sk_X509_num(extra_certs); i++) {
|
||||
x = sk_X509_value(extra_certs, i);
|
||||
if (!ssl_add_cert_to_wpacket(s, pkt, x, i + 1)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk)
|
||||
{
|
||||
if (!WPACKET_start_sub_packet_u24(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_OUTPUT_CERT_CHAIN,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssl_free_wbio_buffer(s);
|
||||
if (!ssl_add_cert_chain(s, pkt, cpk))
|
||||
return 0;
|
||||
|
||||
s->init_num = 0;
|
||||
if (!WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_OUTPUT_CERT_CHAIN,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s->server || s->renegotiate == 2) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tidy up after the end of a handshake. In the case of SCTP this may result
|
||||
* in NBIO events. If |clearbufs| is set then init_buf and the wbio buffer is
|
||||
* freed up as well.
|
||||
*/
|
||||
WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs, int stop)
|
||||
{
|
||||
int discard;
|
||||
void (*cb) (const SSL *ssl, int type, int val) = NULL;
|
||||
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
|
||||
WORK_STATE ret;
|
||||
ret = dtls_wait_for_dry(s);
|
||||
if (ret != WORK_FINISHED_CONTINUE)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (clearbufs) {
|
||||
if (!SSL_IS_DTLS(s)) {
|
||||
/*
|
||||
* We don't do this in DTLS because we may still need the init_buf
|
||||
* in case there are any unexpected retransmits
|
||||
*/
|
||||
BUF_MEM_free(s->init_buf);
|
||||
s->init_buf = NULL;
|
||||
}
|
||||
if (!ssl_free_wbio_buffer(s)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_FINISH_HANDSHAKE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return WORK_ERROR;
|
||||
}
|
||||
s->init_num = 0;
|
||||
}
|
||||
|
||||
if (SSL_IS_TLS13(s) && !s->server
|
||||
&& s->post_handshake_auth == SSL_PHA_REQUESTED)
|
||||
s->post_handshake_auth = SSL_PHA_EXT_SENT;
|
||||
|
||||
if (s->statem.cleanuphand) {
|
||||
/* skipped if we just sent a HelloRequest */
|
||||
s->renegotiate = 0;
|
||||
s->new_session = 0;
|
||||
s->statem.cleanuphand = 0;
|
||||
|
||||
ssl3_cleanup_key_block(s);
|
||||
|
||||
if (s->server) {
|
||||
ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
|
||||
|
||||
s->ctx->stats.sess_accept_good++;
|
||||
/* N.B. s->ctx may not equal s->session_ctx */
|
||||
CRYPTO_atomic_add(&s->ctx->stats.sess_accept_good, 1, &discard,
|
||||
s->ctx->lock);
|
||||
s->handshake_func = ossl_statem_accept;
|
||||
} else {
|
||||
ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
|
||||
/*
|
||||
* In TLSv1.3 we update the cache as part of processing the
|
||||
* NewSessionTicket
|
||||
*/
|
||||
if (!SSL_IS_TLS13(s))
|
||||
ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
|
||||
if (s->hit)
|
||||
s->ctx->stats.sess_hit++;
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_hit, 1, &discard,
|
||||
s->session_ctx->lock);
|
||||
|
||||
s->handshake_func = ossl_statem_connect;
|
||||
s->ctx->stats.sess_connect_good++;
|
||||
CRYPTO_atomic_add(&s->session_ctx->stats.sess_connect_good, 1,
|
||||
&discard, s->session_ctx->lock);
|
||||
}
|
||||
|
||||
if (s->info_callback != NULL)
|
||||
@@ -325,15 +1082,19 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst)
|
||||
}
|
||||
}
|
||||
|
||||
if (!stop)
|
||||
return WORK_FINISHED_CONTINUE;
|
||||
|
||||
ossl_statem_set_in_init(s, 0);
|
||||
return WORK_FINISHED_STOP;
|
||||
}
|
||||
|
||||
int tls_get_message_header(SSL *s, int *mt)
|
||||
{
|
||||
/* s->init_num < SSL3_HM_HEADER_LENGTH */
|
||||
int skip_message, i, recvd_type, al;
|
||||
int skip_message, i, recvd_type;
|
||||
unsigned char *p;
|
||||
unsigned long l;
|
||||
size_t l, readbytes;
|
||||
|
||||
p = (unsigned char *)s->init_buf->data;
|
||||
|
||||
@@ -342,7 +1103,7 @@ int tls_get_message_header(SSL *s, int *mt)
|
||||
i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, &recvd_type,
|
||||
&p[s->init_num],
|
||||
SSL3_HM_HEADER_LENGTH - s->init_num,
|
||||
0);
|
||||
0, &readbytes);
|
||||
if (i <= 0) {
|
||||
s->rwstate = SSL_READING;
|
||||
return 0;
|
||||
@@ -352,28 +1113,41 @@ int tls_get_message_header(SSL *s, int *mt)
|
||||
* A ChangeCipherSpec must be a single byte and may not occur
|
||||
* in the middle of a handshake message.
|
||||
*/
|
||||
if (s->init_num != 0 || i != 1 || p[0] != SSL3_MT_CCS) {
|
||||
al = SSL_AD_UNEXPECTED_MESSAGE;
|
||||
SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER,
|
||||
SSL_R_BAD_CHANGE_CIPHER_SPEC);
|
||||
goto f_err;
|
||||
if (s->init_num != 0 || readbytes != 1 || p[0] != SSL3_MT_CCS) {
|
||||
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
|
||||
SSL_F_TLS_GET_MESSAGE_HEADER,
|
||||
SSL_R_BAD_CHANGE_CIPHER_SPEC);
|
||||
return 0;
|
||||
}
|
||||
if (s->statem.hand_state == TLS_ST_BEFORE
|
||||
&& (s->s3->flags & TLS1_FLAGS_STATELESS) != 0) {
|
||||
/*
|
||||
* We are stateless and we received a CCS. Probably this is
|
||||
* from a client between the first and second ClientHellos.
|
||||
* We should ignore this, but return an error because we do
|
||||
* not return success until we see the second ClientHello
|
||||
* with a valid cookie.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
s->s3->tmp.message_type = *mt = SSL3_MT_CHANGE_CIPHER_SPEC;
|
||||
s->init_num = i - 1;
|
||||
s->init_num = readbytes - 1;
|
||||
s->init_msg = s->init_buf->data;
|
||||
s->s3->tmp.message_size = i;
|
||||
s->s3->tmp.message_size = readbytes;
|
||||
return 1;
|
||||
} else if (recvd_type != SSL3_RT_HANDSHAKE) {
|
||||
al = SSL_AD_UNEXPECTED_MESSAGE;
|
||||
SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, SSL_R_CCS_RECEIVED_EARLY);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
|
||||
SSL_F_TLS_GET_MESSAGE_HEADER,
|
||||
SSL_R_CCS_RECEIVED_EARLY);
|
||||
return 0;
|
||||
}
|
||||
s->init_num += i;
|
||||
s->init_num += readbytes;
|
||||
}
|
||||
|
||||
skip_message = 0;
|
||||
if (!s->server)
|
||||
if (p[0] == SSL3_MT_HELLO_REQUEST)
|
||||
if (s->statem.hand_state != TLS_ST_OK
|
||||
&& p[0] == SSL3_MT_HELLO_REQUEST)
|
||||
/*
|
||||
* The server may always send 'Hello Request' messages --
|
||||
* we are doing a handshake anyway now, so ignore them if
|
||||
@@ -413,9 +1187,9 @@ int tls_get_message_header(SSL *s, int *mt)
|
||||
n2l3(p, l);
|
||||
/* BUF_MEM_grow takes an 'int' parameter */
|
||||
if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) {
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_GET_MESSAGE_HEADER, SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_GET_MESSAGE_HEADER,
|
||||
SSL_R_EXCESSIVE_MESSAGE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
s->s3->tmp.message_size = l;
|
||||
|
||||
@@ -424,14 +1198,11 @@ int tls_get_message_header(SSL *s, int *mt)
|
||||
}
|
||||
|
||||
return 1;
|
||||
f_err:
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tls_get_message_body(SSL *s, unsigned long *len)
|
||||
int tls_get_message_body(SSL *s, size_t *len)
|
||||
{
|
||||
long n;
|
||||
size_t n, readbytes;
|
||||
unsigned char *p;
|
||||
int i;
|
||||
|
||||
@@ -445,14 +1216,14 @@ int tls_get_message_body(SSL *s, unsigned long *len)
|
||||
n = s->s3->tmp.message_size - s->init_num;
|
||||
while (n > 0) {
|
||||
i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, NULL,
|
||||
&p[s->init_num], n, 0);
|
||||
&p[s->init_num], n, 0, &readbytes);
|
||||
if (i <= 0) {
|
||||
s->rwstate = SSL_READING;
|
||||
*len = 0;
|
||||
return 0;
|
||||
}
|
||||
s->init_num += i;
|
||||
n -= i;
|
||||
s->init_num += readbytes;
|
||||
n -= readbytes;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -469,8 +1240,7 @@ int tls_get_message_body(SSL *s, unsigned long *len)
|
||||
if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
|
||||
if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
|
||||
s->init_num)) {
|
||||
SSLerr(SSL_F_TLS_GET_MESSAGE_BODY, ERR_R_EVP_LIB);
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
/* SSLfatal() already called */
|
||||
*len = 0;
|
||||
return 0;
|
||||
}
|
||||
@@ -478,12 +1248,28 @@ int tls_get_message_body(SSL *s, unsigned long *len)
|
||||
s->msg_callback(0, SSL2_VERSION, 0, s->init_buf->data,
|
||||
(size_t)s->init_num, s, s->msg_callback_arg);
|
||||
} else {
|
||||
if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
|
||||
s->init_num + SSL3_HM_HEADER_LENGTH)) {
|
||||
SSLerr(SSL_F_TLS_GET_MESSAGE_BODY, ERR_R_EVP_LIB);
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
*len = 0;
|
||||
return 0;
|
||||
/*
|
||||
* We defer feeding in the HRR until later. We'll do it as part of
|
||||
* processing the message
|
||||
* The TLsv1.3 handshake transcript stops at the ClientFinished
|
||||
* message.
|
||||
*/
|
||||
#define SERVER_HELLO_RANDOM_OFFSET (SSL3_HM_HEADER_LENGTH + 2)
|
||||
/* KeyUpdate and NewSessionTicket do not need to be added */
|
||||
if (!SSL_IS_TLS13(s) || (s->s3->tmp.message_type != SSL3_MT_NEWSESSION_TICKET
|
||||
&& s->s3->tmp.message_type != SSL3_MT_KEY_UPDATE)) {
|
||||
if (s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO
|
||||
|| s->init_num < SERVER_HELLO_RANDOM_OFFSET + SSL3_RANDOM_SIZE
|
||||
|| memcmp(hrrrandom,
|
||||
s->init_buf->data + SERVER_HELLO_RANDOM_OFFSET,
|
||||
SSL3_RANDOM_SIZE) != 0) {
|
||||
if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
|
||||
s->init_num + SSL3_HM_HEADER_LENGTH)) {
|
||||
/* SSLfatal() already called */
|
||||
*len = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s->msg_callback)
|
||||
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data,
|
||||
@@ -491,47 +1277,10 @@ int tls_get_message_body(SSL *s, unsigned long *len)
|
||||
s->msg_callback_arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* init_num should never be negative...should probably be declared
|
||||
* unsigned
|
||||
*/
|
||||
if (s->init_num < 0) {
|
||||
SSLerr(SSL_F_TLS_GET_MESSAGE_BODY, ERR_R_INTERNAL_ERROR);
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
|
||||
*len = 0;
|
||||
return 0;
|
||||
}
|
||||
*len = (unsigned long)s->init_num;
|
||||
*len = s->init_num;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ssl_cert_type(const X509 *x, const EVP_PKEY *pk)
|
||||
{
|
||||
if (pk == NULL && (pk = X509_get0_pubkey(x)) == NULL)
|
||||
return -1;
|
||||
|
||||
switch (EVP_PKEY_id(pk)) {
|
||||
default:
|
||||
return -1;
|
||||
case EVP_PKEY_RSA:
|
||||
return SSL_PKEY_RSA_ENC;
|
||||
case EVP_PKEY_DSA:
|
||||
return SSL_PKEY_DSA_SIGN;
|
||||
#ifndef OPENSSL_NO_EC
|
||||
case EVP_PKEY_EC:
|
||||
return SSL_PKEY_ECC;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
case NID_id_GostR3410_2001:
|
||||
return SSL_PKEY_GOST01;
|
||||
case NID_id_GostR3410_2012_256:
|
||||
return SSL_PKEY_GOST12_256;
|
||||
case NID_id_GostR3410_2012_512:
|
||||
return SSL_PKEY_GOST12_512;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int ssl_verify_alarm_type(long type)
|
||||
{
|
||||
int al;
|
||||
@@ -598,7 +1347,7 @@ int ssl_verify_alarm_type(long type)
|
||||
al = SSL_AD_CERTIFICATE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
return (al);
|
||||
return al;
|
||||
}
|
||||
|
||||
int ssl_allow_compression(SSL *s)
|
||||
@@ -625,11 +1374,17 @@ typedef struct {
|
||||
const SSL_METHOD *(*smeth) (void);
|
||||
} version_info;
|
||||
|
||||
#if TLS_MAX_VERSION != TLS1_2_VERSION
|
||||
# error Code needs update for TLS_method() support beyond TLS1_2_VERSION.
|
||||
#if TLS_MAX_VERSION != TLS1_3_VERSION
|
||||
# error Code needs update for TLS_method() support beyond TLS1_3_VERSION.
|
||||
#endif
|
||||
|
||||
/* Must be in order high to low */
|
||||
static const version_info tls_version_table[] = {
|
||||
#ifndef OPENSSL_NO_TLS1_3
|
||||
{TLS1_3_VERSION, tlsv1_3_client_method, tlsv1_3_server_method},
|
||||
#else
|
||||
{TLS1_3_VERSION, NULL, NULL},
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_TLS1_2
|
||||
{TLS1_2_VERSION, tlsv1_2_client_method, tlsv1_2_server_method},
|
||||
#else
|
||||
@@ -657,6 +1412,7 @@ static const version_info tls_version_table[] = {
|
||||
# error Code needs update for DTLS_method() support beyond DTLS1_2_VERSION.
|
||||
#endif
|
||||
|
||||
/* Must be in order high to low */
|
||||
static const version_info dtls_version_table[] = {
|
||||
#ifndef OPENSSL_NO_DTLS1_2
|
||||
{DTLS1_2_VERSION, dtlsv1_2_client_method, dtlsv1_2_server_method},
|
||||
@@ -698,8 +1454,6 @@ static int ssl_method_error(const SSL *s, const SSL_METHOD *method)
|
||||
return SSL_R_UNSUPPORTED_PROTOCOL;
|
||||
if ((method->flags & SSL_METHOD_NO_SUITEB) != 0 && tls1_suiteb(s))
|
||||
return SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE;
|
||||
else if ((method->flags & SSL_METHOD_NO_FIPS) != 0 && FIPS_mode())
|
||||
return SSL_R_AT_LEAST_TLS_1_0_NEEDED_IN_FIPS_MODE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -841,6 +1595,20 @@ int ssl_set_version_bound(int method_version, int version, int *bound)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void check_for_downgrade(SSL *s, int vers, DOWNGRADE *dgrd)
|
||||
{
|
||||
if (vers == TLS1_2_VERSION
|
||||
&& ssl_version_supported(s, TLS1_3_VERSION)) {
|
||||
*dgrd = DOWNGRADE_TO_1_2;
|
||||
} else if (!SSL_IS_DTLS(s) && vers < TLS1_2_VERSION
|
||||
&& (ssl_version_supported(s, TLS1_2_VERSION)
|
||||
|| ssl_version_supported(s, TLS1_3_VERSION))) {
|
||||
*dgrd = DOWNGRADE_TO_1_1;
|
||||
} else {
|
||||
*dgrd = DOWNGRADE_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ssl_choose_server_version - Choose server (D)TLS version. Called when the
|
||||
* client HELLO is received to select the final server protocol version and
|
||||
@@ -850,7 +1618,7 @@ int ssl_set_version_bound(int method_version, int version, int *bound)
|
||||
*
|
||||
* Returns 0 on success or an SSL error reason number on failure.
|
||||
*/
|
||||
int ssl_choose_server_version(SSL *s)
|
||||
int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd)
|
||||
{
|
||||
/*-
|
||||
* With version-flexible methods we have an initial state with:
|
||||
@@ -862,23 +1630,34 @@ int ssl_choose_server_version(SSL *s)
|
||||
* handle version.
|
||||
*/
|
||||
int server_version = s->method->version;
|
||||
int client_version = s->client_version;
|
||||
int client_version = hello->legacy_version;
|
||||
const version_info *vent;
|
||||
const version_info *table;
|
||||
int disabled = 0;
|
||||
RAW_EXTENSION *suppversions;
|
||||
|
||||
s->client_version = client_version;
|
||||
|
||||
switch (server_version) {
|
||||
default:
|
||||
if (version_cmp(s, client_version, s->version) < 0)
|
||||
return SSL_R_WRONG_SSL_VERSION;
|
||||
if (!SSL_IS_TLS13(s)) {
|
||||
if (version_cmp(s, client_version, s->version) < 0)
|
||||
return SSL_R_WRONG_SSL_VERSION;
|
||||
*dgrd = DOWNGRADE_NONE;
|
||||
/*
|
||||
* If this SSL handle is not from a version flexible method we don't
|
||||
* (and never did) check min/max FIPS or Suite B constraints. Hope
|
||||
* that's OK. It is up to the caller to not choose fixed protocol
|
||||
* versions they don't want. If not, then easy to fix, just return
|
||||
* ssl_method_error(s, s->method)
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* If this SSL handle is not from a version flexible method we don't
|
||||
* (and never did) check min/max FIPS or Suite B constraints. Hope
|
||||
* that's OK. It is up to the caller to not choose fixed protocol
|
||||
* versions they don't want. If not, then easy to fix, just return
|
||||
* ssl_method_error(s, s->method)
|
||||
* Fall through if we are TLSv1.3 already (this means we must be after
|
||||
* a HelloRetryRequest
|
||||
*/
|
||||
return 0;
|
||||
/* fall thru */
|
||||
case TLS_ANY_VERSION:
|
||||
table = tls_version_table;
|
||||
break;
|
||||
@@ -887,6 +1666,84 @@ int ssl_choose_server_version(SSL *s)
|
||||
break;
|
||||
}
|
||||
|
||||
suppversions = &hello->pre_proc_exts[TLSEXT_IDX_supported_versions];
|
||||
|
||||
/* If we did an HRR then supported versions is mandatory */
|
||||
if (!suppversions->present && s->hello_retry_request != SSL_HRR_NONE)
|
||||
return SSL_R_UNSUPPORTED_PROTOCOL;
|
||||
|
||||
if (suppversions->present && !SSL_IS_DTLS(s)) {
|
||||
unsigned int candidate_vers = 0;
|
||||
unsigned int best_vers = 0;
|
||||
const SSL_METHOD *best_method = NULL;
|
||||
PACKET versionslist;
|
||||
|
||||
suppversions->parsed = 1;
|
||||
|
||||
if (!PACKET_as_length_prefixed_1(&suppversions->data, &versionslist)) {
|
||||
/* Trailing or invalid data? */
|
||||
return SSL_R_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
while (PACKET_get_net_2(&versionslist, &candidate_vers)) {
|
||||
/* TODO(TLS1.3): Remove this before release */
|
||||
if (candidate_vers == TLS1_3_VERSION_DRAFT)
|
||||
candidate_vers = TLS1_3_VERSION;
|
||||
/*
|
||||
* TODO(TLS1.3): There is some discussion on the TLS list about
|
||||
* whether to ignore versions <TLS1.2 in supported_versions. At the
|
||||
* moment we honour them if present. To be reviewed later
|
||||
*/
|
||||
if (version_cmp(s, candidate_vers, best_vers) <= 0)
|
||||
continue;
|
||||
for (vent = table;
|
||||
vent->version != 0 && vent->version != (int)candidate_vers;
|
||||
++vent)
|
||||
continue;
|
||||
if (vent->version != 0 && vent->smeth != NULL) {
|
||||
const SSL_METHOD *method;
|
||||
|
||||
method = vent->smeth();
|
||||
if (ssl_method_error(s, method) == 0) {
|
||||
best_vers = candidate_vers;
|
||||
best_method = method;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (PACKET_remaining(&versionslist) != 0) {
|
||||
/* Trailing data? */
|
||||
return SSL_R_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
if (best_vers > 0) {
|
||||
if (s->hello_retry_request != SSL_HRR_NONE) {
|
||||
/*
|
||||
* This is after a HelloRetryRequest so we better check that we
|
||||
* negotiated TLSv1.3
|
||||
*/
|
||||
if (best_vers != TLS1_3_VERSION)
|
||||
return SSL_R_UNSUPPORTED_PROTOCOL;
|
||||
return 0;
|
||||
}
|
||||
check_for_downgrade(s, best_vers, dgrd);
|
||||
s->version = best_vers;
|
||||
s->method = best_method;
|
||||
return 0;
|
||||
}
|
||||
return SSL_R_UNSUPPORTED_PROTOCOL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the supported versions extension isn't present, then the highest
|
||||
* version we can negotiate is TLSv1.2
|
||||
*/
|
||||
if (version_cmp(s, client_version, TLS1_3_VERSION) >= 0)
|
||||
client_version = TLS1_2_VERSION;
|
||||
|
||||
/*
|
||||
* No supported versions extension, so we just use the version supplied in
|
||||
* the ClientHello.
|
||||
*/
|
||||
for (vent = table; vent->version != 0; ++vent) {
|
||||
const SSL_METHOD *method;
|
||||
|
||||
@@ -895,6 +1752,7 @@ int ssl_choose_server_version(SSL *s)
|
||||
continue;
|
||||
method = vent->smeth();
|
||||
if (ssl_method_error(s, method) == 0) {
|
||||
check_for_downgrade(s, vent->version, dgrd);
|
||||
s->version = vent->version;
|
||||
s->method = method;
|
||||
return 0;
|
||||
@@ -911,18 +1769,46 @@ int ssl_choose_server_version(SSL *s)
|
||||
*
|
||||
* @s: client SSL handle.
|
||||
* @version: The proposed version from the server's HELLO.
|
||||
* @extensions: The extensions received
|
||||
*
|
||||
* Returns 0 on success or an SSL error reason number on failure.
|
||||
* Returns 1 on success or 0 on error.
|
||||
*/
|
||||
int ssl_choose_client_version(SSL *s, int version)
|
||||
int ssl_choose_client_version(SSL *s, int version, RAW_EXTENSION *extensions)
|
||||
{
|
||||
const version_info *vent;
|
||||
const version_info *table;
|
||||
int highver = 0;
|
||||
int origv;
|
||||
|
||||
origv = s->version;
|
||||
s->version = version;
|
||||
|
||||
/* This will overwrite s->version if the extension is present */
|
||||
if (!tls_parse_extension(s, TLSEXT_IDX_supported_versions,
|
||||
SSL_EXT_TLS1_2_SERVER_HELLO
|
||||
| SSL_EXT_TLS1_3_SERVER_HELLO, extensions,
|
||||
NULL, 0)) {
|
||||
s->version = origv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (s->hello_retry_request != SSL_HRR_NONE
|
||||
&& s->version != TLS1_3_VERSION) {
|
||||
s->version = origv;
|
||||
SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION,
|
||||
SSL_R_WRONG_SSL_VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (s->method->version) {
|
||||
default:
|
||||
if (version != s->version)
|
||||
return SSL_R_WRONG_SSL_VERSION;
|
||||
if (s->version != s->method->version) {
|
||||
s->version = origv;
|
||||
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
|
||||
SSL_F_SSL_CHOOSE_CLIENT_VERSION,
|
||||
SSL_R_WRONG_SSL_VERSION);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* If this SSL handle is not from a version flexible method we don't
|
||||
* (and never did) check min/max, FIPS or Suite B constraints. Hope
|
||||
@@ -930,7 +1816,7 @@ int ssl_choose_client_version(SSL *s, int version)
|
||||
* versions they don't want. If not, then easy to fix, just return
|
||||
* ssl_method_error(s, s->method)
|
||||
*/
|
||||
return 0;
|
||||
return 1;
|
||||
case TLS_ANY_VERSION:
|
||||
table = tls_version_table;
|
||||
break;
|
||||
@@ -943,24 +1829,71 @@ int ssl_choose_client_version(SSL *s, int version)
|
||||
const SSL_METHOD *method;
|
||||
int err;
|
||||
|
||||
if (version != vent->version)
|
||||
continue;
|
||||
if (vent->cmeth == NULL)
|
||||
break;
|
||||
continue;
|
||||
|
||||
if (highver != 0 && s->version != vent->version)
|
||||
continue;
|
||||
|
||||
method = vent->cmeth();
|
||||
err = ssl_method_error(s, method);
|
||||
if (err != 0)
|
||||
return err;
|
||||
if (err != 0) {
|
||||
if (s->version == vent->version) {
|
||||
s->version = origv;
|
||||
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
|
||||
SSL_F_SSL_CHOOSE_CLIENT_VERSION, err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
if (highver == 0)
|
||||
highver = vent->version;
|
||||
|
||||
if (s->version != vent->version)
|
||||
continue;
|
||||
|
||||
#ifndef OPENSSL_NO_TLS13DOWNGRADE
|
||||
/* Check for downgrades */
|
||||
if (s->version == TLS1_2_VERSION && highver > s->version) {
|
||||
if (memcmp(tls12downgrade,
|
||||
s->s3->server_random + SSL3_RANDOM_SIZE
|
||||
- sizeof(tls12downgrade),
|
||||
sizeof(tls12downgrade)) == 0) {
|
||||
s->version = origv;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_SSL_CHOOSE_CLIENT_VERSION,
|
||||
SSL_R_INAPPROPRIATE_FALLBACK);
|
||||
return 0;
|
||||
}
|
||||
} else if (!SSL_IS_DTLS(s)
|
||||
&& s->version < TLS1_2_VERSION
|
||||
&& highver > s->version) {
|
||||
if (memcmp(tls11downgrade,
|
||||
s->s3->server_random + SSL3_RANDOM_SIZE
|
||||
- sizeof(tls11downgrade),
|
||||
sizeof(tls11downgrade)) == 0) {
|
||||
s->version = origv;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_SSL_CHOOSE_CLIENT_VERSION,
|
||||
SSL_R_INAPPROPRIATE_FALLBACK);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
s->method = method;
|
||||
s->version = version;
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return SSL_R_UNSUPPORTED_PROTOCOL;
|
||||
s->version = origv;
|
||||
SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_SSL_CHOOSE_CLIENT_VERSION,
|
||||
SSL_R_UNSUPPORTED_PROTOCOL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ssl_get_client_min_max_version - get minimum and maximum client version
|
||||
* ssl_get_min_max_version - get minimum and maximum protocol version
|
||||
* @s: The SSL connection
|
||||
* @min_version: The minimum supported version
|
||||
* @max_version: The maximum supported version
|
||||
@@ -968,7 +1901,7 @@ int ssl_choose_client_version(SSL *s, int version)
|
||||
* Work out what version we should be using for the initial ClientHello if the
|
||||
* version is initially (D)TLS_ANY_VERSION. We apply any explicit SSL_OP_NO_xxx
|
||||
* options, the MinProtocol and MaxProtocol configuration commands, any Suite B
|
||||
* or FIPS_mode() constraints and any floor imposed by the security level here,
|
||||
* constraints and any floor imposed by the security level here,
|
||||
* so we don't advertise the wrong protocol version to only reject the outcome later.
|
||||
*
|
||||
* Computing the right floor matters. If, e.g., TLS 1.0 and 1.2 are enabled,
|
||||
@@ -978,8 +1911,7 @@ int ssl_choose_client_version(SSL *s, int version)
|
||||
* Returns 0 on success or an SSL error reason number on failure. On failure
|
||||
* min_version and max_version will also be set to 0.
|
||||
*/
|
||||
int ssl_get_client_min_max_version(const SSL *s, int *min_version,
|
||||
int *max_version)
|
||||
int ssl_get_min_max_version(const SSL *s, int *min_version, int *max_version)
|
||||
{
|
||||
int version;
|
||||
int hole;
|
||||
@@ -1063,7 +1995,7 @@ int ssl_get_client_min_max_version(const SSL *s, int *min_version,
|
||||
|
||||
/*
|
||||
* ssl_set_client_hello_version - Work out what version we should be using for
|
||||
* the initial ClientHello.
|
||||
* the initial ClientHello.legacy_version field.
|
||||
*
|
||||
* @s: client SSL handle.
|
||||
*
|
||||
@@ -1073,11 +2005,277 @@ int ssl_set_client_hello_version(SSL *s)
|
||||
{
|
||||
int ver_min, ver_max, ret;
|
||||
|
||||
ret = ssl_get_client_min_max_version(s, &ver_min, &ver_max);
|
||||
ret = ssl_get_min_max_version(s, &ver_min, &ver_max);
|
||||
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
s->client_version = s->version = ver_max;
|
||||
s->version = ver_max;
|
||||
|
||||
/* TLS1.3 always uses TLS1.2 in the legacy_version field */
|
||||
if (!SSL_IS_DTLS(s) && ver_max > TLS1_2_VERSION)
|
||||
ver_max = TLS1_2_VERSION;
|
||||
|
||||
s->client_version = ver_max;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks a list of |groups| to determine if the |group_id| is in it. If it is
|
||||
* and |checkallow| is 1 then additionally check if the group is allowed to be
|
||||
* used. Returns 1 if the group is in the list (and allowed if |checkallow| is
|
||||
* 1) or 0 otherwise.
|
||||
*/
|
||||
#ifndef OPENSSL_NO_EC
|
||||
int check_in_list(SSL *s, uint16_t group_id, const uint16_t *groups,
|
||||
size_t num_groups, int checkallow)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (groups == NULL || num_groups == 0)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < num_groups; i++) {
|
||||
uint16_t group = groups[i];
|
||||
|
||||
if (group_id == group
|
||||
&& (!checkallow
|
||||
|| tls_curve_allowed(s, group, SSL_SECOP_CURVE_CHECK))) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Replace ClientHello1 in the transcript hash with a synthetic message */
|
||||
int create_synthetic_message_hash(SSL *s, const unsigned char *hashval,
|
||||
size_t hashlen, const unsigned char *hrr,
|
||||
size_t hrrlen)
|
||||
{
|
||||
unsigned char hashvaltmp[EVP_MAX_MD_SIZE];
|
||||
unsigned char msghdr[SSL3_HM_HEADER_LENGTH];
|
||||
|
||||
memset(msghdr, 0, sizeof(msghdr));
|
||||
|
||||
if (hashval == NULL) {
|
||||
hashval = hashvaltmp;
|
||||
hashlen = 0;
|
||||
/* Get the hash of the initial ClientHello */
|
||||
if (!ssl3_digest_cached_records(s, 0)
|
||||
|| !ssl_handshake_hash(s, hashvaltmp, sizeof(hashvaltmp),
|
||||
&hashlen)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reinitialise the transcript hash */
|
||||
if (!ssl3_init_finished_mac(s)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Inject the synthetic message_hash message */
|
||||
msghdr[0] = SSL3_MT_MESSAGE_HASH;
|
||||
msghdr[SSL3_HM_HEADER_LENGTH - 1] = (unsigned char)hashlen;
|
||||
if (!ssl3_finish_mac(s, msghdr, SSL3_HM_HEADER_LENGTH)
|
||||
|| !ssl3_finish_mac(s, hashval, hashlen)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now re-inject the HRR and current message if appropriate (we just deleted
|
||||
* it when we reinitialised the transcript hash above). Only necessary after
|
||||
* receiving a ClientHello2 with a cookie.
|
||||
*/
|
||||
if (hrr != NULL
|
||||
&& (!ssl3_finish_mac(s, hrr, hrrlen)
|
||||
|| !ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
|
||||
s->s3->tmp.message_size
|
||||
+ SSL3_HM_HEADER_LENGTH))) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ca_dn_cmp(const X509_NAME *const *a, const X509_NAME *const *b)
|
||||
{
|
||||
return X509_NAME_cmp(*a, *b);
|
||||
}
|
||||
|
||||
int parse_ca_names(SSL *s, PACKET *pkt)
|
||||
{
|
||||
STACK_OF(X509_NAME) *ca_sk = sk_X509_NAME_new(ca_dn_cmp);
|
||||
X509_NAME *xn = NULL;
|
||||
PACKET cadns;
|
||||
|
||||
if (ca_sk == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_PARSE_CA_NAMES,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
/* get the CA RDNs */
|
||||
if (!PACKET_get_length_prefixed_2(pkt, &cadns)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,SSL_F_PARSE_CA_NAMES,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (PACKET_remaining(&cadns)) {
|
||||
const unsigned char *namestart, *namebytes;
|
||||
unsigned int name_len;
|
||||
|
||||
if (!PACKET_get_net_2(&cadns, &name_len)
|
||||
|| !PACKET_get_bytes(&cadns, &namebytes, name_len)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
namestart = namebytes;
|
||||
if ((xn = d2i_X509_NAME(NULL, &namebytes, name_len)) == NULL) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
|
||||
ERR_R_ASN1_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (namebytes != (namestart + name_len)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_PARSE_CA_NAMES,
|
||||
SSL_R_CA_DN_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!sk_X509_NAME_push(ca_sk, xn)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_PARSE_CA_NAMES,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
xn = NULL;
|
||||
}
|
||||
|
||||
sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free);
|
||||
s->s3->tmp.peer_ca_names = ca_sk;
|
||||
|
||||
return 1;
|
||||
|
||||
err:
|
||||
sk_X509_NAME_pop_free(ca_sk, X509_NAME_free);
|
||||
X509_NAME_free(xn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int construct_ca_names(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
const STACK_OF(X509_NAME) *ca_sk = SSL_get0_CA_list(s);
|
||||
|
||||
/* Start sub-packet for client CA list */
|
||||
if (!WPACKET_start_sub_packet_u16(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ca_sk != NULL) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sk_X509_NAME_num(ca_sk); i++) {
|
||||
unsigned char *namebytes;
|
||||
X509_NAME *name = sk_X509_NAME_value(ca_sk, i);
|
||||
int namelen;
|
||||
|
||||
if (name == NULL
|
||||
|| (namelen = i2d_X509_NAME(name, NULL)) < 0
|
||||
|| !WPACKET_sub_allocate_bytes_u16(pkt, namelen,
|
||||
&namebytes)
|
||||
|| i2d_X509_NAME(name, &namebytes) != namelen) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_CA_NAMES,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Create a buffer containing data to be signed for server key exchange */
|
||||
size_t construct_key_exchange_tbs(SSL *s, unsigned char **ptbs,
|
||||
const void *param, size_t paramlen)
|
||||
{
|
||||
size_t tbslen = 2 * SSL3_RANDOM_SIZE + paramlen;
|
||||
unsigned char *tbs = OPENSSL_malloc(tbslen);
|
||||
|
||||
if (tbs == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_KEY_EXCHANGE_TBS,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
memcpy(tbs, s->s3->client_random, SSL3_RANDOM_SIZE);
|
||||
memcpy(tbs + SSL3_RANDOM_SIZE, s->s3->server_random, SSL3_RANDOM_SIZE);
|
||||
|
||||
memcpy(tbs + SSL3_RANDOM_SIZE * 2, param, paramlen);
|
||||
|
||||
*ptbs = tbs;
|
||||
return tbslen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Saves the current handshake digest for Post-Handshake Auth,
|
||||
* Done after ClientFinished is processed, done exactly once
|
||||
*/
|
||||
int tls13_save_handshake_digest_for_pha(SSL *s)
|
||||
{
|
||||
if (s->pha_dgst == NULL) {
|
||||
if (!ssl3_digest_cached_records(s, 1))
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
|
||||
s->pha_dgst = EVP_MD_CTX_new();
|
||||
if (s->pha_dgst == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (!EVP_MD_CTX_copy_ex(s->pha_dgst,
|
||||
s->s3->handshake_dgst)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS13_SAVE_HANDSHAKE_DIGEST_FOR_PHA,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Restores the Post-Handshake Auth handshake digest
|
||||
* Done just before sending/processing the Cert Request
|
||||
*/
|
||||
int tls13_restore_handshake_digest_for_pha(SSL *s)
|
||||
{
|
||||
if (s->pha_dgst == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (!EVP_MD_CTX_copy_ex(s->s3->handshake_dgst,
|
||||
s->pha_dgst)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS13_RESTORE_HANDSHAKE_DIGEST_FOR_PHA,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
+323
-26
@@ -18,13 +18,25 @@
|
||||
|
||||
/* The spec allows for a longer length than this, but we limit it */
|
||||
#define HELLO_VERIFY_REQUEST_MAX_LENGTH 258
|
||||
#define END_OF_EARLY_DATA_MAX_LENGTH 0
|
||||
#define SERVER_HELLO_MAX_LENGTH 20000
|
||||
#define HELLO_RETRY_REQUEST_MAX_LENGTH 20000
|
||||
#define ENCRYPTED_EXTENSIONS_MAX_LENGTH 20000
|
||||
#define SERVER_KEY_EXCH_MAX_LENGTH 102400
|
||||
#define SERVER_HELLO_DONE_MAX_LENGTH 0
|
||||
#define KEY_UPDATE_MAX_LENGTH 1
|
||||
#define CCS_MAX_LENGTH 1
|
||||
/* Max should actually be 36 but we are generous */
|
||||
#define FINISHED_MAX_LENGTH 64
|
||||
|
||||
/* The maximum number of incoming KeyUpdate messages we will accept */
|
||||
#define MAX_KEY_UPDATE_MESSAGES 32
|
||||
|
||||
/* Dummy message type */
|
||||
#define SSL3_MT_DUMMY -1
|
||||
|
||||
extern const unsigned char hrrrandom[];
|
||||
|
||||
/* Message processing return codes */
|
||||
typedef enum {
|
||||
/* Something bad happened */
|
||||
@@ -40,9 +52,18 @@ typedef enum {
|
||||
MSG_PROCESS_CONTINUE_READING
|
||||
} MSG_PROCESS_RETURN;
|
||||
|
||||
/* Flush the write BIO */
|
||||
int statem_flush(SSL *s);
|
||||
typedef int (*confunc_f) (SSL *s, WPACKET *pkt);
|
||||
|
||||
int ssl3_take_mac(SSL *s);
|
||||
int check_in_list(SSL *s, uint16_t group_id, const uint16_t *groups,
|
||||
size_t num_groups, int checkallow);
|
||||
int create_synthetic_message_hash(SSL *s, const unsigned char *hashval,
|
||||
size_t hashlen, const unsigned char *hrr,
|
||||
size_t hrrlen);
|
||||
int parse_ca_names(SSL *s, PACKET *pkt);
|
||||
int construct_ca_names(SSL *s, WPACKET *pkt);
|
||||
size_t construct_key_exchange_tbs(SSL *s, unsigned char **ptbs,
|
||||
const void *param, size_t paramlen);
|
||||
|
||||
/*
|
||||
* TLS/DTLS client state machine functions
|
||||
@@ -51,8 +72,9 @@ int ossl_statem_client_read_transition(SSL *s, int mt);
|
||||
WRITE_TRAN ossl_statem_client_write_transition(SSL *s);
|
||||
WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst);
|
||||
WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst);
|
||||
int ossl_statem_client_construct_message(SSL *s);
|
||||
unsigned long ossl_statem_client_max_message_size(SSL *s);
|
||||
int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt,
|
||||
confunc_f *confunc, int *mt);
|
||||
size_t ossl_statem_client_max_message_size(SSL *s);
|
||||
MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt);
|
||||
WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst);
|
||||
|
||||
@@ -63,58 +85,66 @@ int ossl_statem_server_read_transition(SSL *s, int mt);
|
||||
WRITE_TRAN ossl_statem_server_write_transition(SSL *s);
|
||||
WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst);
|
||||
WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst);
|
||||
int ossl_statem_server_construct_message(SSL *s);
|
||||
unsigned long ossl_statem_server_max_message_size(SSL *s);
|
||||
int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt,
|
||||
confunc_f *confunc,int *mt);
|
||||
size_t ossl_statem_server_max_message_size(SSL *s);
|
||||
MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt);
|
||||
WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst);
|
||||
|
||||
/* Functions for getting new message data */
|
||||
__owur int tls_get_message_header(SSL *s, int *mt);
|
||||
__owur int tls_get_message_body(SSL *s, unsigned long *len);
|
||||
__owur int dtls_get_message(SSL *s, int *mt, unsigned long *len);
|
||||
__owur int tls_get_message_body(SSL *s, size_t *len);
|
||||
__owur int dtls_get_message(SSL *s, int *mt, size_t *len);
|
||||
|
||||
/* Message construction and processing functions */
|
||||
__owur int tls_process_initial_server_flight(SSL *s);
|
||||
__owur MSG_PROCESS_RETURN tls_process_change_cipher_spec(SSL *s, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt);
|
||||
__owur int tls_construct_change_cipher_spec(SSL *s);
|
||||
__owur int dtls_construct_change_cipher_spec(SSL *s);
|
||||
__owur int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt);
|
||||
__owur int dtls_construct_change_cipher_spec(SSL *s, WPACKET *pkt);
|
||||
|
||||
__owur int tls_construct_finished(SSL *s, const char *sender, int slen);
|
||||
__owur WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst);
|
||||
__owur int tls_construct_finished(SSL *s, WPACKET *pkt);
|
||||
__owur int tls_construct_key_update(SSL *s, WPACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_key_update(SSL *s, PACKET *pkt);
|
||||
__owur WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs,
|
||||
int stop);
|
||||
__owur WORK_STATE dtls_wait_for_dry(SSL *s);
|
||||
|
||||
/* some client-only functions */
|
||||
__owur int tls_construct_client_hello(SSL *s);
|
||||
__owur int tls_construct_client_hello(SSL *s, WPACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt);
|
||||
__owur int tls_process_cert_status_body(SSL *s, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt);
|
||||
__owur int tls_construct_client_verify(SSL *s);
|
||||
__owur int tls_construct_cert_verify(SSL *s, WPACKET *pkt);
|
||||
__owur WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst);
|
||||
__owur int tls_construct_client_certificate(SSL *s);
|
||||
__owur int tls_construct_client_certificate(SSL *s, WPACKET *pkt);
|
||||
__owur int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey);
|
||||
__owur int tls_construct_client_key_exchange(SSL *s);
|
||||
__owur int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt);
|
||||
__owur int tls_client_key_exchange_post_work(SSL *s);
|
||||
__owur int tls_construct_cert_status(SSL *s);
|
||||
__owur int tls_construct_cert_status_body(SSL *s, WPACKET *pkt);
|
||||
__owur int tls_construct_cert_status(SSL *s, WPACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt);
|
||||
__owur int ssl3_check_cert_and_algorithm(SSL *s);
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
__owur int tls_construct_next_proto(SSL *s);
|
||||
__owur int tls_construct_next_proto(SSL *s, WPACKET *pkt);
|
||||
#endif
|
||||
__owur MSG_PROCESS_RETURN tls_process_hello_req(SSL *s, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt);
|
||||
__owur int tls_construct_end_of_early_data(SSL *s, WPACKET *pkt);
|
||||
|
||||
/* some server-only functions */
|
||||
__owur MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt);
|
||||
__owur WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst);
|
||||
__owur int tls_construct_server_hello(SSL *s);
|
||||
__owur int tls_construct_hello_request(SSL *s);
|
||||
__owur int dtls_construct_hello_verify_request(SSL *s);
|
||||
__owur int tls_construct_server_certificate(SSL *s);
|
||||
__owur int tls_construct_server_key_exchange(SSL *s);
|
||||
__owur int tls_construct_certificate_request(SSL *s);
|
||||
__owur int tls_construct_server_done(SSL *s);
|
||||
__owur int tls_construct_server_hello(SSL *s, WPACKET *pkt);
|
||||
__owur int dtls_construct_hello_verify_request(SSL *s, WPACKET *pkt);
|
||||
__owur int tls_construct_server_certificate(SSL *s, WPACKET *pkt);
|
||||
__owur int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt);
|
||||
__owur int tls_construct_certificate_request(SSL *s, WPACKET *pkt);
|
||||
__owur int tls_construct_server_done(SSL *s, WPACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt);
|
||||
__owur MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt);
|
||||
__owur WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst);
|
||||
@@ -122,4 +152,271 @@ __owur MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt);
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
__owur MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt);
|
||||
#endif
|
||||
__owur int tls_construct_new_session_ticket(SSL *s);
|
||||
__owur int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt);
|
||||
MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt);
|
||||
|
||||
|
||||
/* Extension processing */
|
||||
|
||||
typedef enum ext_return_en {
|
||||
EXT_RETURN_FAIL,
|
||||
EXT_RETURN_SENT,
|
||||
EXT_RETURN_NOT_SENT
|
||||
} EXT_RETURN;
|
||||
|
||||
__owur int tls_validate_all_contexts(SSL *s, unsigned int thisctx,
|
||||
RAW_EXTENSION *exts);
|
||||
__owur int extension_is_relevant(SSL *s, unsigned int extctx,
|
||||
unsigned int thisctx);
|
||||
__owur int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
|
||||
RAW_EXTENSION **res, size_t *len, int init);
|
||||
__owur int tls_parse_extension(SSL *s, TLSEXT_INDEX idx, int context,
|
||||
RAW_EXTENSION *exts, X509 *x, size_t chainidx);
|
||||
__owur int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts,
|
||||
X509 *x, size_t chainidx, int fin);
|
||||
__owur int should_add_extension(SSL *s, unsigned int extctx,
|
||||
unsigned int thisctx, int max_version);
|
||||
__owur int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
|
||||
__owur int tls_psk_do_binder(SSL *s, const EVP_MD *md,
|
||||
const unsigned char *msgstart,
|
||||
size_t binderoffset, const unsigned char *binderin,
|
||||
unsigned char *binderout,
|
||||
SSL_SESSION *sess, int sign, int external);
|
||||
|
||||
/* Server Extension processing */
|
||||
int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_EC
|
||||
int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidxl);
|
||||
#endif
|
||||
int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_ctos_sig_algs_cert(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
int tls_parse_ctos_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
int tls_parse_ctos_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_ctos_post_handshake_auth(SSL *, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
|
||||
EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#ifndef OPENSSL_NO_EC
|
||||
EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
EXT_RETURN tls_construct_stoc_alpn(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
EXT_RETURN tls_construct_stoc_use_srtp(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#endif
|
||||
EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
/*
|
||||
* Not in public headers as this is not an official extension. Only used when
|
||||
* SSL_OP_CRYPTOPRO_TLSEXT_BUG is set.
|
||||
*/
|
||||
#define TLSEXT_TYPE_cryptopro_bug 0xfde8
|
||||
EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
|
||||
/* Client Extension processing */
|
||||
EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_EC
|
||||
EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_sig_algs(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
EXT_RETURN tls_construct_ctos_npn(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#endif
|
||||
EXT_RETURN tls_construct_ctos_alpn(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#endif
|
||||
EXT_RETURN tls_construct_ctos_etm(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_CT
|
||||
EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#endif
|
||||
EXT_RETURN tls_construct_ctos_ems(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_cookie(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt,
|
||||
unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
|
||||
int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_EC
|
||||
int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#endif
|
||||
int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#ifndef OPENSSL_NO_OCSP
|
||||
int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_CT
|
||||
int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#ifndef OPENSSL_NO_SRTP
|
||||
int tls_parse_stoc_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
#endif
|
||||
int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context,
|
||||
X509 *x, size_t chainidx);
|
||||
int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||
size_t chainidx);
|
||||
|
||||
int tls_handle_alpn(SSL *s);
|
||||
|
||||
int tls13_save_handshake_digest_for_pha(SSL *s);
|
||||
int tls13_restore_handshake_digest_for_pha(SSL *s);
|
||||
+2076
-1401
@@ -1,5 +1,7 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
|
||||
* Copyright 2005 Nokia. All rights reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
@@ -7,50 +9,11 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/* ====================================================================
|
||||
* Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* Portions of the attached software ("Contribution") are developed by
|
||||
* SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
|
||||
*
|
||||
* The Contribution is licensed pursuant to the OpenSSL open source
|
||||
* license provided above.
|
||||
*
|
||||
* ECC cipher suite support in OpenSSL originally written by
|
||||
* Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
|
||||
*
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright 2005 Nokia. All rights reserved.
|
||||
*
|
||||
* The portions of the attached software ("Contribution") is developed by
|
||||
* Nokia Corporation and is licensed pursuant to the OpenSSL open source
|
||||
* license.
|
||||
*
|
||||
* The Contribution, originally written by Mika Kousa and Pasi Eronen of
|
||||
* Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
|
||||
* support (see RFC 4279) to OpenSSL.
|
||||
*
|
||||
* No patent licenses or other rights except those expressly stated in
|
||||
* the OpenSSL open source license shall be deemed granted or received
|
||||
* expressly, by implication, estoppel, or otherwise.
|
||||
*
|
||||
* No assurances are provided by Nokia that the Contribution does not
|
||||
* infringe the patent or other intellectual property rights of any third
|
||||
* party or that the license provides you with all the necessary rights
|
||||
* to make use of the Contribution.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
|
||||
* ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
|
||||
* SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
|
||||
* OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
|
||||
* OTHERWISE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "../ssl_locl.h"
|
||||
#include "statem_locl.h"
|
||||
#include "internal/constant_time_locl.h"
|
||||
#include "internal/cryptlib.h"
|
||||
#include <openssl/buffer.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/objects.h>
|
||||
@@ -61,28 +24,132 @@
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/md5.h>
|
||||
|
||||
static STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,
|
||||
PACKET *cipher_suites,
|
||||
STACK_OF(SSL_CIPHER)
|
||||
**skp, int sslv2format,
|
||||
int *al);
|
||||
static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt);
|
||||
|
||||
/*
|
||||
* server_read_transition() encapsulates the logic for the allowed handshake
|
||||
* state transitions when the server is reading messages from the client. The
|
||||
* message type that the client has sent is provided in |mt|. The current state
|
||||
* is in |s->statem.hand_state|.
|
||||
* ossl_statem_server13_read_transition() encapsulates the logic for the allowed
|
||||
* handshake state transitions when a TLSv1.3 server is reading messages from
|
||||
* the client. The message type that the client has sent is provided in |mt|.
|
||||
* The current state is in |s->statem.hand_state|.
|
||||
*
|
||||
* Valid return values are:
|
||||
* 1: Success (transition allowed)
|
||||
* 0: Error (transition not allowed)
|
||||
* Return values are 1 for success (transition allowed) and 0 on error
|
||||
* (transition not allowed)
|
||||
*/
|
||||
static int ossl_statem_server13_read_transition(SSL *s, int mt)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
/*
|
||||
* Note: There is no case for TLS_ST_BEFORE because at that stage we have
|
||||
* not negotiated TLSv1.3 yet, so that case is handled by
|
||||
* ossl_statem_server_read_transition()
|
||||
*/
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case TLS_ST_EARLY_DATA:
|
||||
if (s->hello_retry_request == SSL_HRR_PENDING) {
|
||||
if (mt == SSL3_MT_CLIENT_HELLO) {
|
||||
st->hand_state = TLS_ST_SR_CLNT_HELLO;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
} else if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
|
||||
if (mt == SSL3_MT_END_OF_EARLY_DATA) {
|
||||
st->hand_state = TLS_ST_SR_END_OF_EARLY_DATA;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
|
||||
case TLS_ST_SR_END_OF_EARLY_DATA:
|
||||
case TLS_ST_SW_FINISHED:
|
||||
if (s->s3->tmp.cert_request) {
|
||||
if (mt == SSL3_MT_CERTIFICATE) {
|
||||
st->hand_state = TLS_ST_SR_CERT;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (mt == SSL3_MT_FINISHED) {
|
||||
st->hand_state = TLS_ST_SR_FINISHED;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TLS_ST_SR_CERT:
|
||||
if (s->session->peer == NULL) {
|
||||
if (mt == SSL3_MT_FINISHED) {
|
||||
st->hand_state = TLS_ST_SR_FINISHED;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (mt == SSL3_MT_CERTIFICATE_VERIFY) {
|
||||
st->hand_state = TLS_ST_SR_CERT_VRFY;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TLS_ST_SR_CERT_VRFY:
|
||||
if (mt == SSL3_MT_FINISHED) {
|
||||
st->hand_state = TLS_ST_SR_FINISHED;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case TLS_ST_OK:
|
||||
/*
|
||||
* Its never ok to start processing handshake messages in the middle of
|
||||
* early data (i.e. before we've received the end of early data alert)
|
||||
*/
|
||||
if (s->early_data_state == SSL_EARLY_DATA_READING)
|
||||
break;
|
||||
|
||||
if (mt == SSL3_MT_CERTIFICATE
|
||||
&& s->post_handshake_auth == SSL_PHA_REQUESTED) {
|
||||
st->hand_state = TLS_ST_SR_CERT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mt == SSL3_MT_KEY_UPDATE) {
|
||||
st->hand_state = TLS_ST_SR_KEY_UPDATE;
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* No valid transition found */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ossl_statem_server_read_transition() encapsulates the logic for the allowed
|
||||
* handshake state transitions when the server is reading messages from the
|
||||
* client. The message type that the client has sent is provided in |mt|. The
|
||||
* current state is in |s->statem.hand_state|.
|
||||
*
|
||||
* Return values are 1 for success (transition allowed) and 0 on error
|
||||
* (transition not allowed)
|
||||
*/
|
||||
int ossl_statem_server_read_transition(SSL *s, int mt)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
if (!ossl_statem_server13_read_transition(s, mt))
|
||||
goto err;
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case TLS_ST_BEFORE:
|
||||
case TLS_ST_OK:
|
||||
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
|
||||
if (mt == SSL3_MT_CLIENT_HELLO) {
|
||||
st->hand_state = TLS_ST_SR_CLNT_HELLO;
|
||||
@@ -111,10 +178,9 @@ int ossl_statem_server_read_transition(SSL *s, int mt)
|
||||
* not going to accept it because we require a client
|
||||
* cert.
|
||||
*/
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL,
|
||||
SSL3_AD_HANDSHAKE_FAILURE);
|
||||
SSLerr(SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
|
||||
SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
|
||||
SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
|
||||
return 0;
|
||||
}
|
||||
st->hand_state = TLS_ST_SR_KEY_EXCH;
|
||||
@@ -176,7 +242,7 @@ int ossl_statem_server_read_transition(SSL *s, int mt)
|
||||
|
||||
case TLS_ST_SR_CHANGE:
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
if (s->s3->next_proto_neg_seen) {
|
||||
if (s->s3->npn_seen) {
|
||||
if (mt == SSL3_MT_NEXT_PROTO) {
|
||||
st->hand_state = TLS_ST_SR_NEXT_PROTO;
|
||||
return 1;
|
||||
@@ -207,14 +273,13 @@ int ossl_statem_server_read_transition(SSL *s, int mt)
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
err:
|
||||
/* No valid transition found */
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, SSL3_AD_UNEXPECTED_MESSAGE);
|
||||
SSLerr(SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION, SSL_R_UNEXPECTED_MESSAGE);
|
||||
SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE,
|
||||
SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
|
||||
SSL_R_UNEXPECTED_MESSAGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -267,16 +332,22 @@ static int send_server_key_exchange(SSL *s)
|
||||
* 1: Yes
|
||||
* 0: No
|
||||
*/
|
||||
static int send_certificate_request(SSL *s)
|
||||
int send_certificate_request(SSL *s)
|
||||
{
|
||||
if (
|
||||
/* don't request cert unless asked for it: */
|
||||
s->verify_mode & SSL_VERIFY_PEER
|
||||
/*
|
||||
* if SSL_VERIFY_CLIENT_ONCE is set, don't request cert
|
||||
* during re-negotiation:
|
||||
* don't request if post-handshake-only unless doing
|
||||
* post-handshake in TLSv1.3:
|
||||
*/
|
||||
&& (s->s3->tmp.finish_md_len == 0 ||
|
||||
&& (!SSL_IS_TLS13(s) || !(s->verify_mode & SSL_VERIFY_POST_HANDSHAKE)
|
||||
|| s->post_handshake_auth == SSL_PHA_REQUEST_PENDING)
|
||||
/*
|
||||
* if SSL_VERIFY_CLIENT_ONCE is set, don't request cert
|
||||
* a second time:
|
||||
*/
|
||||
&& (s->certreqs_sent < 1 ||
|
||||
!(s->verify_mode & SSL_VERIFY_CLIENT_ONCE))
|
||||
/*
|
||||
* never request cert in anonymous ciphersuites (see
|
||||
@@ -304,34 +375,179 @@ static int send_certificate_request(SSL *s)
|
||||
}
|
||||
|
||||
/*
|
||||
* server_write_transition() works out what handshake state to move to next
|
||||
* when the server is writing messages to be sent to the client.
|
||||
* ossl_statem_server13_write_transition() works out what handshake state to
|
||||
* move to next when a TLSv1.3 server is writing messages to be sent to the
|
||||
* client.
|
||||
*/
|
||||
static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
/*
|
||||
* No case for TLS_ST_BEFORE, because at that stage we have not negotiated
|
||||
* TLSv1.3 yet, so that is handled by ossl_statem_server_write_transition()
|
||||
*/
|
||||
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return WRITE_TRAN_ERROR;
|
||||
|
||||
case TLS_ST_OK:
|
||||
if (s->key_update != SSL_KEY_UPDATE_NONE) {
|
||||
st->hand_state = TLS_ST_SW_KEY_UPDATE;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
}
|
||||
if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
|
||||
st->hand_state = TLS_ST_SW_CERT_REQ;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
}
|
||||
/* Try to read from the client instead */
|
||||
return WRITE_TRAN_FINISHED;
|
||||
|
||||
case TLS_ST_SR_CLNT_HELLO:
|
||||
st->hand_state = TLS_ST_SW_SRVR_HELLO;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_SW_SRVR_HELLO:
|
||||
if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
|
||||
&& s->hello_retry_request != SSL_HRR_COMPLETE)
|
||||
st->hand_state = TLS_ST_SW_CHANGE;
|
||||
else if (s->hello_retry_request == SSL_HRR_PENDING)
|
||||
st->hand_state = TLS_ST_EARLY_DATA;
|
||||
else
|
||||
st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_SW_CHANGE:
|
||||
if (s->hello_retry_request == SSL_HRR_PENDING)
|
||||
st->hand_state = TLS_ST_EARLY_DATA;
|
||||
else
|
||||
st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_SW_ENCRYPTED_EXTENSIONS:
|
||||
if (s->hit)
|
||||
st->hand_state = TLS_ST_SW_FINISHED;
|
||||
else if (send_certificate_request(s))
|
||||
st->hand_state = TLS_ST_SW_CERT_REQ;
|
||||
else
|
||||
st->hand_state = TLS_ST_SW_CERT;
|
||||
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_SW_CERT_REQ:
|
||||
if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
|
||||
s->post_handshake_auth = SSL_PHA_REQUESTED;
|
||||
st->hand_state = TLS_ST_OK;
|
||||
} else {
|
||||
st->hand_state = TLS_ST_SW_CERT;
|
||||
}
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_SW_CERT:
|
||||
st->hand_state = TLS_ST_SW_CERT_VRFY;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_SW_CERT_VRFY:
|
||||
st->hand_state = TLS_ST_SW_FINISHED;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_SW_FINISHED:
|
||||
st->hand_state = TLS_ST_EARLY_DATA;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_EARLY_DATA:
|
||||
return WRITE_TRAN_FINISHED;
|
||||
|
||||
case TLS_ST_SR_FINISHED:
|
||||
/*
|
||||
* Technically we have finished the handshake at this point, but we're
|
||||
* going to remain "in_init" for now and write out the session ticket
|
||||
* immediately.
|
||||
* TODO(TLS1.3): Perhaps we need to be able to control this behaviour
|
||||
* and give the application the opportunity to delay sending the
|
||||
* session ticket?
|
||||
*/
|
||||
if (s->post_handshake_auth == SSL_PHA_REQUESTED)
|
||||
s->post_handshake_auth = SSL_PHA_EXT_RECEIVED;
|
||||
st->hand_state = TLS_ST_SW_SESSION_TICKET;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_SR_KEY_UPDATE:
|
||||
if (s->key_update != SSL_KEY_UPDATE_NONE) {
|
||||
st->hand_state = TLS_ST_SW_KEY_UPDATE;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
}
|
||||
/* Fall through */
|
||||
|
||||
case TLS_ST_SW_KEY_UPDATE:
|
||||
case TLS_ST_SW_SESSION_TICKET:
|
||||
st->hand_state = TLS_ST_OK;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ossl_statem_server_write_transition() works out what handshake state to move
|
||||
* to next when the server is writing messages to be sent to the client.
|
||||
*/
|
||||
WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
/*
|
||||
* Note that before the ClientHello we don't know what version we are going
|
||||
* to negotiate yet, so we don't take this branch until later
|
||||
*/
|
||||
|
||||
if (SSL_IS_TLS13(s))
|
||||
return ossl_statem_server13_write_transition(s);
|
||||
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return WRITE_TRAN_ERROR;
|
||||
|
||||
case TLS_ST_OK:
|
||||
if (st->request_state == TLS_ST_SW_HELLO_REQ) {
|
||||
/* We must be trying to renegotiate */
|
||||
st->hand_state = TLS_ST_SW_HELLO_REQ;
|
||||
st->request_state = TLS_ST_BEFORE;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
}
|
||||
/* Must be an incoming ClientHello */
|
||||
if (!tls_setup_handshake(s)) {
|
||||
/* SSLfatal() already called */
|
||||
return WRITE_TRAN_ERROR;
|
||||
}
|
||||
/* Fall through */
|
||||
|
||||
case TLS_ST_BEFORE:
|
||||
/* Just go straight to trying to read from the client */
|
||||
return WRITE_TRAN_FINISHED;
|
||||
|
||||
case TLS_ST_OK:
|
||||
/* We must be trying to renegotiate */
|
||||
st->hand_state = TLS_ST_SW_HELLO_REQ;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_SW_HELLO_REQ:
|
||||
st->hand_state = TLS_ST_OK;
|
||||
ossl_statem_set_in_init(s, 0);
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_SR_CLNT_HELLO:
|
||||
if (SSL_IS_DTLS(s) && !s->d1->cookie_verified
|
||||
&& (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE))
|
||||
&& (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) {
|
||||
st->hand_state = DTLS_ST_SW_HELLO_VERIFY_REQUEST;
|
||||
else
|
||||
} else if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) {
|
||||
/* We must have rejected the renegotiation */
|
||||
st->hand_state = TLS_ST_OK;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
} else {
|
||||
st->hand_state = TLS_ST_SW_SRVR_HELLO;
|
||||
}
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
|
||||
@@ -339,7 +555,7 @@ WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
|
||||
|
||||
case TLS_ST_SW_SRVR_HELLO:
|
||||
if (s->hit) {
|
||||
if (s->tlsext_ticket_expected)
|
||||
if (s->ext.ticket_expected)
|
||||
st->hand_state = TLS_ST_SW_SESSION_TICKET;
|
||||
else
|
||||
st->hand_state = TLS_ST_SW_CHANGE;
|
||||
@@ -360,7 +576,7 @@ WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_SW_CERT:
|
||||
if (s->tlsext_status_expected) {
|
||||
if (s->ext.status_expected) {
|
||||
st->hand_state = TLS_ST_SW_CERT_STATUS;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
}
|
||||
@@ -390,9 +606,8 @@ WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
|
||||
case TLS_ST_SR_FINISHED:
|
||||
if (s->hit) {
|
||||
st->hand_state = TLS_ST_OK;
|
||||
ossl_statem_set_in_init(s, 0);
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
} else if (s->tlsext_ticket_expected) {
|
||||
} else if (s->ext.ticket_expected) {
|
||||
st->hand_state = TLS_ST_SW_SESSION_TICKET;
|
||||
} else {
|
||||
st->hand_state = TLS_ST_SW_CHANGE;
|
||||
@@ -412,12 +627,7 @@ WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
|
||||
return WRITE_TRAN_FINISHED;
|
||||
}
|
||||
st->hand_state = TLS_ST_OK;
|
||||
ossl_statem_set_in_init(s, 0);
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
return WRITE_TRAN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -430,6 +640,10 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
/* No pre work to be done */
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_HELLO_REQ:
|
||||
s->shutdown = 0;
|
||||
if (SSL_IS_DTLS(s))
|
||||
@@ -457,13 +671,24 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
|
||||
|
||||
case TLS_ST_SW_SRVR_DONE:
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s)))
|
||||
if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
|
||||
/* Calls SSLfatal() as required */
|
||||
return dtls_wait_for_dry(s);
|
||||
}
|
||||
#endif
|
||||
return WORK_FINISHED_CONTINUE;
|
||||
|
||||
case TLS_ST_SW_SESSION_TICKET:
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
/*
|
||||
* Actually this is the end of the handshake, but we're going
|
||||
* straight into writing the session ticket out. So we finish off
|
||||
* the handshake, but keep the various buffers active.
|
||||
*
|
||||
* Calls SSLfatal as required.
|
||||
*/
|
||||
return tls_finish_handshake(s, wst, 0, 0);
|
||||
} if (SSL_IS_DTLS(s)) {
|
||||
/*
|
||||
* We're into the last flight. We don't retransmit the last flight
|
||||
* unless we need to, so we don't use the timer
|
||||
@@ -473,9 +698,11 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_CHANGE:
|
||||
if (SSL_IS_TLS13(s))
|
||||
break;
|
||||
s->session->cipher = s->s3->tmp.new_cipher;
|
||||
if (!s->method->ssl3_enc->setup_key_block(s)) {
|
||||
ossl_statem_set_error(s);
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
@@ -489,12 +716,15 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
|
||||
}
|
||||
return WORK_FINISHED_CONTINUE;
|
||||
|
||||
case TLS_ST_OK:
|
||||
return tls_finish_handshake(s, wst);
|
||||
case TLS_ST_EARLY_DATA:
|
||||
if (s->early_data_state != SSL_EARLY_DATA_ACCEPTING
|
||||
&& (s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
|
||||
return WORK_FINISHED_CONTINUE;
|
||||
/* Fall through */
|
||||
|
||||
default:
|
||||
/* No pre work to be done */
|
||||
break;
|
||||
case TLS_ST_OK:
|
||||
/* Calls SSLfatal() as required */
|
||||
return tls_finish_handshake(s, wst, 1, 1);
|
||||
}
|
||||
|
||||
return WORK_FINISHED_CONTINUE;
|
||||
@@ -511,11 +741,15 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
|
||||
s->init_num = 0;
|
||||
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
/* No post work to be done */
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_HELLO_REQ:
|
||||
if (statem_flush(s) != 1)
|
||||
return WORK_MORE_A;
|
||||
if (!ssl3_init_finished_mac(s)) {
|
||||
ossl_statem_set_error(s);
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
break;
|
||||
@@ -525,7 +759,7 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
|
||||
return WORK_MORE_A;
|
||||
/* HelloVerifyRequest resets Finished MAC */
|
||||
if (s->version != DTLS1_BAD_VER && !ssl3_init_finished_mac(s)) {
|
||||
ossl_statem_set_error(s);
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
/*
|
||||
@@ -536,6 +770,12 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_SRVR_HELLO:
|
||||
if (SSL_IS_TLS13(s) && s->hello_retry_request == SSL_HRR_PENDING) {
|
||||
if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0
|
||||
&& statem_flush(s) != 1)
|
||||
return WORK_MORE_A;
|
||||
break;
|
||||
}
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
if (SSL_IS_DTLS(s) && s->hit) {
|
||||
unsigned char sctpauthkey[64];
|
||||
@@ -552,7 +792,9 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
|
||||
sizeof(sctpauthkey), labelbuffer,
|
||||
sizeof(labelbuffer), NULL, 0,
|
||||
0) <= 0) {
|
||||
ossl_statem_set_error(s);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_OSSL_STATEM_SERVER_POST_WORK,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return WORK_ERROR;
|
||||
}
|
||||
|
||||
@@ -560,9 +802,41 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
|
||||
sizeof(sctpauthkey), sctpauthkey);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
if (!SSL_IS_TLS13(s)
|
||||
|| ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
|
||||
&& s->hello_retry_request != SSL_HRR_COMPLETE))
|
||||
break;
|
||||
/* Fall through */
|
||||
|
||||
case TLS_ST_SW_CHANGE:
|
||||
if (s->hello_retry_request == SSL_HRR_PENDING) {
|
||||
if (!statem_flush(s))
|
||||
return WORK_MORE_A;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* TODO(TLS1.3): This actually causes a problem. We don't yet know
|
||||
* whether the next record we are going to receive is an unencrypted
|
||||
* alert, or an encrypted handshake message. We're going to need
|
||||
* something clever in the record layer for this.
|
||||
*/
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
if (!s->method->ssl3_enc->setup_key_block(s)
|
||||
|| !s->method->ssl3_enc->change_cipher_state(s,
|
||||
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
|
||||
if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED
|
||||
&& !s->method->ssl3_enc->change_cipher_state(s,
|
||||
SSL3_CC_HANDSHAKE |SSL3_CHANGE_CIPHER_SERVER_READ)) {
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_SCTP
|
||||
if (SSL_IS_DTLS(s) && !s->hit) {
|
||||
/*
|
||||
@@ -576,7 +850,7 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
|
||||
if (!s->method->ssl3_enc->change_cipher_state(s,
|
||||
SSL3_CHANGE_CIPHER_SERVER_WRITE))
|
||||
{
|
||||
ossl_statem_set_error(s);
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
|
||||
@@ -602,10 +876,36 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
|
||||
0, NULL);
|
||||
}
|
||||
#endif
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
if (!s->method->ssl3_enc->generate_master_secret(s,
|
||||
s->master_secret, s->handshake_secret, 0,
|
||||
&s->session->master_key_length)
|
||||
|| !s->method->ssl3_enc->change_cipher_state(s,
|
||||
SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_WRITE))
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* No post work to be done */
|
||||
case TLS_ST_SW_CERT_REQ:
|
||||
if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
|
||||
if (statem_flush(s) != 1)
|
||||
return WORK_MORE_A;
|
||||
}
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_KEY_UPDATE:
|
||||
if (statem_flush(s) != 1)
|
||||
return WORK_MORE_A;
|
||||
if (!tls13_update_key(s, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_SESSION_TICKET:
|
||||
if (SSL_IS_TLS13(s) && statem_flush(s) != 1)
|
||||
return WORK_MORE_A;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -613,63 +913,108 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a message to be sent from the server to the client.
|
||||
* Get the message construction function and message type for sending from the
|
||||
* server
|
||||
*
|
||||
* Valid return values are:
|
||||
* 1: Success
|
||||
* 0: Error
|
||||
*/
|
||||
int ossl_statem_server_construct_message(SSL *s)
|
||||
int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt,
|
||||
confunc_f *confunc, int *mt)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
switch (st->hand_state) {
|
||||
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
|
||||
return dtls_construct_hello_verify_request(s);
|
||||
|
||||
case TLS_ST_SW_HELLO_REQ:
|
||||
return tls_construct_hello_request(s);
|
||||
|
||||
case TLS_ST_SW_SRVR_HELLO:
|
||||
return tls_construct_server_hello(s);
|
||||
|
||||
case TLS_ST_SW_CERT:
|
||||
return tls_construct_server_certificate(s);
|
||||
|
||||
case TLS_ST_SW_KEY_EXCH:
|
||||
return tls_construct_server_key_exchange(s);
|
||||
|
||||
case TLS_ST_SW_CERT_REQ:
|
||||
return tls_construct_certificate_request(s);
|
||||
|
||||
case TLS_ST_SW_SRVR_DONE:
|
||||
return tls_construct_server_done(s);
|
||||
|
||||
case TLS_ST_SW_SESSION_TICKET:
|
||||
return tls_construct_new_session_ticket(s);
|
||||
|
||||
case TLS_ST_SW_CERT_STATUS:
|
||||
return tls_construct_cert_status(s);
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE,
|
||||
SSL_R_BAD_HANDSHAKE_STATE);
|
||||
return 0;
|
||||
|
||||
case TLS_ST_SW_CHANGE:
|
||||
if (SSL_IS_DTLS(s))
|
||||
return dtls_construct_change_cipher_spec(s);
|
||||
*confunc = dtls_construct_change_cipher_spec;
|
||||
else
|
||||
return tls_construct_change_cipher_spec(s);
|
||||
*confunc = tls_construct_change_cipher_spec;
|
||||
*mt = SSL3_MT_CHANGE_CIPHER_SPEC;
|
||||
break;
|
||||
|
||||
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
|
||||
*confunc = dtls_construct_hello_verify_request;
|
||||
*mt = DTLS1_MT_HELLO_VERIFY_REQUEST;
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_HELLO_REQ:
|
||||
/* No construction function needed */
|
||||
*confunc = NULL;
|
||||
*mt = SSL3_MT_HELLO_REQUEST;
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_SRVR_HELLO:
|
||||
*confunc = tls_construct_server_hello;
|
||||
*mt = SSL3_MT_SERVER_HELLO;
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_CERT:
|
||||
*confunc = tls_construct_server_certificate;
|
||||
*mt = SSL3_MT_CERTIFICATE;
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_CERT_VRFY:
|
||||
*confunc = tls_construct_cert_verify;
|
||||
*mt = SSL3_MT_CERTIFICATE_VERIFY;
|
||||
break;
|
||||
|
||||
|
||||
case TLS_ST_SW_KEY_EXCH:
|
||||
*confunc = tls_construct_server_key_exchange;
|
||||
*mt = SSL3_MT_SERVER_KEY_EXCHANGE;
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_CERT_REQ:
|
||||
*confunc = tls_construct_certificate_request;
|
||||
*mt = SSL3_MT_CERTIFICATE_REQUEST;
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_SRVR_DONE:
|
||||
*confunc = tls_construct_server_done;
|
||||
*mt = SSL3_MT_SERVER_DONE;
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_SESSION_TICKET:
|
||||
*confunc = tls_construct_new_session_ticket;
|
||||
*mt = SSL3_MT_NEWSESSION_TICKET;
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_CERT_STATUS:
|
||||
*confunc = tls_construct_cert_status;
|
||||
*mt = SSL3_MT_CERTIFICATE_STATUS;
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_FINISHED:
|
||||
return tls_construct_finished(s,
|
||||
s->method->
|
||||
ssl3_enc->server_finished_label,
|
||||
s->method->
|
||||
ssl3_enc->server_finished_label_len);
|
||||
*confunc = tls_construct_finished;
|
||||
*mt = SSL3_MT_FINISHED;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
case TLS_ST_EARLY_DATA:
|
||||
*confunc = NULL;
|
||||
*mt = SSL3_MT_DUMMY;
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_ENCRYPTED_EXTENSIONS:
|
||||
*confunc = tls_construct_encrypted_extensions;
|
||||
*mt = SSL3_MT_ENCRYPTED_EXTENSIONS;
|
||||
break;
|
||||
|
||||
case TLS_ST_SW_KEY_UPDATE:
|
||||
*confunc = tls_construct_key_update;
|
||||
*mt = SSL3_MT_KEY_UPDATE;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -696,14 +1041,21 @@ int ossl_statem_server_construct_message(SSL *s)
|
||||
* Returns the maximum allowed length for the current message that we are
|
||||
* reading. Excludes the message header.
|
||||
*/
|
||||
unsigned long ossl_statem_server_max_message_size(SSL *s)
|
||||
size_t ossl_statem_server_max_message_size(SSL *s)
|
||||
{
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
return 0;
|
||||
|
||||
case TLS_ST_SR_CLNT_HELLO:
|
||||
return CLIENT_HELLO_MAX_LENGTH;
|
||||
|
||||
case TLS_ST_SR_END_OF_EARLY_DATA:
|
||||
return END_OF_EARLY_DATA_MAX_LENGTH;
|
||||
|
||||
case TLS_ST_SR_CERT:
|
||||
return s->max_cert_list;
|
||||
|
||||
@@ -724,12 +1076,9 @@ unsigned long ossl_statem_server_max_message_size(SSL *s)
|
||||
case TLS_ST_SR_FINISHED:
|
||||
return FINISHED_MAX_LENGTH;
|
||||
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
break;
|
||||
case TLS_ST_SR_KEY_UPDATE:
|
||||
return KEY_UPDATE_MAX_LENGTH;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -740,9 +1089,19 @@ MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt)
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return MSG_PROCESS_ERROR;
|
||||
|
||||
case TLS_ST_SR_CLNT_HELLO:
|
||||
return tls_process_client_hello(s, pkt);
|
||||
|
||||
case TLS_ST_SR_END_OF_EARLY_DATA:
|
||||
return tls_process_end_of_early_data(s, pkt);
|
||||
|
||||
case TLS_ST_SR_CERT:
|
||||
return tls_process_client_certificate(s, pkt);
|
||||
|
||||
@@ -763,12 +1122,10 @@ MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt)
|
||||
case TLS_ST_SR_FINISHED:
|
||||
return tls_process_finished(s, pkt);
|
||||
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
break;
|
||||
}
|
||||
case TLS_ST_SR_KEY_UPDATE:
|
||||
return tls_process_key_update(s, pkt);
|
||||
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -780,26 +1137,27 @@ WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst)
|
||||
OSSL_STATEM *st = &s->statem;
|
||||
|
||||
switch (st->hand_state) {
|
||||
default:
|
||||
/* Shouldn't happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return WORK_ERROR;
|
||||
|
||||
case TLS_ST_SR_CLNT_HELLO:
|
||||
return tls_post_process_client_hello(s, wst);
|
||||
|
||||
case TLS_ST_SR_KEY_EXCH:
|
||||
return tls_post_process_client_key_exchange(s, wst);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Shouldn't happen */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
static int ssl_check_srp_ext_ClientHello(SSL *s, int *al)
|
||||
/* Returns 1 on success, 0 for retryable error, -1 for fatal error */
|
||||
static int ssl_check_srp_ext_ClientHello(SSL *s)
|
||||
{
|
||||
int ret = SSL_ERROR_NONE;
|
||||
|
||||
*al = SSL_AD_UNRECOGNIZED_NAME;
|
||||
int ret;
|
||||
int al = SSL_AD_UNRECOGNIZED_NAME;
|
||||
|
||||
if ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) &&
|
||||
(s->srp_ctx.TLS_ext_srp_username_callback != NULL)) {
|
||||
@@ -808,100 +1166,173 @@ static int ssl_check_srp_ext_ClientHello(SSL *s, int *al)
|
||||
* RFC 5054 says SHOULD reject, we do so if There is no srp
|
||||
* login name
|
||||
*/
|
||||
ret = SSL3_AL_FATAL;
|
||||
*al = SSL_AD_UNKNOWN_PSK_IDENTITY;
|
||||
SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY,
|
||||
SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO,
|
||||
SSL_R_PSK_IDENTITY_NOT_FOUND);
|
||||
return -1;
|
||||
} else {
|
||||
ret = SSL_srp_server_param_with_username(s, al);
|
||||
ret = SSL_srp_server_param_with_username(s, &al);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
if (ret == SSL3_AL_FATAL) {
|
||||
SSLfatal(s, al, SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO,
|
||||
al == SSL_AD_UNKNOWN_PSK_IDENTITY
|
||||
? SSL_R_PSK_IDENTITY_NOT_FOUND
|
||||
: SSL_R_CLIENTHELLO_TLSEXT);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int tls_construct_hello_request(SSL *s)
|
||||
int dtls_raw_hello_verify_request(WPACKET *pkt, unsigned char *cookie,
|
||||
size_t cookie_len)
|
||||
{
|
||||
if (!ssl_set_handshake_header(s, SSL3_MT_HELLO_REQUEST, 0)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_HELLO_REQUEST, ERR_R_INTERNAL_ERROR);
|
||||
ossl_statem_set_error(s);
|
||||
/* Always use DTLS 1.0 version: see RFC 6347 */
|
||||
if (!WPACKET_put_bytes_u16(pkt, DTLS1_VERSION)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, cookie, cookie_len))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned int dtls_raw_hello_verify_request(unsigned char *buf,
|
||||
unsigned char *cookie,
|
||||
unsigned char cookie_len)
|
||||
int dtls_construct_hello_verify_request(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
unsigned int msg_len;
|
||||
unsigned char *p;
|
||||
|
||||
p = buf;
|
||||
/* Always use DTLS 1.0 version: see RFC 6347 */
|
||||
*(p++) = DTLS1_VERSION >> 8;
|
||||
*(p++) = DTLS1_VERSION & 0xFF;
|
||||
|
||||
*(p++) = (unsigned char)cookie_len;
|
||||
memcpy(p, cookie, cookie_len);
|
||||
p += cookie_len;
|
||||
msg_len = p - buf;
|
||||
|
||||
return msg_len;
|
||||
}
|
||||
|
||||
int dtls_construct_hello_verify_request(SSL *s)
|
||||
{
|
||||
unsigned int len;
|
||||
unsigned char *buf;
|
||||
|
||||
buf = (unsigned char *)s->init_buf->data;
|
||||
|
||||
unsigned int cookie_leni;
|
||||
if (s->ctx->app_gen_cookie_cb == NULL ||
|
||||
s->ctx->app_gen_cookie_cb(s, s->d1->cookie,
|
||||
&(s->d1->cookie_len)) == 0 ||
|
||||
s->d1->cookie_len > 255) {
|
||||
SSLerr(SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST,
|
||||
SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
|
||||
ossl_statem_set_error(s);
|
||||
&cookie_leni) == 0 ||
|
||||
cookie_leni > 255) {
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST,
|
||||
SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
s->d1->cookie_len = cookie_leni;
|
||||
|
||||
if (!dtls_raw_hello_verify_request(pkt, s->d1->cookie,
|
||||
s->d1->cookie_len)) {
|
||||
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = dtls_raw_hello_verify_request(&buf[DTLS1_HM_HEADER_LENGTH],
|
||||
s->d1->cookie, s->d1->cookie_len);
|
||||
|
||||
dtls1_set_message_header(s, DTLS1_MT_HELLO_VERIFY_REQUEST, len, 0, len);
|
||||
len += DTLS1_HM_HEADER_LENGTH;
|
||||
|
||||
/* number of bytes to write */
|
||||
s->init_num = len;
|
||||
s->init_off = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
/*-
|
||||
* ssl_check_for_safari attempts to fingerprint Safari using OS X
|
||||
* SecureTransport using the TLS extension block in |hello|.
|
||||
* Safari, since 10.6, sends exactly these extensions, in this order:
|
||||
* SNI,
|
||||
* elliptic_curves
|
||||
* ec_point_formats
|
||||
* signature_algorithms (for TLSv1.2 only)
|
||||
*
|
||||
* We wish to fingerprint Safari because they broke ECDHE-ECDSA support in 10.8,
|
||||
* but they advertise support. So enabling ECDHE-ECDSA ciphers breaks them.
|
||||
* Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from
|
||||
* 10.8..10.8.3 (which don't work).
|
||||
*/
|
||||
static void ssl_check_for_safari(SSL *s, const CLIENTHELLO_MSG *hello)
|
||||
{
|
||||
static const unsigned char kSafariExtensionsBlock[] = {
|
||||
0x00, 0x0a, /* elliptic_curves extension */
|
||||
0x00, 0x08, /* 8 bytes */
|
||||
0x00, 0x06, /* 6 bytes of curve ids */
|
||||
0x00, 0x17, /* P-256 */
|
||||
0x00, 0x18, /* P-384 */
|
||||
0x00, 0x19, /* P-521 */
|
||||
|
||||
0x00, 0x0b, /* ec_point_formats */
|
||||
0x00, 0x02, /* 2 bytes */
|
||||
0x01, /* 1 point format */
|
||||
0x00, /* uncompressed */
|
||||
/* The following is only present in TLS 1.2 */
|
||||
0x00, 0x0d, /* signature_algorithms */
|
||||
0x00, 0x0c, /* 12 bytes */
|
||||
0x00, 0x0a, /* 10 bytes */
|
||||
0x05, 0x01, /* SHA-384/RSA */
|
||||
0x04, 0x01, /* SHA-256/RSA */
|
||||
0x02, 0x01, /* SHA-1/RSA */
|
||||
0x04, 0x03, /* SHA-256/ECDSA */
|
||||
0x02, 0x03, /* SHA-1/ECDSA */
|
||||
};
|
||||
/* Length of the common prefix (first two extensions). */
|
||||
static const size_t kSafariCommonExtensionsLength = 18;
|
||||
unsigned int type;
|
||||
PACKET sni, tmppkt;
|
||||
size_t ext_len;
|
||||
|
||||
tmppkt = hello->extensions;
|
||||
|
||||
if (!PACKET_forward(&tmppkt, 2)
|
||||
|| !PACKET_get_net_2(&tmppkt, &type)
|
||||
|| !PACKET_get_length_prefixed_2(&tmppkt, &sni)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (type != TLSEXT_TYPE_server_name)
|
||||
return;
|
||||
|
||||
ext_len = TLS1_get_client_version(s) >= TLS1_2_VERSION ?
|
||||
sizeof(kSafariExtensionsBlock) : kSafariCommonExtensionsLength;
|
||||
|
||||
s->s3->is_probably_safari = PACKET_equal(&tmppkt, kSafariExtensionsBlock,
|
||||
ext_len);
|
||||
}
|
||||
#endif /* !OPENSSL_NO_EC */
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
|
||||
{
|
||||
int i, al = SSL_AD_INTERNAL_ERROR;
|
||||
unsigned int j, complen = 0;
|
||||
unsigned long id;
|
||||
const SSL_CIPHER *c;
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
SSL_COMP *comp = NULL;
|
||||
#endif
|
||||
STACK_OF(SSL_CIPHER) *ciphers = NULL;
|
||||
int protverr;
|
||||
/* |cookie| will only be initialized for DTLS. */
|
||||
PACKET session_id, cipher_suites, compression, extensions, cookie;
|
||||
int is_v2_record;
|
||||
PACKET session_id, compression, extensions, cookie;
|
||||
static const unsigned char null_compression = 0;
|
||||
CLIENTHELLO_MSG *clienthello = NULL;
|
||||
|
||||
is_v2_record = RECORD_LAYER_is_sslv2_record(&s->rlayer);
|
||||
/* Check if this is actually an unexpected renegotiation ClientHello */
|
||||
if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) {
|
||||
if (!ossl_assert(!SSL_IS_TLS13(s))) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if ((s->options & SSL_OP_NO_RENEGOTIATION) != 0
|
||||
|| (!s->s3->send_connection_binding
|
||||
&& (s->options
|
||||
& SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) == 0)) {
|
||||
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
|
||||
return MSG_PROCESS_FINISHED_READING;
|
||||
}
|
||||
s->renegotiate = 1;
|
||||
s->new_session = 1;
|
||||
}
|
||||
|
||||
clienthello = OPENSSL_zalloc(sizeof(*clienthello));
|
||||
if (clienthello == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* First, parse the raw ClientHello data into the CLIENTHELLO_MSG structure.
|
||||
*/
|
||||
clienthello->isv2 = RECORD_LAYER_is_sslv2_record(&s->rlayer);
|
||||
PACKET_null_init(&cookie);
|
||||
/* First lets get s->client_version set correctly */
|
||||
if (is_v2_record) {
|
||||
unsigned int version;
|
||||
|
||||
if (clienthello->isv2) {
|
||||
unsigned int mt;
|
||||
|
||||
if (!SSL_IS_FIRST_HANDSHAKE(s)
|
||||
|| s->hello_retry_request != SSL_HRR_NONE) {
|
||||
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
|
||||
SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNEXPECTED_MESSAGE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*-
|
||||
* An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2
|
||||
* header is sent directly on the wire, not wrapped as a TLS
|
||||
@@ -924,136 +1355,97 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
|
||||
* layer in order to have determined that this is a SSLv2 record
|
||||
* in the first place
|
||||
*/
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!PACKET_get_net_2(pkt, &version)) {
|
||||
/* No protocol version supplied! */
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
|
||||
goto err;
|
||||
}
|
||||
if (version == 0x0002) {
|
||||
/* This is real SSLv2. We don't support it. */
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
|
||||
goto err;
|
||||
} else if ((version & 0xff00) == (SSL3_VERSION_MAJOR << 8)) {
|
||||
/* SSLv3/TLS */
|
||||
s->client_version = version;
|
||||
} else {
|
||||
/* No idea what protocol this is */
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* use version from inside client hello, not from record header (may
|
||||
* differ: see RFC 2246, Appendix E, second paragraph)
|
||||
*/
|
||||
if (!PACKET_get_net_2(pkt, (unsigned int *)&s->client_version)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
|
||||
goto f_err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Do SSL/TLS version negotiation if applicable. For DTLS we just check
|
||||
* versions are potentially compatible. Version negotiation comes later.
|
||||
*/
|
||||
if (!SSL_IS_DTLS(s)) {
|
||||
protverr = ssl_choose_server_version(s);
|
||||
} else if (s->method->version != DTLS_ANY_VERSION &&
|
||||
DTLS_VERSION_LT(s->client_version, s->version)) {
|
||||
protverr = SSL_R_VERSION_TOO_LOW;
|
||||
} else {
|
||||
protverr = 0;
|
||||
}
|
||||
|
||||
if (protverr) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, protverr);
|
||||
if ((!s->enc_write_ctx && !s->write_hash)) {
|
||||
/*
|
||||
* similar to ssl3_get_record, send alert using remote version
|
||||
* number
|
||||
*/
|
||||
s->version = s->client_version;
|
||||
}
|
||||
al = SSL_AD_PROTOCOL_VERSION;
|
||||
goto f_err;
|
||||
if (!PACKET_get_net_2(pkt, &clienthello->legacy_version)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_LENGTH_TOO_SHORT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Parse the message and load client random. */
|
||||
if (is_v2_record) {
|
||||
if (clienthello->isv2) {
|
||||
/*
|
||||
* Handle an SSLv2 backwards compatible ClientHello
|
||||
* Note, this is only for SSLv3+ using the backward compatible format.
|
||||
* Real SSLv2 is not supported, and is rejected above.
|
||||
* Real SSLv2 is not supported, and is rejected below.
|
||||
*/
|
||||
unsigned int cipher_len, session_id_len, challenge_len;
|
||||
unsigned int ciphersuite_len, session_id_len, challenge_len;
|
||||
PACKET challenge;
|
||||
|
||||
if (!PACKET_get_net_2(pkt, &cipher_len)
|
||||
if (!PACKET_get_net_2(pkt, &ciphersuite_len)
|
||||
|| !PACKET_get_net_2(pkt, &session_id_len)
|
||||
|| !PACKET_get_net_2(pkt, &challenge_len)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_RECORD_LENGTH_MISMATCH);
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_RECORD_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!PACKET_get_sub_packet(pkt, &cipher_suites, cipher_len)
|
||||
|| !PACKET_get_sub_packet(pkt, &session_id, session_id_len)
|
||||
if (!PACKET_get_sub_packet(pkt, &clienthello->ciphersuites,
|
||||
ciphersuite_len)
|
||||
|| !PACKET_copy_bytes(pkt, clienthello->session_id, session_id_len)
|
||||
|| !PACKET_get_sub_packet(pkt, &challenge, challenge_len)
|
||||
/* No extensions. */
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_RECORD_LENGTH_MISMATCH);
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_RECORD_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
clienthello->session_id_len = session_id_len;
|
||||
|
||||
/* Load the client random and compression list. */
|
||||
challenge_len = challenge_len > SSL3_RANDOM_SIZE ? SSL3_RANDOM_SIZE :
|
||||
challenge_len;
|
||||
memset(s->s3->client_random, 0, SSL3_RANDOM_SIZE);
|
||||
/* Load the client random and compression list. We use SSL3_RANDOM_SIZE
|
||||
* here rather than sizeof(clienthello->random) because that is the limit
|
||||
* for SSLv3 and it is fixed. It won't change even if
|
||||
* sizeof(clienthello->random) does.
|
||||
*/
|
||||
challenge_len = challenge_len > SSL3_RANDOM_SIZE
|
||||
? SSL3_RANDOM_SIZE : challenge_len;
|
||||
memset(clienthello->random, 0, SSL3_RANDOM_SIZE);
|
||||
if (!PACKET_copy_bytes(&challenge,
|
||||
s->s3->client_random + SSL3_RANDOM_SIZE -
|
||||
clienthello->random + SSL3_RANDOM_SIZE -
|
||||
challenge_len, challenge_len)
|
||||
/* Advertise only null compression. */
|
||||
|| !PACKET_buf_init(&compression, &null_compression, 1)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
PACKET_null_init(&extensions);
|
||||
PACKET_null_init(&clienthello->extensions);
|
||||
} else {
|
||||
/* Regular ClientHello. */
|
||||
if (!PACKET_copy_bytes(pkt, s->s3->client_random, SSL3_RANDOM_SIZE)
|
||||
|| !PACKET_get_length_prefixed_1(pkt, &session_id)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
if (PACKET_remaining(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
if (!PACKET_copy_bytes(pkt, clienthello->random, SSL3_RANDOM_SIZE)
|
||||
|| !PACKET_get_length_prefixed_1(pkt, &session_id)
|
||||
|| !PACKET_copy_all(&session_id, clienthello->session_id,
|
||||
SSL_MAX_SSL_SESSION_ID_LENGTH,
|
||||
&clienthello->session_id_len)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
if (!PACKET_get_length_prefixed_1(pkt, &cookie)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
if (!PACKET_copy_all(&cookie, clienthello->dtls_cookie,
|
||||
DTLS1_COOKIE_LENGTH,
|
||||
&clienthello->dtls_cookie_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* If we require cookies and this ClientHello doesn't contain one,
|
||||
@@ -1061,55 +1453,260 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
|
||||
* So check cookie length...
|
||||
*/
|
||||
if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
|
||||
if (PACKET_remaining(&cookie) == 0)
|
||||
return 1;
|
||||
if (clienthello->dtls_cookie_len == 0)
|
||||
return MSG_PROCESS_FINISHED_READING;
|
||||
}
|
||||
}
|
||||
|
||||
if (!PACKET_get_length_prefixed_2(pkt, &cipher_suites)
|
||||
|| !PACKET_get_length_prefixed_1(pkt, &compression)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
if (!PACKET_get_length_prefixed_2(pkt, &clienthello->ciphersuites)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!PACKET_get_length_prefixed_1(pkt, &compression)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Could be empty. */
|
||||
extensions = *pkt;
|
||||
if (PACKET_remaining(pkt) == 0) {
|
||||
PACKET_null_init(&clienthello->extensions);
|
||||
} else {
|
||||
if (!PACKET_get_length_prefixed_2(pkt, &clienthello->extensions)
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!PACKET_copy_all(&compression, clienthello->compressions,
|
||||
MAX_COMPRESSIONS_SIZE,
|
||||
&clienthello->compressions_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Preserve the raw extensions PACKET for later use */
|
||||
extensions = clienthello->extensions;
|
||||
if (!tls_collect_extensions(s, &extensions, SSL_EXT_CLIENT_HELLO,
|
||||
&clienthello->pre_proc_exts,
|
||||
&clienthello->pre_proc_exts_len, 1)) {
|
||||
/* SSLfatal already been called */
|
||||
goto err;
|
||||
}
|
||||
s->clienthello = clienthello;
|
||||
|
||||
return MSG_PROCESS_CONTINUE_PROCESSING;
|
||||
|
||||
err:
|
||||
if (clienthello != NULL)
|
||||
OPENSSL_free(clienthello->pre_proc_exts);
|
||||
OPENSSL_free(clienthello);
|
||||
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
static int tls_early_post_process_client_hello(SSL *s)
|
||||
{
|
||||
unsigned int j;
|
||||
int i, al = SSL_AD_INTERNAL_ERROR;
|
||||
int protverr;
|
||||
size_t loop;
|
||||
unsigned long id;
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
SSL_COMP *comp = NULL;
|
||||
#endif
|
||||
const SSL_CIPHER *c;
|
||||
STACK_OF(SSL_CIPHER) *ciphers = NULL;
|
||||
STACK_OF(SSL_CIPHER) *scsvs = NULL;
|
||||
CLIENTHELLO_MSG *clienthello = s->clienthello;
|
||||
DOWNGRADE dgrd = DOWNGRADE_NONE;
|
||||
|
||||
/* Finished parsing the ClientHello, now we can start processing it */
|
||||
/* Give the ClientHello callback a crack at things */
|
||||
if (s->ctx->client_hello_cb != NULL) {
|
||||
/* A failure in the ClientHello callback terminates the connection. */
|
||||
switch (s->ctx->client_hello_cb(s, &al, s->ctx->client_hello_cb_arg)) {
|
||||
case SSL_CLIENT_HELLO_SUCCESS:
|
||||
break;
|
||||
case SSL_CLIENT_HELLO_RETRY:
|
||||
s->rwstate = SSL_CLIENT_HELLO_CB;
|
||||
return -1;
|
||||
case SSL_CLIENT_HELLO_ERROR:
|
||||
default:
|
||||
SSLfatal(s, al,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_CALLBACK_FAILED);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up the client_random */
|
||||
memcpy(s->s3->client_random, clienthello->random, SSL3_RANDOM_SIZE);
|
||||
|
||||
/* Choose the version */
|
||||
|
||||
if (clienthello->isv2) {
|
||||
if (clienthello->legacy_version == SSL2_VERSION
|
||||
|| (clienthello->legacy_version & 0xff00)
|
||||
!= (SSL3_VERSION_MAJOR << 8)) {
|
||||
/*
|
||||
* This is real SSLv2 or something completely unknown. We don't
|
||||
* support it.
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_UNKNOWN_PROTOCOL);
|
||||
goto err;
|
||||
}
|
||||
/* SSLv3/TLS */
|
||||
s->client_version = clienthello->legacy_version;
|
||||
}
|
||||
/*
|
||||
* Do SSL/TLS version negotiation if applicable. For DTLS we just check
|
||||
* versions are potentially compatible. Version negotiation comes later.
|
||||
*/
|
||||
if (!SSL_IS_DTLS(s)) {
|
||||
protverr = ssl_choose_server_version(s, clienthello, &dgrd);
|
||||
} else if (s->method->version != DTLS_ANY_VERSION &&
|
||||
DTLS_VERSION_LT((int)clienthello->legacy_version, s->version)) {
|
||||
protverr = SSL_R_VERSION_TOO_LOW;
|
||||
} else {
|
||||
protverr = 0;
|
||||
}
|
||||
|
||||
if (protverr) {
|
||||
if (SSL_IS_FIRST_HANDSHAKE(s)) {
|
||||
/* like ssl3_get_record, send alert using remote version number */
|
||||
s->version = s->client_version = clienthello->legacy_version;
|
||||
}
|
||||
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* TLSv1.3 specifies that a ClientHello must end on a record boundary */
|
||||
if (SSL_IS_TLS13(s) && RECORD_LAYER_processed_read_pending(&s->rlayer)) {
|
||||
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_NOT_ON_RECORD_BOUNDARY);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (SSL_IS_DTLS(s)) {
|
||||
/* Empty cookie was already handled above by returning early. */
|
||||
if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
|
||||
if (s->ctx->app_verify_cookie_cb != NULL) {
|
||||
if (s->ctx->app_verify_cookie_cb(s, PACKET_data(&cookie),
|
||||
PACKET_remaining(&cookie)) ==
|
||||
0) {
|
||||
al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_COOKIE_MISMATCH);
|
||||
goto f_err;
|
||||
if (s->ctx->app_verify_cookie_cb(s, clienthello->dtls_cookie,
|
||||
clienthello->dtls_cookie_len) == 0) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_COOKIE_MISMATCH);
|
||||
goto err;
|
||||
/* else cookie verification succeeded */
|
||||
}
|
||||
/* default verification */
|
||||
} else if (!PACKET_equal(&cookie, s->d1->cookie, s->d1->cookie_len)) {
|
||||
al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH);
|
||||
goto f_err;
|
||||
} else if (s->d1->cookie_len != clienthello->dtls_cookie_len
|
||||
|| memcmp(clienthello->dtls_cookie, s->d1->cookie,
|
||||
s->d1->cookie_len) != 0) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_COOKIE_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
s->d1->cookie_verified = 1;
|
||||
}
|
||||
if (s->method->version == DTLS_ANY_VERSION) {
|
||||
protverr = ssl_choose_server_version(s);
|
||||
protverr = ssl_choose_server_version(s, clienthello, &dgrd);
|
||||
if (protverr != 0) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, protverr);
|
||||
s->version = s->client_version;
|
||||
al = SSL_AD_PROTOCOL_VERSION;
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s->hit = 0;
|
||||
|
||||
if (!ssl_cache_cipherlist(s, &clienthello->ciphersuites,
|
||||
clienthello->isv2) ||
|
||||
!bytes_to_cipher_list(s, &clienthello->ciphersuites, &ciphers, &scsvs,
|
||||
clienthello->isv2, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->s3->send_connection_binding = 0;
|
||||
/* Check what signalling cipher-suite values were received. */
|
||||
if (scsvs != NULL) {
|
||||
for(i = 0; i < sk_SSL_CIPHER_num(scsvs); i++) {
|
||||
c = sk_SSL_CIPHER_value(scsvs, i);
|
||||
if (SSL_CIPHER_get_id(c) == SSL3_CK_SCSV) {
|
||||
if (s->renegotiate) {
|
||||
/* SCSV is fatal if renegotiating */
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
|
||||
goto err;
|
||||
}
|
||||
s->s3->send_connection_binding = 1;
|
||||
} else if (SSL_CIPHER_get_id(c) == SSL3_CK_FALLBACK_SCSV &&
|
||||
!ssl_check_version_downgrade(s)) {
|
||||
/*
|
||||
* This SCSV indicates that the client previously tried
|
||||
* a higher version. We should fail if the current version
|
||||
* is an unexpected downgrade, as that indicates that the first
|
||||
* connection may have been tampered with in order to trigger
|
||||
* an insecure downgrade.
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_INAPPROPRIATE_FALLBACK,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_INAPPROPRIATE_FALLBACK);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* For TLSv1.3 we must select the ciphersuite *before* session resumption */
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
const SSL_CIPHER *cipher =
|
||||
ssl3_choose_cipher(s, ciphers, ssl_get_cipher_preferences(s));
|
||||
|
||||
if (cipher == NULL) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_NO_SHARED_CIPHER);
|
||||
goto err;
|
||||
}
|
||||
if (s->hello_retry_request == SSL_HRR_PENDING
|
||||
&& (s->s3->tmp.new_cipher == NULL
|
||||
|| s->s3->tmp.new_cipher->id != cipher->id)) {
|
||||
/*
|
||||
* A previous HRR picked a different ciphersuite to the one we
|
||||
* just selected. Something must have changed.
|
||||
*/
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_BAD_CIPHER);
|
||||
goto err;
|
||||
}
|
||||
s->s3->tmp.new_cipher = cipher;
|
||||
}
|
||||
|
||||
/* We need to do this before getting the session */
|
||||
if (!tls_parse_extension(s, TLSEXT_IDX_extended_master_secret,
|
||||
SSL_EXT_CLIENT_HELLO,
|
||||
clienthello->pre_proc_exts, NULL, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't allow resumption in a backwards compatible ClientHello.
|
||||
* TODO(openssl-team): in TLS1.1+, session_id MUST be empty.
|
||||
@@ -1126,41 +1723,41 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
|
||||
* SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION setting will be
|
||||
* ignored.
|
||||
*/
|
||||
if (is_v2_record ||
|
||||
if (clienthello->isv2 ||
|
||||
(s->new_session &&
|
||||
(s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) {
|
||||
if (!ssl_get_new_session(s, 1))
|
||||
if (!ssl_get_new_session(s, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
i = ssl_get_prev_session(s, &extensions, &session_id);
|
||||
/*
|
||||
* Only resume if the session's version matches the negotiated
|
||||
* version.
|
||||
* RFC 5246 does not provide much useful advice on resumption
|
||||
* with a different protocol version. It doesn't forbid it but
|
||||
* the sanity of such behaviour would be questionable.
|
||||
* In practice, clients do not accept a version mismatch and
|
||||
* will abort the handshake with an error.
|
||||
*/
|
||||
if (i == 1 && s->version == s->session->ssl_version) {
|
||||
i = ssl_get_prev_session(s, clienthello);
|
||||
if (i == 1) {
|
||||
/* previous session */
|
||||
s->hit = 1;
|
||||
} else if (i == -1) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
} else {
|
||||
/* i == 0 */
|
||||
if (!ssl_get_new_session(s, 1))
|
||||
if (!ssl_get_new_session(s, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ssl_bytes_to_cipher_list(s, &cipher_suites, &(ciphers),
|
||||
is_v2_record, &al) == NULL) {
|
||||
goto f_err;
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
memcpy(s->tmp_session_id, s->clienthello->session_id,
|
||||
s->clienthello->session_id_len);
|
||||
s->tmp_session_id_len = s->clienthello->session_id_len;
|
||||
}
|
||||
|
||||
/* If it is a hit, check that the cipher is in the list */
|
||||
if (s->hit) {
|
||||
/*
|
||||
* If it is a hit, check that the cipher is in the list. In TLSv1.3 we check
|
||||
* ciphersuite compatibility with the session as part of resumption.
|
||||
*/
|
||||
if (!SSL_IS_TLS13(s) && s->hit) {
|
||||
j = 0;
|
||||
id = s->session->cipher->id;
|
||||
|
||||
@@ -1183,32 +1780,36 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
|
||||
* we need to have the cipher in the cipher list if we are asked
|
||||
* to reuse it
|
||||
*/
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_REQUIRED_CIPHER_MISSING);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_REQUIRED_CIPHER_MISSING);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
complen = PACKET_remaining(&compression);
|
||||
for (j = 0; j < complen; j++) {
|
||||
if (PACKET_data(&compression)[j] == 0)
|
||||
for (loop = 0; loop < clienthello->compressions_len; loop++) {
|
||||
if (clienthello->compressions[loop] == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (j >= complen) {
|
||||
if (loop >= clienthello->compressions_len) {
|
||||
/* no compress */
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_NO_COMPRESSION_SPECIFIED);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_NO_COMPRESSION_SPECIFIED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
|
||||
ssl_check_for_safari(s, clienthello);
|
||||
#endif /* !OPENSSL_NO_EC */
|
||||
|
||||
/* TLS extensions */
|
||||
if (s->version >= SSL3_VERSION) {
|
||||
if (!ssl_parse_clienthello_tlsext(s, &extensions)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_PARSE_TLSEXT);
|
||||
goto err;
|
||||
}
|
||||
if (!tls_parse_all_extensions(s, SSL_EXT_CLIENT_HELLO,
|
||||
clienthello->pre_proc_exts, NULL, 0, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1220,19 +1821,33 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
|
||||
{
|
||||
unsigned char *pos;
|
||||
pos = s->s3->server_random;
|
||||
if (ssl_fill_hello_random(s, 1, pos, SSL3_RANDOM_SIZE) <= 0) {
|
||||
goto f_err;
|
||||
if (ssl_fill_hello_random(s, 1, pos, SSL3_RANDOM_SIZE, dgrd) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!s->hit && s->version >= TLS1_VERSION && s->tls_session_secret_cb) {
|
||||
if (!s->hit
|
||||
&& s->version >= TLS1_VERSION
|
||||
&& !SSL_IS_TLS13(s)
|
||||
&& !SSL_IS_DTLS(s)
|
||||
&& s->ext.session_secret_cb) {
|
||||
const SSL_CIPHER *pref_cipher = NULL;
|
||||
/*
|
||||
* s->session->master_key_length is a size_t, but this is an int for
|
||||
* backwards compat reasons
|
||||
*/
|
||||
int master_key_length;
|
||||
|
||||
s->session->master_key_length = sizeof(s->session->master_key);
|
||||
if (s->tls_session_secret_cb(s, s->session->master_key,
|
||||
&s->session->master_key_length, ciphers,
|
||||
master_key_length = sizeof(s->session->master_key);
|
||||
if (s->ext.session_secret_cb(s, s->session->master_key,
|
||||
&master_key_length, ciphers,
|
||||
&pref_cipher,
|
||||
s->tls_session_secret_cb_arg)) {
|
||||
s->ext.session_secret_cb_arg)
|
||||
&& master_key_length > 0) {
|
||||
s->session->master_key_length = master_key_length;
|
||||
s->hit = 1;
|
||||
s->session->ciphers = ciphers;
|
||||
s->session->verify_result = X509_V_OK;
|
||||
@@ -1240,15 +1855,14 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
|
||||
ciphers = NULL;
|
||||
|
||||
/* check if some cipher was preferred by call back */
|
||||
if (pref_cipher == NULL) {
|
||||
if (pref_cipher == NULL)
|
||||
pref_cipher = ssl3_choose_cipher(s, s->session->ciphers,
|
||||
ssl_get_cipher_preferences(s));
|
||||
}
|
||||
|
||||
if (pref_cipher == NULL) {
|
||||
al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_NO_SHARED_CIPHER);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_NO_SHARED_CIPHER);
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->session->cipher = pref_cipher;
|
||||
@@ -1266,17 +1880,31 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
|
||||
* algorithms from the client, starting at q.
|
||||
*/
|
||||
s->s3->tmp.new_compression = NULL;
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
/*
|
||||
* We already checked above that the NULL compression method appears in
|
||||
* the list. Now we check there aren't any others (which is illegal in
|
||||
* a TLSv1.3 ClientHello.
|
||||
*/
|
||||
if (clienthello->compressions_len != 1) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_INVALID_COMPRESSION_ALGORITHM);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
/* This only happens if we have a cache hit */
|
||||
if (s->session->compress_meth != 0) {
|
||||
else if (s->session->compress_meth != 0) {
|
||||
int m, comp_id = s->session->compress_meth;
|
||||
unsigned int k;
|
||||
/* Perform sanity checks on resumed compression algorithm */
|
||||
/* Can't disable compression */
|
||||
if (!ssl_allow_compression(s)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_INCONSISTENT_COMPRESSION);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_INCONSISTENT_COMPRESSION);
|
||||
goto err;
|
||||
}
|
||||
/* Look for resumed compression method */
|
||||
for (m = 0; m < sk_SSL_COMP_num(s->ctx->comp_methods); m++) {
|
||||
@@ -1287,24 +1915,25 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
|
||||
}
|
||||
}
|
||||
if (s->s3->tmp.new_compression == NULL) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_INVALID_COMPRESSION_ALGORITHM);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_INVALID_COMPRESSION_ALGORITHM);
|
||||
goto err;
|
||||
}
|
||||
/* Look for resumed method in compression list */
|
||||
for (k = 0; k < complen; k++) {
|
||||
if (PACKET_data(&compression)[k] == comp_id)
|
||||
for (k = 0; k < clienthello->compressions_len; k++) {
|
||||
if (clienthello->compressions[k] == comp_id)
|
||||
break;
|
||||
}
|
||||
if (k >= complen) {
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING);
|
||||
goto f_err;
|
||||
if (k >= clienthello->compressions_len) {
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING);
|
||||
goto err;
|
||||
}
|
||||
} else if (s->hit)
|
||||
} else if (s->hit) {
|
||||
comp = NULL;
|
||||
else if (ssl_allow_compression(s) && s->ctx->comp_methods) {
|
||||
} else if (ssl_allow_compression(s) && s->ctx->comp_methods) {
|
||||
/* See if we have a match */
|
||||
int m, nn, v, done = 0;
|
||||
unsigned int o;
|
||||
@@ -1313,8 +1942,8 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
|
||||
for (m = 0; m < nn; m++) {
|
||||
comp = sk_SSL_COMP_value(s->ctx->comp_methods, m);
|
||||
v = comp->id;
|
||||
for (o = 0; o < complen; o++) {
|
||||
if (v == PACKET_data(&compression)[o]) {
|
||||
for (o = 0; o < clienthello->compressions_len; o++) {
|
||||
if (v == clienthello->compressions[o]) {
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
@@ -1333,8 +1962,10 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
|
||||
* using compression.
|
||||
*/
|
||||
if (s->session->compress_meth != 0) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_INCONSISTENT_COMPRESSION);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_INCONSISTENT_COMPRESSION);
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1342,89 +1973,233 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
|
||||
* Given s->session->ciphers and SSL_get_ciphers, we must pick a cipher
|
||||
*/
|
||||
|
||||
if (!s->hit || SSL_IS_TLS13(s)) {
|
||||
sk_SSL_CIPHER_free(s->session->ciphers);
|
||||
s->session->ciphers = ciphers;
|
||||
if (ciphers == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
ciphers = NULL;
|
||||
}
|
||||
|
||||
if (!s->hit) {
|
||||
#ifdef OPENSSL_NO_COMP
|
||||
s->session->compress_meth = 0;
|
||||
#else
|
||||
s->session->compress_meth = (comp == NULL) ? 0 : comp->id;
|
||||
#endif
|
||||
sk_SSL_CIPHER_free(s->session->ciphers);
|
||||
s->session->ciphers = ciphers;
|
||||
if (ciphers == NULL) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
|
||||
goto f_err;
|
||||
}
|
||||
ciphers = NULL;
|
||||
if (!tls1_set_server_sigalgs(s)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_CLIENTHELLO_TLSEXT);
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
sk_SSL_CIPHER_free(ciphers);
|
||||
return MSG_PROCESS_CONTINUE_PROCESSING;
|
||||
f_err:
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
sk_SSL_CIPHER_free(scsvs);
|
||||
OPENSSL_free(clienthello->pre_proc_exts);
|
||||
OPENSSL_free(s->clienthello);
|
||||
s->clienthello = NULL;
|
||||
return 1;
|
||||
err:
|
||||
ossl_statem_set_error(s);
|
||||
|
||||
sk_SSL_CIPHER_free(ciphers);
|
||||
return MSG_PROCESS_ERROR;
|
||||
sk_SSL_CIPHER_free(scsvs);
|
||||
OPENSSL_free(clienthello->pre_proc_exts);
|
||||
OPENSSL_free(s->clienthello);
|
||||
s->clienthello = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call the status request callback if needed. Upon success, returns 1.
|
||||
* Upon failure, returns 0.
|
||||
*/
|
||||
static int tls_handle_status_request(SSL *s)
|
||||
{
|
||||
s->ext.status_expected = 0;
|
||||
|
||||
/*
|
||||
* If status request then ask callback what to do. Note: this must be
|
||||
* called after servername callbacks in case the certificate has changed,
|
||||
* and must be called after the cipher has been chosen because this may
|
||||
* influence which certificate is sent
|
||||
*/
|
||||
if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing && s->ctx != NULL
|
||||
&& s->ctx->ext.status_cb != NULL) {
|
||||
int ret;
|
||||
|
||||
/* If no certificate can't return certificate status */
|
||||
if (s->s3->tmp.cert != NULL) {
|
||||
/*
|
||||
* Set current certificate to one we will use so SSL_get_certificate
|
||||
* et al can pick it up.
|
||||
*/
|
||||
s->cert->key = s->s3->tmp.cert;
|
||||
ret = s->ctx->ext.status_cb(s, s->ctx->ext.status_arg);
|
||||
switch (ret) {
|
||||
/* We don't want to send a status request response */
|
||||
case SSL_TLSEXT_ERR_NOACK:
|
||||
s->ext.status_expected = 0;
|
||||
break;
|
||||
/* status request response should be sent */
|
||||
case SSL_TLSEXT_ERR_OK:
|
||||
if (s->ext.ocsp.resp)
|
||||
s->ext.status_expected = 1;
|
||||
break;
|
||||
/* something bad happened */
|
||||
case SSL_TLSEXT_ERR_ALERT_FATAL:
|
||||
default:
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_HANDLE_STATUS_REQUEST,
|
||||
SSL_R_CLIENTHELLO_TLSEXT);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call the alpn_select callback if needed. Upon success, returns 1.
|
||||
* Upon failure, returns 0.
|
||||
*/
|
||||
int tls_handle_alpn(SSL *s)
|
||||
{
|
||||
const unsigned char *selected = NULL;
|
||||
unsigned char selected_len = 0;
|
||||
|
||||
if (s->ctx->ext.alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) {
|
||||
int r = s->ctx->ext.alpn_select_cb(s, &selected, &selected_len,
|
||||
s->s3->alpn_proposed,
|
||||
(unsigned int)s->s3->alpn_proposed_len,
|
||||
s->ctx->ext.alpn_select_cb_arg);
|
||||
|
||||
if (r == SSL_TLSEXT_ERR_OK) {
|
||||
OPENSSL_free(s->s3->alpn_selected);
|
||||
s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len);
|
||||
if (s->s3->alpn_selected == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_HANDLE_ALPN,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
s->s3->alpn_selected_len = selected_len;
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
/* ALPN takes precedence over NPN. */
|
||||
s->s3->npn_seen = 0;
|
||||
#endif
|
||||
|
||||
/* Check ALPN is consistent with session */
|
||||
if (s->session->ext.alpn_selected == NULL
|
||||
|| selected_len != s->session->ext.alpn_selected_len
|
||||
|| memcmp(selected, s->session->ext.alpn_selected,
|
||||
selected_len) != 0) {
|
||||
/* Not consistent so can't be used for early_data */
|
||||
s->ext.early_data_ok = 0;
|
||||
|
||||
if (!s->hit) {
|
||||
/* If a new session update it with the new ALPN value */
|
||||
s->session->ext.alpn_selected = OPENSSL_memdup(selected,
|
||||
selected_len);
|
||||
if (s->session->ext.alpn_selected == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_HANDLE_ALPN,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
s->session->ext.alpn_selected_len = selected_len;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
} else if (r != SSL_TLSEXT_ERR_NOACK) {
|
||||
SSLfatal(s, SSL_AD_NO_APPLICATION_PROTOCOL, SSL_F_TLS_HANDLE_ALPN,
|
||||
SSL_R_NO_APPLICATION_PROTOCOL);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* If r == SSL_TLSEXT_ERR_NOACK then behave as if no callback was
|
||||
* present.
|
||||
*/
|
||||
}
|
||||
|
||||
/* Check ALPN is consistent with session */
|
||||
if (s->session->ext.alpn_selected != NULL) {
|
||||
/* Not consistent so can't be used for early_data */
|
||||
s->ext.early_data_ok = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
|
||||
{
|
||||
int al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
const SSL_CIPHER *cipher;
|
||||
|
||||
if (wst == WORK_MORE_A) {
|
||||
if (!s->hit) {
|
||||
int rv = tls_early_post_process_client_hello(s);
|
||||
if (rv == 0) {
|
||||
/* SSLfatal() was already called */
|
||||
goto err;
|
||||
}
|
||||
if (rv < 0)
|
||||
return WORK_MORE_A;
|
||||
wst = WORK_MORE_B;
|
||||
}
|
||||
if (wst == WORK_MORE_B) {
|
||||
if (!s->hit || SSL_IS_TLS13(s)) {
|
||||
/* Let cert callback update server certificates if required */
|
||||
if (s->cert->cert_cb) {
|
||||
if (!s->hit && s->cert->cert_cb != NULL) {
|
||||
int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg);
|
||||
if (rv == 0) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_CERT_CB_ERROR);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_CERT_CB_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (rv < 0) {
|
||||
s->rwstate = SSL_X509_LOOKUP;
|
||||
return WORK_MORE_A;
|
||||
return WORK_MORE_B;
|
||||
}
|
||||
s->rwstate = SSL_NOTHING;
|
||||
}
|
||||
cipher =
|
||||
ssl3_choose_cipher(s, s->session->ciphers,
|
||||
ssl_get_cipher_preferences(s));
|
||||
|
||||
if (cipher == NULL) {
|
||||
SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_NO_SHARED_CIPHER);
|
||||
goto f_err;
|
||||
/* In TLSv1.3 we selected the ciphersuite before resumption */
|
||||
if (!SSL_IS_TLS13(s)) {
|
||||
cipher =
|
||||
ssl3_choose_cipher(s, s->session->ciphers, ssl_get_cipher_preferences(s));
|
||||
|
||||
if (cipher == NULL) {
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_NO_SHARED_CIPHER);
|
||||
goto err;
|
||||
}
|
||||
s->s3->tmp.new_cipher = cipher;
|
||||
}
|
||||
if (!s->hit) {
|
||||
if (!tls_choose_sigalg(s, 1)) {
|
||||
/* SSLfatal already called */
|
||||
goto err;
|
||||
}
|
||||
/* check whether we should disable session resumption */
|
||||
if (s->not_resumable_session_cb != NULL)
|
||||
s->session->not_resumable =
|
||||
s->not_resumable_session_cb(s,
|
||||
((s->s3->tmp.new_cipher->algorithm_mkey
|
||||
& (SSL_kDHE | SSL_kECDHE)) != 0));
|
||||
if (s->session->not_resumable)
|
||||
/* do not send a session ticket */
|
||||
s->ext.ticket_expected = 0;
|
||||
}
|
||||
s->s3->tmp.new_cipher = cipher;
|
||||
/* check whether we should disable session resumption */
|
||||
if (s->not_resumable_session_cb != NULL)
|
||||
s->session->not_resumable = s->not_resumable_session_cb(s,
|
||||
((cipher->algorithm_mkey & (SSL_kDHE | SSL_kECDHE)) != 0));
|
||||
if (s->session->not_resumable)
|
||||
/* do not send a session ticket */
|
||||
s->tlsext_ticket_expected = 0;
|
||||
} else {
|
||||
/* Session-id reuse */
|
||||
s->s3->tmp.new_cipher = s->session->cipher;
|
||||
}
|
||||
|
||||
if (!(s->verify_mode & SSL_VERIFY_PEER)) {
|
||||
if (!ssl3_digest_cached_records(s, 0)) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
}
|
||||
|
||||
/*-
|
||||
* we now have the following setup.
|
||||
* client_random
|
||||
@@ -1437,73 +2212,71 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
|
||||
* s->s3->tmp.new_cipher- the new cipher to use.
|
||||
*/
|
||||
|
||||
/* Handles TLS extensions that we couldn't check earlier */
|
||||
if (s->version >= SSL3_VERSION) {
|
||||
if (!ssl_check_clienthello_tlsext_late(s, &al)) {
|
||||
SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_CLIENTHELLO_TLSEXT);
|
||||
goto f_err;
|
||||
}
|
||||
/*
|
||||
* Call status_request callback if needed. Has to be done after the
|
||||
* certificate callbacks etc above.
|
||||
*/
|
||||
if (!tls_handle_status_request(s)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* Call alpn_select callback if needed. Has to be done after SNI and
|
||||
* cipher negotiation (HTTP/2 restricts permitted ciphers). In TLSv1.3
|
||||
* we already did this because cipher negotiation happens earlier, and
|
||||
* we must handle ALPN before we decide whether to accept early_data.
|
||||
*/
|
||||
if (!SSL_IS_TLS13(s) && !tls_handle_alpn(s)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
wst = WORK_MORE_B;
|
||||
wst = WORK_MORE_C;
|
||||
}
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
if (wst == WORK_MORE_B) {
|
||||
if (wst == WORK_MORE_C) {
|
||||
int ret;
|
||||
if ((ret = ssl_check_srp_ext_ClientHello(s, &al)) < 0) {
|
||||
if ((ret = ssl_check_srp_ext_ClientHello(s)) == 0) {
|
||||
/*
|
||||
* callback indicates further work to be done
|
||||
*/
|
||||
s->rwstate = SSL_X509_LOOKUP;
|
||||
return WORK_MORE_B;
|
||||
return WORK_MORE_C;
|
||||
}
|
||||
if (ret != SSL_ERROR_NONE) {
|
||||
/*
|
||||
* This is not really an error but the only means to for
|
||||
* a client to detect whether srp is supported.
|
||||
*/
|
||||
if (al != TLS1_AD_UNKNOWN_PSK_IDENTITY)
|
||||
SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_CLIENTHELLO_TLSEXT);
|
||||
else
|
||||
SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
|
||||
SSL_R_PSK_IDENTITY_NOT_FOUND);
|
||||
goto f_err;
|
||||
if (ret < 0) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
s->renegotiate = 2;
|
||||
|
||||
return WORK_FINISHED_STOP;
|
||||
f_err:
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
ossl_statem_set_error(s);
|
||||
err:
|
||||
return WORK_ERROR;
|
||||
}
|
||||
|
||||
int tls_construct_server_hello(SSL *s)
|
||||
int tls_construct_server_hello(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
unsigned char *buf;
|
||||
unsigned char *p, *d;
|
||||
int i, sl;
|
||||
int al = 0;
|
||||
unsigned long l;
|
||||
int compm;
|
||||
size_t sl, len;
|
||||
int version;
|
||||
unsigned char *session_id;
|
||||
int usetls13 = SSL_IS_TLS13(s) || s->hello_retry_request == SSL_HRR_PENDING;
|
||||
|
||||
buf = (unsigned char *)s->init_buf->data;
|
||||
|
||||
/* Do the message type and length last */
|
||||
d = p = ssl_handshake_start(s);
|
||||
|
||||
*(p++) = s->version >> 8;
|
||||
*(p++) = s->version & 0xff;
|
||||
|
||||
/*
|
||||
* Random stuff. Filling of the server_random takes place in
|
||||
* tls_process_client_hello()
|
||||
*/
|
||||
memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE);
|
||||
p += SSL3_RANDOM_SIZE;
|
||||
version = usetls13 ? TLS1_2_VERSION : s->version;
|
||||
if (!WPACKET_put_bytes_u16(pkt, version)
|
||||
/*
|
||||
* Random stuff. Filling of the server_random takes place in
|
||||
* tls_process_client_hello()
|
||||
*/
|
||||
|| !WPACKET_memcpy(pkt,
|
||||
s->hello_retry_request == SSL_HRR_PENDING
|
||||
? hrrrandom : s->s3->server_random,
|
||||
SSL3_RANDOM_SIZE)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-
|
||||
* There are several cases for the session ID to send
|
||||
@@ -1517,6 +2290,8 @@ int tls_construct_server_hello(SSL *s)
|
||||
* session ID.
|
||||
* - However, if we want the new session to be single-use,
|
||||
* we send back a 0-length session ID.
|
||||
* - In TLSv1.3 we echo back the session id sent to us by the client
|
||||
* regardless
|
||||
* s->hit is non-zero in either case of session reuse,
|
||||
* so the following won't overwrite an ID that we're supposed
|
||||
* to send back.
|
||||
@@ -1526,115 +2301,113 @@ int tls_construct_server_hello(SSL *s)
|
||||
&& !s->hit))
|
||||
s->session->session_id_length = 0;
|
||||
|
||||
sl = s->session->session_id_length;
|
||||
if (sl > (int)sizeof(s->session->session_id)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
|
||||
ossl_statem_set_error(s);
|
||||
if (usetls13) {
|
||||
sl = s->tmp_session_id_len;
|
||||
session_id = s->tmp_session_id;
|
||||
} else {
|
||||
sl = s->session->session_id_length;
|
||||
session_id = s->session->session_id;
|
||||
}
|
||||
|
||||
if (sl > sizeof(s->session->session_id)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
*(p++) = sl;
|
||||
memcpy(p, s->session->session_id, sl);
|
||||
p += sl;
|
||||
|
||||
/* put the cipher */
|
||||
i = ssl3_put_cipher_by_char(s->s3->tmp.new_cipher, p);
|
||||
p += i;
|
||||
|
||||
/* put the compression method */
|
||||
/* set up the compression method */
|
||||
#ifdef OPENSSL_NO_COMP
|
||||
*(p++) = 0;
|
||||
compm = 0;
|
||||
#else
|
||||
if (s->s3->tmp.new_compression == NULL)
|
||||
*(p++) = 0;
|
||||
if (usetls13 || s->s3->tmp.new_compression == NULL)
|
||||
compm = 0;
|
||||
else
|
||||
*(p++) = s->s3->tmp.new_compression->id;
|
||||
compm = s->s3->tmp.new_compression->id;
|
||||
#endif
|
||||
|
||||
if (ssl_prepare_serverhello_tlsext(s) <= 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, SSL_R_SERVERHELLO_TLSEXT);
|
||||
ossl_statem_set_error(s);
|
||||
return 0;
|
||||
}
|
||||
if ((p =
|
||||
ssl_add_serverhello_tlsext(s, p, buf + SSL3_RT_MAX_PLAIN_LENGTH,
|
||||
&al)) == NULL) {
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
|
||||
ossl_statem_set_error(s);
|
||||
if (!WPACKET_sub_memcpy_u8(pkt, session_id, sl)
|
||||
|| !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt, &len)
|
||||
|| !WPACKET_put_bytes_u8(pkt, compm)
|
||||
|| !tls_construct_extensions(s, pkt,
|
||||
s->hello_retry_request
|
||||
== SSL_HRR_PENDING
|
||||
? SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST
|
||||
: (SSL_IS_TLS13(s)
|
||||
? SSL_EXT_TLS1_3_SERVER_HELLO
|
||||
: SSL_EXT_TLS1_2_SERVER_HELLO),
|
||||
NULL, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* do the header */
|
||||
l = (p - d);
|
||||
if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_HELLO, l)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
|
||||
ossl_statem_set_error(s);
|
||||
if (s->hello_retry_request == SSL_HRR_PENDING) {
|
||||
/* Ditch the session. We'll create a new one next time around */
|
||||
SSL_SESSION_free(s->session);
|
||||
s->session = NULL;
|
||||
s->hit = 0;
|
||||
|
||||
/*
|
||||
* Re-initialise the Transcript Hash. We're going to prepopulate it with
|
||||
* a synthetic message_hash in place of ClientHello1.
|
||||
*/
|
||||
if (!create_synthetic_message_hash(s, NULL, 0, NULL, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
} else if (!(s->verify_mode & SSL_VERIFY_PEER)
|
||||
&& !ssl3_digest_cached_records(s, 0)) {
|
||||
/* SSLfatal() already called */;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_server_done(SSL *s)
|
||||
int tls_construct_server_done(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_DONE, 0)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_DONE, ERR_R_INTERNAL_ERROR);
|
||||
ossl_statem_set_error(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!s->s3->tmp.cert_request) {
|
||||
if (!ssl3_digest_cached_records(s, 0)) {
|
||||
ossl_statem_set_error(s);
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_server_key_exchange(SSL *s)
|
||||
int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_DH
|
||||
EVP_PKEY *pkdh = NULL;
|
||||
int j;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_EC
|
||||
unsigned char *encodedPoint = NULL;
|
||||
int encodedlen = 0;
|
||||
size_t encodedlen = 0;
|
||||
int curve_id = 0;
|
||||
#endif
|
||||
EVP_PKEY *pkey;
|
||||
const EVP_MD *md = NULL;
|
||||
unsigned char *p, *d;
|
||||
int al, i;
|
||||
const SIGALG_LOOKUP *lu = s->s3->tmp.sigalg;
|
||||
int i;
|
||||
unsigned long type;
|
||||
int n;
|
||||
const BIGNUM *r[4];
|
||||
int nr[4], kn;
|
||||
BUF_MEM *buf;
|
||||
EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
|
||||
EVP_PKEY_CTX *pctx = NULL;
|
||||
size_t paramlen, paramoffset;
|
||||
|
||||
if (!WPACKET_get_total_written(pkt, ¶moffset)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (md_ctx == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
type = s->s3->tmp.new_cipher->algorithm_mkey;
|
||||
|
||||
buf = s->init_buf;
|
||||
|
||||
r[0] = r[1] = r[2] = r[3] = NULL;
|
||||
n = 0;
|
||||
#ifndef OPENSSL_NO_PSK
|
||||
if (type & SSL_PSK) {
|
||||
/*
|
||||
* reserve size for record length and PSK identity hint
|
||||
*/
|
||||
n += 2;
|
||||
if (s->cert->psk_identity_hint)
|
||||
n += strlen(s->cert->psk_identity_hint);
|
||||
}
|
||||
/* Plain PSK or RSAPSK nothing to do */
|
||||
if (type & (SSL_kPSK | SSL_kRSAPSK)) {
|
||||
} else
|
||||
@@ -1651,10 +2424,10 @@ int tls_construct_server_key_exchange(SSL *s)
|
||||
pkdh = EVP_PKEY_new();
|
||||
if (pkdh == NULL || dhp == NULL) {
|
||||
DH_free(dhp);
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
EVP_PKEY_assign_DH(pkdh, dhp);
|
||||
pkdhp = pkdh;
|
||||
@@ -1665,36 +2438,36 @@ int tls_construct_server_key_exchange(SSL *s)
|
||||
DH *dhp = s->cert->dh_tmp_cb(s, 0, 1024);
|
||||
pkdh = ssl_dh_to_pkey(dhp);
|
||||
if (pkdh == NULL) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
pkdhp = pkdh;
|
||||
}
|
||||
if (pkdhp == NULL) {
|
||||
al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
SSL_R_MISSING_TMP_DH_KEY);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
SSL_R_MISSING_TMP_DH_KEY);
|
||||
goto err;
|
||||
}
|
||||
if (!ssl_security(s, SSL_SECOP_TMP_DH,
|
||||
EVP_PKEY_security_bits(pkdhp), 0, pkdhp)) {
|
||||
al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
SSL_R_DH_KEY_TOO_SMALL);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
SSL_R_DH_KEY_TOO_SMALL);
|
||||
goto err;
|
||||
}
|
||||
if (s->s3->tmp.pkey != NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
s->s3->tmp.pkey = ssl_generate_pkey(pkdhp);
|
||||
|
||||
if (s->s3->tmp.pkey == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EVP_LIB);
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -1709,45 +2482,38 @@ int tls_construct_server_key_exchange(SSL *s)
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_EC
|
||||
if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
|
||||
int nid;
|
||||
|
||||
if (s->s3->tmp.pkey != NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Get NID of appropriate shared curve */
|
||||
nid = tls1_shared_curve(s, -2);
|
||||
curve_id = tls1_ec_nid2curve_id(nid);
|
||||
curve_id = tls1_shared_group(s, -2);
|
||||
if (curve_id == 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
|
||||
goto err;
|
||||
}
|
||||
s->s3->tmp.pkey = ssl_generate_pkey_curve(curve_id);
|
||||
s->s3->tmp.pkey = ssl_generate_pkey_group(s, curve_id);
|
||||
/* Generate a new key for this curve */
|
||||
if (s->s3->tmp.pkey == NULL) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EVP_LIB);
|
||||
goto f_err;
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Encode the public key. */
|
||||
encodedlen = EVP_PKEY_get1_tls_encodedpoint(s->s3->tmp.pkey,
|
||||
&encodedPoint);
|
||||
if (encodedlen == 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EC_LIB);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* We only support named (not generic) curves in ECDH ephemeral key
|
||||
* exchanges. In this situation, we need four additional bytes to
|
||||
* encode the entire ServerECDHParams structure.
|
||||
*/
|
||||
n += 4 + encodedlen;
|
||||
|
||||
/*
|
||||
* We'll generate the serverKeyExchange message explicitly so we
|
||||
* can set these to NULLs
|
||||
@@ -1763,8 +2529,9 @@ int tls_construct_server_key_exchange(SSL *s)
|
||||
if ((s->srp_ctx.N == NULL) ||
|
||||
(s->srp_ctx.g == NULL) ||
|
||||
(s->srp_ctx.s == NULL) || (s->srp_ctx.B == NULL)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
SSL_R_MISSING_SRP_PARAM);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
SSL_R_MISSING_SRP_PARAM);
|
||||
goto err;
|
||||
}
|
||||
r[0] = s->srp_ctx.N;
|
||||
@@ -1774,85 +2541,59 @@ int tls_construct_server_key_exchange(SSL *s)
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
|
||||
goto f_err;
|
||||
}
|
||||
for (i = 0; i < 4 && r[i] != NULL; i++) {
|
||||
nr[i] = BN_num_bytes(r[i]);
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
if ((i == 2) && (type & SSL_kSRP))
|
||||
n += 1 + nr[i];
|
||||
else
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DH
|
||||
/*-
|
||||
* for interoperability with some versions of the Microsoft TLS
|
||||
* stack, we need to zero pad the DHE pub key to the same length
|
||||
* as the prime, so use the length of the prime here
|
||||
*/
|
||||
if ((i == 2) && (type & (SSL_kDHE | SSL_kDHEPSK)))
|
||||
n += 2 + nr[0];
|
||||
else
|
||||
#endif
|
||||
n += 2 + nr[i];
|
||||
}
|
||||
|
||||
if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
|
||||
&& !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)) {
|
||||
if ((pkey = ssl_get_sign_pkey(s, s->s3->tmp.new_cipher, &md))
|
||||
== NULL) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
kn = EVP_PKEY_size(pkey);
|
||||
/* Allow space for signature algorithm */
|
||||
if (SSL_USE_SIGALGS(s))
|
||||
kn += 2;
|
||||
/* Allow space for signature length */
|
||||
kn += 2;
|
||||
} else {
|
||||
pkey = NULL;
|
||||
kn = 0;
|
||||
}
|
||||
|
||||
if (!BUF_MEM_grow_clean(buf, n + SSL_HM_HEADER_LENGTH(s) + kn)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_LIB_BUF);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (((s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) != 0)
|
||||
|| ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)) != 0) {
|
||||
lu = NULL;
|
||||
} else if (lu == NULL) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
d = p = ssl_handshake_start(s);
|
||||
|
||||
#ifndef OPENSSL_NO_PSK
|
||||
if (type & SSL_PSK) {
|
||||
/* copy PSK identity hint */
|
||||
if (s->cert->psk_identity_hint) {
|
||||
size_t len = strlen(s->cert->psk_identity_hint);
|
||||
if (len > PSK_MAX_IDENTITY_LEN) {
|
||||
/*
|
||||
* Should not happen - we already checked this when we set
|
||||
* the identity hint
|
||||
*/
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
s2n(len, p);
|
||||
memcpy(p, s->cert->psk_identity_hint, len);
|
||||
p += len;
|
||||
} else {
|
||||
s2n(0, p);
|
||||
size_t len = (s->cert->psk_identity_hint == NULL)
|
||||
? 0 : strlen(s->cert->psk_identity_hint);
|
||||
|
||||
/*
|
||||
* It should not happen that len > PSK_MAX_IDENTITY_LEN - we already
|
||||
* checked this when we set the identity hint - but just in case
|
||||
*/
|
||||
if (len > PSK_MAX_IDENTITY_LEN
|
||||
|| !WPACKET_sub_memcpy_u16(pkt, s->cert->psk_identity_hint,
|
||||
len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < 4 && r[i] != NULL; i++) {
|
||||
unsigned char *binval;
|
||||
int res;
|
||||
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
if ((i == 2) && (type & SSL_kSRP)) {
|
||||
*p = nr[i];
|
||||
p++;
|
||||
res = WPACKET_start_sub_packet_u8(pkt);
|
||||
} else
|
||||
#endif
|
||||
res = WPACKET_start_sub_packet_u16(pkt);
|
||||
|
||||
if (!res) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_DH
|
||||
/*-
|
||||
* for interoperability with some versions of the Microsoft TLS
|
||||
@@ -1860,97 +2601,124 @@ int tls_construct_server_key_exchange(SSL *s)
|
||||
* as the prime
|
||||
*/
|
||||
if ((i == 2) && (type & (SSL_kDHE | SSL_kDHEPSK))) {
|
||||
s2n(nr[0], p);
|
||||
for (j = 0; j < (nr[0] - nr[2]); ++j) {
|
||||
*p = 0;
|
||||
++p;
|
||||
size_t len = BN_num_bytes(r[0]) - BN_num_bytes(r[2]);
|
||||
|
||||
if (len > 0) {
|
||||
if (!WPACKET_allocate_bytes(pkt, len, &binval)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
memset(binval, 0, len);
|
||||
}
|
||||
} else
|
||||
}
|
||||
#endif
|
||||
s2n(nr[i], p);
|
||||
BN_bn2bin(r[i], p);
|
||||
p += nr[i];
|
||||
if (!WPACKET_allocate_bytes(pkt, BN_num_bytes(r[i]), &binval)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
BN_bn2bin(r[i], binval);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
|
||||
/*
|
||||
* XXX: For now, we only support named (not generic) curves. In
|
||||
* this situation, the serverKeyExchange message has: [1 byte
|
||||
* CurveType], [2 byte CurveName] [1 byte length of encoded
|
||||
* point], followed by the actual encoded point itself
|
||||
* We only support named (not generic) curves. In this situation, the
|
||||
* ServerKeyExchange message has: [1 byte CurveType], [2 byte CurveName]
|
||||
* [1 byte length of encoded point], followed by the actual encoded
|
||||
* point itself
|
||||
*/
|
||||
*p = NAMED_CURVE_TYPE;
|
||||
p += 1;
|
||||
*p = 0;
|
||||
p += 1;
|
||||
*p = curve_id;
|
||||
p += 1;
|
||||
*p = encodedlen;
|
||||
p += 1;
|
||||
memcpy(p, encodedPoint, encodedlen);
|
||||
if (!WPACKET_put_bytes_u8(pkt, NAMED_CURVE_TYPE)
|
||||
|| !WPACKET_put_bytes_u8(pkt, 0)
|
||||
|| !WPACKET_put_bytes_u8(pkt, curve_id)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, encodedPoint, encodedlen)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_free(encodedPoint);
|
||||
encodedPoint = NULL;
|
||||
p += encodedlen;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* not anonymous */
|
||||
if (pkey != NULL) {
|
||||
/*
|
||||
* n is the length of the params, they start at &(d[4]) and p
|
||||
* points to the space at the end.
|
||||
*/
|
||||
if (md) {
|
||||
/* send signature algorithm */
|
||||
if (SSL_USE_SIGALGS(s)) {
|
||||
if (!tls12_get_sigandhash(p, pkey, md)) {
|
||||
/* Should never happen */
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto f_err;
|
||||
}
|
||||
p += 2;
|
||||
}
|
||||
#ifdef SSL_DEBUG
|
||||
fprintf(stderr, "Using hash %s\n", EVP_MD_name(md));
|
||||
#endif
|
||||
if (EVP_SignInit_ex(md_ctx, md, NULL) <= 0
|
||||
|| EVP_SignUpdate(md_ctx, &(s->s3->client_random[0]),
|
||||
SSL3_RANDOM_SIZE) <= 0
|
||||
|| EVP_SignUpdate(md_ctx, &(s->s3->server_random[0]),
|
||||
SSL3_RANDOM_SIZE) <= 0
|
||||
|| EVP_SignUpdate(md_ctx, d, n) <= 0
|
||||
|| EVP_SignFinal(md_ctx, &(p[2]),
|
||||
(unsigned int *)&i, pkey) <= 0) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_LIB_EVP);
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
s2n(i, p);
|
||||
n += i + 2;
|
||||
if (SSL_USE_SIGALGS(s))
|
||||
n += 2;
|
||||
} else {
|
||||
/* Is this error check actually needed? */
|
||||
al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
SSL_R_UNKNOWN_PKEY_TYPE);
|
||||
goto f_err;
|
||||
}
|
||||
}
|
||||
if (lu != NULL) {
|
||||
EVP_PKEY *pkey = s->s3->tmp.cert->privatekey;
|
||||
const EVP_MD *md;
|
||||
unsigned char *sigbytes1, *sigbytes2, *tbs;
|
||||
size_t siglen, tbslen;
|
||||
int rv;
|
||||
|
||||
if (!ssl_set_handshake_header(s, SSL3_MT_SERVER_KEY_EXCHANGE, n)) {
|
||||
al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
|
||||
goto f_err;
|
||||
if (pkey == NULL || !tls1_lookup_md(lu, &md)) {
|
||||
/* Should never happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
/* Get length of the parameters we have written above */
|
||||
if (!WPACKET_get_length(pkt, ¶mlen)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
/* send signature algorithm */
|
||||
if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* Create the signature. We don't know the actual length of the sig
|
||||
* until after we've created it, so we reserve enough bytes for it
|
||||
* up front, and then properly allocate them in the WPACKET
|
||||
* afterwards.
|
||||
*/
|
||||
siglen = EVP_PKEY_size(pkey);
|
||||
if (!WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1)
|
||||
|| EVP_DigestSignInit(md_ctx, &pctx, md, NULL, pkey) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (lu->sig == EVP_PKEY_RSA_PSS) {
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
|
||||
|| EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, RSA_PSS_SALTLEN_DIGEST) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
tbslen = construct_key_exchange_tbs(s, &tbs,
|
||||
s->init_buf->data + paramoffset,
|
||||
paramlen);
|
||||
if (tbslen == 0) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
rv = EVP_DigestSign(md_ctx, sigbytes1, &siglen, tbs, tbslen);
|
||||
OPENSSL_free(tbs);
|
||||
if (rv <= 0 || !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2)
|
||||
|| sigbytes1 != sigbytes2) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
return 1;
|
||||
f_err:
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
err:
|
||||
#ifndef OPENSSL_NO_DH
|
||||
EVP_PKEY_free(pkdh);
|
||||
@@ -1959,81 +2727,82 @@ int tls_construct_server_key_exchange(SSL *s)
|
||||
OPENSSL_free(encodedPoint);
|
||||
#endif
|
||||
EVP_MD_CTX_free(md_ctx);
|
||||
ossl_statem_set_error(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tls_construct_certificate_request(SSL *s)
|
||||
int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
unsigned char *p, *d;
|
||||
int i, j, nl, off, n;
|
||||
STACK_OF(X509_NAME) *sk = NULL;
|
||||
X509_NAME *name;
|
||||
BUF_MEM *buf;
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
/* Send random context when doing post-handshake auth */
|
||||
if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
|
||||
OPENSSL_free(s->pha_context);
|
||||
s->pha_context_len = 32;
|
||||
if ((s->pha_context = OPENSSL_malloc(s->pha_context_len)) == NULL
|
||||
|| ssl_randbytes(s, s->pha_context, s->pha_context_len) <= 0
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, s->pha_context, s->pha_context_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
/* reset the handshake hash back to just after the ClientFinished */
|
||||
if (!tls13_restore_handshake_digest_for_pha(s)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!WPACKET_put_bytes_u8(pkt, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
buf = s->init_buf;
|
||||
|
||||
d = p = ssl_handshake_start(s);
|
||||
if (!tls_construct_extensions(s, pkt,
|
||||
SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, NULL,
|
||||
0)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* get the list of acceptable cert types */
|
||||
p++;
|
||||
n = ssl3_get_req_cert_type(s, p);
|
||||
d[0] = n;
|
||||
p += n;
|
||||
n++;
|
||||
if (!WPACKET_start_sub_packet_u8(pkt)
|
||||
|| !ssl3_get_req_cert_type(s, pkt) || !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (SSL_USE_SIGALGS(s)) {
|
||||
const unsigned char *psigs;
|
||||
unsigned char *etmp = p;
|
||||
nl = tls12_get_psigalgs(s, 1, &psigs);
|
||||
/* Skip over length for now */
|
||||
p += 2;
|
||||
nl = tls12_copy_sigalgs(s, p, psigs, nl);
|
||||
/* Now fill in length */
|
||||
s2n(nl, etmp);
|
||||
p += nl;
|
||||
n += nl + 2;
|
||||
}
|
||||
const uint16_t *psigs;
|
||||
size_t nl = tls12_get_psigalgs(s, 1, &psigs);
|
||||
|
||||
off = n;
|
||||
p += 2;
|
||||
n += 2;
|
||||
|
||||
sk = SSL_get_client_CA_list(s);
|
||||
nl = 0;
|
||||
if (sk != NULL) {
|
||||
for (i = 0; i < sk_X509_NAME_num(sk); i++) {
|
||||
name = sk_X509_NAME_value(sk, i);
|
||||
j = i2d_X509_NAME(name, NULL);
|
||||
if (!BUF_MEM_grow_clean(buf, SSL_HM_HEADER_LENGTH(s) + n + j + 2)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_BUF_LIB);
|
||||
goto err;
|
||||
}
|
||||
p = ssl_handshake_start(s) + n;
|
||||
s2n(j, p);
|
||||
i2d_X509_NAME(name, &p);
|
||||
n += 2 + j;
|
||||
nl += 2 + j;
|
||||
if (!WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)
|
||||
|| !tls12_copy_sigalgs(s, pkt, psigs, nl)
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/* else no CA names */
|
||||
p = ssl_handshake_start(s) + off;
|
||||
s2n(nl, p);
|
||||
|
||||
if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_REQUEST, n)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
if (!construct_ca_names(s, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
done:
|
||||
s->certreqs_sent++;
|
||||
s->s3->tmp.cert_request = 1;
|
||||
|
||||
return 1;
|
||||
err:
|
||||
ossl_statem_set_error(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt, int *al)
|
||||
static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_PSK
|
||||
unsigned char psk[PSK_MAX_PSK_LEN];
|
||||
@@ -2041,24 +2810,24 @@ static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt, int *al)
|
||||
PACKET psk_identity;
|
||||
|
||||
if (!PACKET_get_length_prefixed_2(pkt, &psk_identity)) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, SSL_R_LENGTH_MISMATCH);
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
if (PACKET_remaining(&psk_identity) > PSK_MAX_IDENTITY_LEN) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, SSL_R_DATA_LENGTH_TOO_LONG);
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
|
||||
SSL_R_DATA_LENGTH_TOO_LONG);
|
||||
return 0;
|
||||
}
|
||||
if (s->psk_server_callback == NULL) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, SSL_R_PSK_NO_SERVER_CB);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
|
||||
SSL_R_PSK_NO_SERVER_CB);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!PACKET_strndup(&psk_identity, &s->session->psk_identity)) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2066,16 +2835,16 @@ static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt, int *al)
|
||||
psk, sizeof(psk));
|
||||
|
||||
if (psklen > PSK_MAX_PSK_LEN) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
} else if (psklen == 0) {
|
||||
/*
|
||||
* PSK related to the given identity not found
|
||||
*/
|
||||
*al = SSL_AD_UNKNOWN_PSK_IDENTITY;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
|
||||
SSL_R_PSK_IDENTITY_NOT_FOUND);
|
||||
SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY,
|
||||
SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
|
||||
SSL_R_PSK_IDENTITY_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2084,8 +2853,8 @@ static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt, int *al)
|
||||
OPENSSL_cleanse(psk, psklen);
|
||||
|
||||
if (s->s3->tmp.psk == NULL) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_MALLOC_FAILURE);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2094,13 +2863,13 @@ static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt, int *al)
|
||||
return 1;
|
||||
#else
|
||||
/* Should never happen */
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
|
||||
static int tls_process_cke_rsa(SSL *s, PACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_RSA
|
||||
unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
|
||||
@@ -2112,10 +2881,10 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
|
||||
unsigned char *rsa_decrypt = NULL;
|
||||
int ret = 0;
|
||||
|
||||
rsa = EVP_PKEY_get0_RSA(s->cert->pkeys[SSL_PKEY_RSA_ENC].privatekey);
|
||||
rsa = EVP_PKEY_get0_RSA(s->cert->pkeys[SSL_PKEY_RSA].privatekey);
|
||||
if (rsa == NULL) {
|
||||
*al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, SSL_R_MISSING_RSA_CERTIFICATE);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
|
||||
SSL_R_MISSING_RSA_CERTIFICATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2125,8 +2894,8 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
|
||||
} else {
|
||||
if (!PACKET_get_length_prefixed_2(pkt, &enc_premaster)
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, SSL_R_LENGTH_MISMATCH);
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -2138,15 +2907,15 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
|
||||
* their ciphertext cannot accommodate a premaster secret anyway.
|
||||
*/
|
||||
if (RSA_size(rsa) < SSL_MAX_MASTER_KEY_LENGTH) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
|
||||
RSA_R_KEY_SIZE_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rsa_decrypt = OPENSSL_malloc(RSA_size(rsa));
|
||||
if (rsa_decrypt == NULL) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, ERR_R_MALLOC_FAILURE);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2158,18 +2927,26 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
|
||||
* fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
|
||||
*/
|
||||
|
||||
if (RAND_bytes(rand_premaster_secret, sizeof(rand_premaster_secret)) <= 0)
|
||||
if (ssl_randbytes(s, rand_premaster_secret,
|
||||
sizeof(rand_premaster_secret)) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decrypt with no padding. PKCS#1 padding will be removed as part of
|
||||
* the timing-sensitive code below.
|
||||
*/
|
||||
decrypt_len = RSA_private_decrypt(PACKET_remaining(&enc_premaster),
|
||||
PACKET_data(&enc_premaster),
|
||||
rsa_decrypt, rsa, RSA_NO_PADDING);
|
||||
if (decrypt_len < 0)
|
||||
/* TODO(size_t): Convert this function */
|
||||
decrypt_len = (int)RSA_private_decrypt((int)PACKET_remaining(&enc_premaster),
|
||||
PACKET_data(&enc_premaster),
|
||||
rsa_decrypt, rsa, RSA_NO_PADDING);
|
||||
if (decrypt_len < 0) {
|
||||
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Check the padding. See RFC 3447, section 7.2.2. */
|
||||
|
||||
@@ -2179,8 +2956,8 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
|
||||
* PS is at least 8 bytes.
|
||||
*/
|
||||
if (decrypt_len < 11 + SSL_MAX_MASTER_KEY_LENGTH) {
|
||||
*al = SSL_AD_DECRYPT_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, SSL_R_DECRYPTION_FAILED);
|
||||
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
|
||||
SSL_R_DECRYPTION_FAILED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -2247,8 +3024,7 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
|
||||
|
||||
if (!ssl_generate_master_secret(s, rsa_decrypt + padding_len,
|
||||
sizeof(rand_premaster_secret), 0)) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, ERR_R_INTERNAL_ERROR);
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -2258,13 +3034,13 @@ static int tls_process_cke_rsa(SSL *s, PACKET *pkt, int *al)
|
||||
return ret;
|
||||
#else
|
||||
/* Should never happen */
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_RSA, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_process_cke_dhe(SSL *s, PACKET *pkt, int *al)
|
||||
static int tls_process_cke_dhe(SSL *s, PACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_DH
|
||||
EVP_PKEY *skey = NULL;
|
||||
@@ -2276,47 +3052,47 @@ static int tls_process_cke_dhe(SSL *s, PACKET *pkt, int *al)
|
||||
int ret = 0;
|
||||
|
||||
if (!PACKET_get_net_2(pkt, &i) || PACKET_remaining(pkt) != i) {
|
||||
*al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_DHE,
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
|
||||
SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
|
||||
goto err;
|
||||
}
|
||||
skey = s->s3->tmp.pkey;
|
||||
if (skey == NULL) {
|
||||
*al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, SSL_R_MISSING_TMP_DH_KEY);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
|
||||
SSL_R_MISSING_TMP_DH_KEY);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (PACKET_remaining(pkt) == 0L) {
|
||||
*al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, SSL_R_MISSING_TMP_DH_KEY);
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
|
||||
SSL_R_MISSING_TMP_DH_KEY);
|
||||
goto err;
|
||||
}
|
||||
if (!PACKET_get_bytes(pkt, &data, i)) {
|
||||
/* We already checked we have enough data */
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
ckey = EVP_PKEY_new();
|
||||
if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) == 0) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, SSL_R_BN_LIB);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
|
||||
SSL_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
cdh = EVP_PKEY_get0_DH(ckey);
|
||||
pub_key = BN_bin2bn(data, i, NULL);
|
||||
|
||||
if (pub_key == NULL || !DH_set0_key(cdh, pub_key, NULL)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
if (pub_key != NULL)
|
||||
BN_free(pub_key);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ssl_derive(s, skey, ckey) == 0) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, ERR_R_INTERNAL_ERROR);
|
||||
if (ssl_derive(s, skey, ckey, 1) == 0) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -2328,13 +3104,13 @@ static int tls_process_cke_dhe(SSL *s, PACKET *pkt, int *al)
|
||||
return ret;
|
||||
#else
|
||||
/* Should never happen */
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_DHE, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt, int *al)
|
||||
static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_EC
|
||||
EVP_PKEY *skey = s->s3->tmp.pkey;
|
||||
@@ -2343,8 +3119,8 @@ static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt, int *al)
|
||||
|
||||
if (PACKET_remaining(pkt) == 0L) {
|
||||
/* We don't support ECDH client auth */
|
||||
*al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, SSL_R_MISSING_TMP_ECDH_KEY);
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_CKE_ECDHE,
|
||||
SSL_R_MISSING_TMP_ECDH_KEY);
|
||||
goto err;
|
||||
} else {
|
||||
unsigned int i;
|
||||
@@ -2358,25 +3134,25 @@ static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt, int *al)
|
||||
/* Get encoded point length */
|
||||
if (!PACKET_get_1(pkt, &i) || !PACKET_get_bytes(pkt, &data, i)
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, SSL_R_LENGTH_MISMATCH);
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
ckey = EVP_PKEY_new();
|
||||
if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) <= 0) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, ERR_R_EVP_LIB);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
|
||||
ERR_R_EVP_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (EVP_PKEY_set1_tls_encodedpoint(ckey, data, i) == 0) {
|
||||
*al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, ERR_R_EC_LIB);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
|
||||
ERR_R_EC_LIB);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (ssl_derive(s, skey, ckey) == 0) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
|
||||
if (ssl_derive(s, skey, ckey, 1) == 0) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -2389,13 +3165,13 @@ static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt, int *al)
|
||||
return ret;
|
||||
#else
|
||||
/* Should never happen */
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_ECDHE, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_process_cke_srp(SSL *s, PACKET *pkt, int *al)
|
||||
static int tls_process_cke_srp(SSL *s, PACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_SRP
|
||||
unsigned int i;
|
||||
@@ -2403,41 +3179,43 @@ static int tls_process_cke_srp(SSL *s, PACKET *pkt, int *al)
|
||||
|
||||
if (!PACKET_get_net_2(pkt, &i)
|
||||
|| !PACKET_get_bytes(pkt, &data, i)) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, SSL_R_BAD_SRP_A_LENGTH);
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
|
||||
SSL_R_BAD_SRP_A_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
if ((s->srp_ctx.A = BN_bin2bn(data, i, NULL)) == NULL) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, ERR_R_BN_LIB);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
|
||||
ERR_R_BN_LIB);
|
||||
return 0;
|
||||
}
|
||||
if (BN_ucmp(s->srp_ctx.A, s->srp_ctx.N) >= 0 || BN_is_zero(s->srp_ctx.A)) {
|
||||
*al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, SSL_R_BAD_SRP_PARAMETERS);
|
||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_CKE_SRP,
|
||||
SSL_R_BAD_SRP_PARAMETERS);
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_free(s->session->srp_username);
|
||||
s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
|
||||
if (s->session->srp_username == NULL) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, ERR_R_MALLOC_FAILURE);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!srp_generate_server_master_secret(s)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, ERR_R_INTERNAL_ERROR);
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
#else
|
||||
/* Should never happen */
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_SRP, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int tls_process_cke_gost(SSL *s, PACKET *pkt, int *al)
|
||||
static int tls_process_cke_gost(SSL *s, PACKET *pkt)
|
||||
{
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
EVP_PKEY_CTX *pkey_ctx;
|
||||
@@ -2448,7 +3226,7 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt, int *al)
|
||||
unsigned long alg_a;
|
||||
int Ttag, Tclass;
|
||||
long Tlen;
|
||||
long sess_key_len;
|
||||
size_t sess_key_len;
|
||||
const unsigned char *data;
|
||||
int ret = 0;
|
||||
|
||||
@@ -2471,13 +3249,13 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt, int *al)
|
||||
|
||||
pkey_ctx = EVP_PKEY_CTX_new(pk, NULL);
|
||||
if (pkey_ctx == NULL) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, ERR_R_MALLOC_FAILURE);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
@@ -2494,35 +3272,35 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt, int *al)
|
||||
/* Decrypt session key */
|
||||
sess_key_len = PACKET_remaining(pkt);
|
||||
if (!PACKET_get_bytes(pkt, &data, sess_key_len)) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
/* TODO(size_t): Convert this function */
|
||||
if (ASN1_get_object((const unsigned char **)&data, &Tlen, &Ttag,
|
||||
&Tclass, sess_key_len) != V_ASN1_CONSTRUCTED
|
||||
&Tclass, (long)sess_key_len) != V_ASN1_CONSTRUCTED
|
||||
|| Ttag != V_ASN1_SEQUENCE || Tclass != V_ASN1_UNIVERSAL) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, SSL_R_DECRYPTION_FAILED);
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
|
||||
SSL_R_DECRYPTION_FAILED);
|
||||
goto err;
|
||||
}
|
||||
start = data;
|
||||
inlen = Tlen;
|
||||
if (EVP_PKEY_decrypt
|
||||
(pkey_ctx, premaster_secret, &outlen, start, inlen) <= 0) {
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, SSL_R_DECRYPTION_FAILED);
|
||||
if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start,
|
||||
inlen) <= 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
|
||||
SSL_R_DECRYPTION_FAILED);
|
||||
goto err;
|
||||
}
|
||||
/* Generate master secret */
|
||||
if (!ssl_generate_master_secret(s, premaster_secret,
|
||||
sizeof(premaster_secret), 0)) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, ERR_R_INTERNAL_ERROR);
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
/* Check if pubkey from client certificate was used */
|
||||
if (EVP_PKEY_CTX_ctrl
|
||||
(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2, NULL) > 0)
|
||||
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2,
|
||||
NULL) > 0)
|
||||
s->statem.no_cert_verify = 1;
|
||||
|
||||
ret = 1;
|
||||
@@ -2531,68 +3309,75 @@ static int tls_process_cke_gost(SSL *s, PACKET *pkt, int *al)
|
||||
return ret;
|
||||
#else
|
||||
/* Should never happen */
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CKE_GOST, ERR_R_INTERNAL_ERROR);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
|
||||
{
|
||||
int al = -1;
|
||||
unsigned long alg_k;
|
||||
|
||||
alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
|
||||
|
||||
/* For PSK parse and retrieve identity, obtain PSK key */
|
||||
if ((alg_k & SSL_PSK) && !tls_process_cke_psk_preamble(s, pkt, &al))
|
||||
if ((alg_k & SSL_PSK) && !tls_process_cke_psk_preamble(s, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (alg_k & SSL_kPSK) {
|
||||
/* Identity extracted earlier: should be nothing left */
|
||||
if (PACKET_remaining(pkt) != 0) {
|
||||
al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
/* PSK handled by ssl_generate_master_secret */
|
||||
if (!ssl_generate_master_secret(s, NULL, 0, 0)) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
|
||||
if (!tls_process_cke_rsa(s, pkt, &al))
|
||||
if (!tls_process_cke_rsa(s, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
|
||||
if (!tls_process_cke_dhe(s, pkt, &al))
|
||||
if (!tls_process_cke_dhe(s, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
|
||||
if (!tls_process_cke_ecdhe(s, pkt, &al))
|
||||
if (!tls_process_cke_ecdhe(s, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else if (alg_k & SSL_kSRP) {
|
||||
if (!tls_process_cke_srp(s, pkt, &al))
|
||||
if (!tls_process_cke_srp(s, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else if (alg_k & SSL_kGOST) {
|
||||
if (!tls_process_cke_gost(s, pkt, &al))
|
||||
if (!tls_process_cke_gost(s, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
|
||||
SSL_R_UNKNOWN_CIPHER_TYPE);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
|
||||
SSL_R_UNKNOWN_CIPHER_TYPE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return MSG_PROCESS_CONTINUE_PROCESSING;
|
||||
err:
|
||||
if (al != -1)
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
#ifndef OPENSSL_NO_PSK
|
||||
OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
|
||||
s->s3->tmp.psk = NULL;
|
||||
#endif
|
||||
ossl_statem_set_error(s);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
@@ -2614,8 +3399,10 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
|
||||
sizeof(sctpauthkey), labelbuffer,
|
||||
sizeof(labelbuffer), NULL, 0,
|
||||
0) <= 0) {
|
||||
ossl_statem_set_error(s);
|
||||
return WORK_ERROR;;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return WORK_ERROR;
|
||||
}
|
||||
|
||||
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
|
||||
@@ -2630,15 +3417,15 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
|
||||
* the handshake_buffer
|
||||
*/
|
||||
if (!ssl3_digest_cached_records(s, 0)) {
|
||||
ossl_statem_set_error(s);
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
return WORK_FINISHED_CONTINUE;
|
||||
} else {
|
||||
if (!s->s3->handshake_buffer) {
|
||||
SSLerr(SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
ossl_statem_set_error(s);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return WORK_ERROR;
|
||||
}
|
||||
/*
|
||||
@@ -2646,7 +3433,7 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
|
||||
* extms we've done this already so this is a no-op
|
||||
*/
|
||||
if (!ssl3_digest_cached_records(s, 1)) {
|
||||
ossl_statem_set_error(s);
|
||||
/* SSLfatal() already called */
|
||||
return WORK_ERROR;
|
||||
}
|
||||
}
|
||||
@@ -2654,216 +3441,90 @@ WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
|
||||
return WORK_FINISHED_CONTINUE;
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
|
||||
{
|
||||
EVP_PKEY *pkey = NULL;
|
||||
const unsigned char *sig, *data;
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
unsigned char *gost_data = NULL;
|
||||
#endif
|
||||
int al, ret = MSG_PROCESS_ERROR;
|
||||
int type = 0, j;
|
||||
unsigned int len;
|
||||
X509 *peer;
|
||||
const EVP_MD *md = NULL;
|
||||
long hdatalen = 0;
|
||||
void *hdata;
|
||||
|
||||
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
|
||||
|
||||
if (mctx == NULL) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
peer = s->session->peer;
|
||||
pkey = X509_get0_pubkey(peer);
|
||||
if (pkey == NULL) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
type = X509_certificate_type(peer, pkey);
|
||||
|
||||
if (!(type & EVP_PKT_SIGN)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY,
|
||||
SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
|
||||
al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
if (SSL_USE_SIGALGS(s)) {
|
||||
int rv;
|
||||
|
||||
if (!PACKET_get_bytes(pkt, &sig, 2)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
rv = tls12_check_peer_sigalg(&md, s, sig, pkey);
|
||||
if (rv == -1) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
goto f_err;
|
||||
} else if (rv == 0) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
#ifdef SSL_DEBUG
|
||||
fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
|
||||
#endif
|
||||
} else {
|
||||
/* Use default digest for this key type */
|
||||
int idx = ssl_cert_type(NULL, pkey);
|
||||
if (idx >= 0)
|
||||
md = s->s3->tmp.md[idx];
|
||||
if (md == NULL) {
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for broken implementations of GOST ciphersuites */
|
||||
/*
|
||||
* If key is GOST and len is exactly 64 or 128, it is signature without
|
||||
* length field (CryptoPro implementations at least till TLS 1.2)
|
||||
*/
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
if (!SSL_USE_SIGALGS(s)
|
||||
&& ((PACKET_remaining(pkt) == 64
|
||||
&& (EVP_PKEY_id(pkey) == NID_id_GostR3410_2001
|
||||
|| EVP_PKEY_id(pkey) == NID_id_GostR3410_2012_256))
|
||||
|| (PACKET_remaining(pkt) == 128
|
||||
&& EVP_PKEY_id(pkey) == NID_id_GostR3410_2012_512))) {
|
||||
len = PACKET_remaining(pkt);
|
||||
} else
|
||||
#endif
|
||||
if (!PACKET_get_net_2(pkt, &len)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_LENGTH_MISMATCH);
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
j = EVP_PKEY_size(pkey);
|
||||
if (((int)len > j) || ((int)PACKET_remaining(pkt) > j)
|
||||
|| (PACKET_remaining(pkt) == 0)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_WRONG_SIGNATURE_SIZE);
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
if (!PACKET_get_bytes(pkt, &data, len)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_LENGTH_MISMATCH);
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
|
||||
if (hdatalen <= 0) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
#ifdef SSL_DEBUG
|
||||
fprintf(stderr, "Using client verify alg %s\n", EVP_MD_name(md));
|
||||
#endif
|
||||
if (!EVP_VerifyInit_ex(mctx, md, NULL)
|
||||
|| !EVP_VerifyUpdate(mctx, hdata, hdatalen)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
{
|
||||
int pktype = EVP_PKEY_id(pkey);
|
||||
if (pktype == NID_id_GostR3410_2001
|
||||
|| pktype == NID_id_GostR3410_2012_256
|
||||
|| pktype == NID_id_GostR3410_2012_512) {
|
||||
if ((gost_data = OPENSSL_malloc(len)) == NULL) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_MALLOC_FAILURE);
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
BUF_reverse(gost_data, data, len);
|
||||
data = gost_data;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (s->version == SSL3_VERSION
|
||||
&& !EVP_MD_CTX_ctrl(mctx, EVP_CTRL_SSL3_MASTER_SECRET,
|
||||
s->session->master_key_length,
|
||||
s->session->master_key)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, ERR_R_EVP_LIB);
|
||||
al = SSL_AD_INTERNAL_ERROR;
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
if (EVP_VerifyFinal(mctx, data, len, pkey) <= 0) {
|
||||
al = SSL_AD_DECRYPT_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CERT_VERIFY, SSL_R_BAD_SIGNATURE);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
ret = MSG_PROCESS_CONTINUE_READING;
|
||||
if (0) {
|
||||
f_err:
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
ossl_statem_set_error(s);
|
||||
}
|
||||
BIO_free(s->s3->handshake_buffer);
|
||||
s->s3->handshake_buffer = NULL;
|
||||
EVP_MD_CTX_free(mctx);
|
||||
#ifndef OPENSSL_NO_GOST
|
||||
OPENSSL_free(gost_data);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
|
||||
{
|
||||
int i, al = SSL_AD_INTERNAL_ERROR, ret = MSG_PROCESS_ERROR;
|
||||
int i;
|
||||
MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
|
||||
X509 *x = NULL;
|
||||
unsigned long l, llen;
|
||||
unsigned long l;
|
||||
const unsigned char *certstart, *certbytes;
|
||||
STACK_OF(X509) *sk = NULL;
|
||||
PACKET spkt;
|
||||
PACKET spkt, context;
|
||||
size_t chainidx;
|
||||
SSL_SESSION *new_sess = NULL;
|
||||
|
||||
if ((sk = sk_X509_new_null()) == NULL) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!PACKET_get_net_3(pkt, &llen)
|
||||
|| !PACKET_get_sub_packet(pkt, &spkt, llen)
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, SSL_R_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
if (SSL_IS_TLS13(s) && (!PACKET_get_length_prefixed_1(pkt, &context)
|
||||
|| (s->pha_context == NULL && PACKET_remaining(&context) != 0)
|
||||
|| (s->pha_context != NULL &&
|
||||
!PACKET_equal(&context, s->pha_context, s->pha_context_len)))) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
SSL_R_INVALID_CONTEXT);
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (PACKET_remaining(&spkt) > 0) {
|
||||
if (!PACKET_get_length_prefixed_3(pkt, &spkt)
|
||||
|| PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (chainidx = 0; PACKET_remaining(&spkt) > 0; chainidx++) {
|
||||
if (!PACKET_get_net_3(&spkt, &l)
|
||||
|| !PACKET_get_bytes(&spkt, &certbytes, l)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
SSL_R_CERT_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
SSL_R_CERT_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
certstart = certbytes;
|
||||
x = d2i_X509(NULL, (const unsigned char **)&certbytes, l);
|
||||
if (x == NULL) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_ASN1_LIB);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_ASN1_LIB);
|
||||
goto err;
|
||||
}
|
||||
if (certbytes != (certstart + l)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
SSL_R_CERT_LENGTH_MISMATCH);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
SSL_R_CERT_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
RAW_EXTENSION *rawexts = NULL;
|
||||
PACKET extensions;
|
||||
|
||||
if (!PACKET_get_length_prefixed_2(&spkt, &extensions)) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR,
|
||||
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
SSL_R_BAD_LENGTH);
|
||||
goto err;
|
||||
}
|
||||
if (!tls_collect_extensions(s, &extensions,
|
||||
SSL_EXT_TLS1_3_CERTIFICATE, &rawexts,
|
||||
NULL, chainidx == 0)
|
||||
|| !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE,
|
||||
rawexts, x, chainidx,
|
||||
PACKET_remaining(&spkt) == 0)) {
|
||||
OPENSSL_free(rawexts);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_free(rawexts);
|
||||
}
|
||||
|
||||
if (!sk_X509_push(sk, x)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_MALLOC_FAILURE);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
x = NULL;
|
||||
}
|
||||
@@ -2871,103 +3532,202 @@ MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
|
||||
if (sk_X509_num(sk) <= 0) {
|
||||
/* TLS does not mind 0 certs returned */
|
||||
if (s->version == SSL3_VERSION) {
|
||||
al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
SSL_R_NO_CERTIFICATES_RETURNED);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
SSL_R_NO_CERTIFICATES_RETURNED);
|
||||
goto err;
|
||||
}
|
||||
/* Fail for TLS only if we required a certificate */
|
||||
else if ((s->verify_mode & SSL_VERIFY_PEER) &&
|
||||
(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
|
||||
al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_CERTIFICATE_REQUIRED,
|
||||
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
|
||||
goto err;
|
||||
}
|
||||
/* No client certificate so digest cached records */
|
||||
if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, 0)) {
|
||||
goto f_err;
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
EVP_PKEY *pkey;
|
||||
i = ssl_verify_cert_chain(s, sk);
|
||||
if (i <= 0) {
|
||||
al = ssl_verify_alarm_type(s->verify_result);
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
SSL_R_CERTIFICATE_VERIFY_FAILED);
|
||||
goto f_err;
|
||||
SSLfatal(s, ssl_verify_alarm_type(s->verify_result),
|
||||
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
SSL_R_CERTIFICATE_VERIFY_FAILED);
|
||||
goto err;
|
||||
}
|
||||
if (i > 1) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, i);
|
||||
al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, i);
|
||||
goto err;
|
||||
}
|
||||
pkey = X509_get0_pubkey(sk_X509_value(sk, 0));
|
||||
if (pkey == NULL) {
|
||||
al = SSL3_AD_HANDSHAKE_FAILURE;
|
||||
SSLerr(SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
SSL_R_UNKNOWN_CERTIFICATE_TYPE);
|
||||
goto f_err;
|
||||
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
SSL_R_UNKNOWN_CERTIFICATE_TYPE);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Sessions must be immutable once they go into the session cache. Otherwise
|
||||
* we can get multi-thread problems. Therefore we don't "update" sessions,
|
||||
* we replace them with a duplicate. Here, we need to do this every time
|
||||
* a new certificate is received via post-handshake authentication, as the
|
||||
* session may have already gone into the session cache.
|
||||
*/
|
||||
|
||||
if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
|
||||
int m = s->session_ctx->session_cache_mode;
|
||||
|
||||
if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (m & SSL_SESS_CACHE_SERVER) {
|
||||
/*
|
||||
* Remove the old session from the cache. We carry on if this fails
|
||||
*/
|
||||
SSL_CTX_remove_session(s->session_ctx, s->session);
|
||||
}
|
||||
|
||||
SSL_SESSION_free(s->session);
|
||||
s->session = new_sess;
|
||||
}
|
||||
|
||||
X509_free(s->session->peer);
|
||||
s->session->peer = sk_X509_shift(sk);
|
||||
s->session->verify_result = s->verify_result;
|
||||
|
||||
sk_X509_pop_free(s->session->peer_chain, X509_free);
|
||||
s->session->peer_chain = sk;
|
||||
|
||||
if (new_sess != NULL)
|
||||
ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
|
||||
|
||||
/*
|
||||
* Freeze the handshake buffer. For <TLS1.3 we do this after the CKE
|
||||
* message
|
||||
*/
|
||||
if (SSL_IS_TLS13(s) && !ssl3_digest_cached_records(s, 1)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inconsistency alert: cert_chain does *not* include the peer's own
|
||||
* certificate, while we do include it in statem_clnt.c
|
||||
*/
|
||||
sk = NULL;
|
||||
ret = MSG_PROCESS_CONTINUE_READING;
|
||||
goto done;
|
||||
|
||||
f_err:
|
||||
ssl3_send_alert(s, SSL3_AL_FATAL, al);
|
||||
ossl_statem_set_error(s);
|
||||
done:
|
||||
/* Save the current hash state for when we receive the CertificateVerify */
|
||||
if (SSL_IS_TLS13(s)
|
||||
&& !ssl_handshake_hash(s, s->cert_verify_hash,
|
||||
sizeof(s->cert_verify_hash),
|
||||
&s->cert_verify_hash_len)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = MSG_PROCESS_CONTINUE_READING;
|
||||
|
||||
err:
|
||||
X509_free(x);
|
||||
sk_X509_pop_free(sk, X509_free);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tls_construct_server_certificate(SSL *s)
|
||||
int tls_construct_server_certificate(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
CERT_PKEY *cpk;
|
||||
CERT_PKEY *cpk = s->s3->tmp.cert;
|
||||
|
||||
cpk = ssl_get_server_send_pkey(s);
|
||||
if (cpk == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
|
||||
ossl_statem_set_error(s);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!ssl3_output_cert_chain(s, cpk)) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
|
||||
ossl_statem_set_error(s);
|
||||
/*
|
||||
* In TLSv1.3 the certificate chain is always preceded by a 0 length context
|
||||
* for the server Certificate message
|
||||
*/
|
||||
if (SSL_IS_TLS13(s) && !WPACKET_put_bytes_u8(pkt, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
if (!ssl3_output_cert_chain(s, pkt, cpk)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_construct_new_session_ticket(SSL *s)
|
||||
int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
unsigned char *senc = NULL;
|
||||
EVP_CIPHER_CTX *ctx = NULL;
|
||||
HMAC_CTX *hctx = NULL;
|
||||
unsigned char *p, *macstart;
|
||||
unsigned char *p, *encdata1, *encdata2, *macdata1, *macdata2;
|
||||
const unsigned char *const_p;
|
||||
int len, slen_full, slen;
|
||||
int len, slen_full, slen, lenfinal;
|
||||
SSL_SESSION *sess;
|
||||
unsigned int hlen;
|
||||
SSL_CTX *tctx = s->session_ctx;
|
||||
unsigned char iv[EVP_MAX_IV_LENGTH];
|
||||
unsigned char key_name[TLSEXT_KEYNAME_LENGTH];
|
||||
int iv_len;
|
||||
size_t macoffset, macendoffset;
|
||||
union {
|
||||
unsigned char age_add_c[sizeof(uint32_t)];
|
||||
uint32_t age_add;
|
||||
} age_add_u;
|
||||
|
||||
if (SSL_IS_TLS13(s)) {
|
||||
if (ssl_randbytes(s, age_add_u.age_add_c, sizeof(age_add_u)) <= 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
s->session->ext.tick_age_add = age_add_u.age_add;
|
||||
/*
|
||||
* ticket_nonce is set to a single 0 byte because we only ever send a
|
||||
* single ticket per connection. IMPORTANT: If we ever support multiple
|
||||
* tickets per connection then this will need to be changed.
|
||||
*/
|
||||
OPENSSL_free(s->session->ext.tick_nonce);
|
||||
s->session->ext.tick_nonce = OPENSSL_zalloc(sizeof(char));
|
||||
if (s->session->ext.tick_nonce == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
s->session->ext.tick_nonce_len = 1;
|
||||
s->session->time = (long)time(NULL);
|
||||
if (s->s3->alpn_selected != NULL) {
|
||||
OPENSSL_free(s->session->ext.alpn_selected);
|
||||
s->session->ext.alpn_selected =
|
||||
OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len);
|
||||
if (s->session->ext.alpn_selected == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
|
||||
ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
s->session->ext.alpn_selected_len = s->s3->alpn_selected_len;
|
||||
}
|
||||
s->session->ext.max_early_data = s->max_early_data;
|
||||
}
|
||||
|
||||
/* get session encoding length */
|
||||
slen_full = i2d_SSL_SESSION(s->session, NULL);
|
||||
@@ -2976,145 +3736,164 @@ int tls_construct_new_session_ticket(SSL *s)
|
||||
* long
|
||||
*/
|
||||
if (slen_full == 0 || slen_full > 0xFF00) {
|
||||
ossl_statem_set_error(s);
|
||||
return 0;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
senc = OPENSSL_malloc(slen_full);
|
||||
if (senc == NULL) {
|
||||
ossl_statem_set_error(s);
|
||||
return 0;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx = EVP_CIPHER_CTX_new();
|
||||
hctx = HMAC_CTX_new();
|
||||
if (ctx == NULL || hctx == NULL) {
|
||||
SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
p = senc;
|
||||
if (!i2d_SSL_SESSION(s->session, &p))
|
||||
if (!i2d_SSL_SESSION(s->session, &p)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
* create a fresh copy (not shared with other threads) to clean up
|
||||
*/
|
||||
const_p = senc;
|
||||
sess = d2i_SSL_SESSION(NULL, &const_p, slen_full);
|
||||
if (sess == NULL)
|
||||
if (sess == NULL) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
sess->session_id_length = 0; /* ID is irrelevant for the ticket */
|
||||
|
||||
slen = i2d_SSL_SESSION(sess, NULL);
|
||||
if (slen == 0 || slen > slen_full) { /* shouldn't ever happen */
|
||||
if (slen == 0 || slen > slen_full) {
|
||||
/* shouldn't ever happen */
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
SSL_SESSION_free(sess);
|
||||
goto err;
|
||||
}
|
||||
p = senc;
|
||||
if (!i2d_SSL_SESSION(sess, &p)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
SSL_SESSION_free(sess);
|
||||
goto err;
|
||||
}
|
||||
SSL_SESSION_free(sess);
|
||||
|
||||
/*-
|
||||
* Grow buffer if need be: the length calculation is as
|
||||
* follows handshake_header_length +
|
||||
* 4 (ticket lifetime hint) + 2 (ticket length) +
|
||||
* sizeof(keyname) + max_iv_len (iv length) +
|
||||
* max_enc_block_size (max encrypted session * length) +
|
||||
* max_md_size (HMAC) + session_length.
|
||||
*/
|
||||
if (!BUF_MEM_grow(s->init_buf,
|
||||
SSL_HM_HEADER_LENGTH(s) + 6 + sizeof(key_name) +
|
||||
EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH +
|
||||
EVP_MAX_MD_SIZE + slen))
|
||||
goto err;
|
||||
|
||||
p = ssl_handshake_start(s);
|
||||
/*
|
||||
* Initialize HMAC and cipher contexts. If callback present it does
|
||||
* all the work otherwise use generated values from parent ctx.
|
||||
*/
|
||||
if (tctx->tlsext_ticket_key_cb) {
|
||||
if (tctx->ext.ticket_key_cb) {
|
||||
/* if 0 is returned, write an empty ticket */
|
||||
int ret = tctx->tlsext_ticket_key_cb(s, key_name, iv, ctx,
|
||||
int ret = tctx->ext.ticket_key_cb(s, key_name, iv, ctx,
|
||||
hctx, 1);
|
||||
|
||||
if (ret == 0) {
|
||||
l2n(0, p); /* timeout */
|
||||
s2n(0, p); /* length */
|
||||
if (!ssl_set_handshake_header
|
||||
(s, SSL3_MT_NEWSESSION_TICKET, p - ssl_handshake_start(s)))
|
||||
|
||||
/* Put timeout and length */
|
||||
if (!WPACKET_put_bytes_u32(pkt, 0)
|
||||
|| !WPACKET_put_bytes_u16(pkt, 0)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_free(senc);
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
HMAC_CTX_free(hctx);
|
||||
return 1;
|
||||
}
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
|
||||
SSL_R_CALLBACK_FAILED);
|
||||
goto err;
|
||||
}
|
||||
iv_len = EVP_CIPHER_CTX_iv_length(ctx);
|
||||
} else {
|
||||
const EVP_CIPHER *cipher = EVP_aes_256_cbc();
|
||||
|
||||
iv_len = EVP_CIPHER_iv_length(cipher);
|
||||
if (RAND_bytes(iv, iv_len) <= 0)
|
||||
if (ssl_randbytes(s, iv, iv_len) <= 0
|
||||
|| !EVP_EncryptInit_ex(ctx, cipher, NULL,
|
||||
tctx->ext.tick_aes_key, iv)
|
||||
|| !HMAC_Init_ex(hctx, tctx->ext.tick_hmac_key,
|
||||
sizeof(tctx->ext.tick_hmac_key),
|
||||
EVP_sha256(), NULL)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
if (!EVP_EncryptInit_ex(ctx, cipher, NULL,
|
||||
tctx->tlsext_tick_aes_key, iv))
|
||||
goto err;
|
||||
if (!HMAC_Init_ex(hctx, tctx->tlsext_tick_hmac_key,
|
||||
sizeof(tctx->tlsext_tick_hmac_key),
|
||||
EVP_sha256(), NULL))
|
||||
goto err;
|
||||
memcpy(key_name, tctx->tlsext_tick_key_name,
|
||||
sizeof(tctx->tlsext_tick_key_name));
|
||||
}
|
||||
memcpy(key_name, tctx->ext.tick_key_name,
|
||||
sizeof(tctx->ext.tick_key_name));
|
||||
}
|
||||
|
||||
/*
|
||||
* Ticket lifetime hint (advisory only): We leave this unspecified
|
||||
* for resumed session (for simplicity), and guess that tickets for
|
||||
* new sessions will live as long as their sessions.
|
||||
* Ticket lifetime hint: For TLSv1.2 this is advisory only and we leave this
|
||||
* unspecified for resumed session (for simplicity).
|
||||
* In TLSv1.3 we reset the "time" field above, and always specify the
|
||||
* timeout.
|
||||
*/
|
||||
l2n(s->hit ? 0 : s->session->timeout, p);
|
||||
|
||||
/* Skip ticket length for now */
|
||||
p += 2;
|
||||
/* Output key name */
|
||||
macstart = p;
|
||||
memcpy(p, key_name, sizeof(key_name));
|
||||
p += sizeof(key_name);
|
||||
/* output IV */
|
||||
memcpy(p, iv, iv_len);
|
||||
p += iv_len;
|
||||
/* Encrypt session data */
|
||||
if (!EVP_EncryptUpdate(ctx, p, &len, senc, slen))
|
||||
if (!WPACKET_put_bytes_u32(pkt,
|
||||
(s->hit && !SSL_IS_TLS13(s))
|
||||
? 0 : s->session->timeout)
|
||||
|| (SSL_IS_TLS13(s)
|
||||
&& (!WPACKET_put_bytes_u32(pkt, age_add_u.age_add)
|
||||
|| !WPACKET_sub_memcpy_u8(pkt, s->session->ext.tick_nonce,
|
||||
s->session->ext.tick_nonce_len)))
|
||||
/* Now the actual ticket data */
|
||||
|| !WPACKET_start_sub_packet_u16(pkt)
|
||||
|| !WPACKET_get_total_written(pkt, &macoffset)
|
||||
/* Output key name */
|
||||
|| !WPACKET_memcpy(pkt, key_name, sizeof(key_name))
|
||||
/* output IV */
|
||||
|| !WPACKET_memcpy(pkt, iv, iv_len)
|
||||
|| !WPACKET_reserve_bytes(pkt, slen + EVP_MAX_BLOCK_LENGTH,
|
||||
&encdata1)
|
||||
/* Encrypt session data */
|
||||
|| !EVP_EncryptUpdate(ctx, encdata1, &len, senc, slen)
|
||||
|| !WPACKET_allocate_bytes(pkt, len, &encdata2)
|
||||
|| encdata1 != encdata2
|
||||
|| !EVP_EncryptFinal(ctx, encdata1 + len, &lenfinal)
|
||||
|| !WPACKET_allocate_bytes(pkt, lenfinal, &encdata2)
|
||||
|| encdata1 + len != encdata2
|
||||
|| len + lenfinal > slen + EVP_MAX_BLOCK_LENGTH
|
||||
|| !WPACKET_get_total_written(pkt, &macendoffset)
|
||||
|| !HMAC_Update(hctx,
|
||||
(unsigned char *)s->init_buf->data + macoffset,
|
||||
macendoffset - macoffset)
|
||||
|| !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &macdata1)
|
||||
|| !HMAC_Final(hctx, macdata1, &hlen)
|
||||
|| hlen > EVP_MAX_MD_SIZE
|
||||
|| !WPACKET_allocate_bytes(pkt, hlen, &macdata2)
|
||||
|| macdata1 != macdata2
|
||||
|| !WPACKET_close(pkt)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
|
||||
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
p += len;
|
||||
if (!EVP_EncryptFinal(ctx, p, &len))
|
||||
}
|
||||
if (SSL_IS_TLS13(s)
|
||||
&& !tls_construct_extensions(s, pkt,
|
||||
SSL_EXT_TLS1_3_NEW_SESSION_TICKET,
|
||||
NULL, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
goto err;
|
||||
p += len;
|
||||
|
||||
if (!HMAC_Update(hctx, macstart, p - macstart))
|
||||
goto err;
|
||||
if (!HMAC_Final(hctx, p, &hlen))
|
||||
goto err;
|
||||
|
||||
}
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
HMAC_CTX_free(hctx);
|
||||
ctx = NULL;
|
||||
hctx = NULL;
|
||||
|
||||
p += hlen;
|
||||
/* Now write out lengths: p points to end of data written */
|
||||
/* Total length */
|
||||
len = p - ssl_handshake_start(s);
|
||||
/* Skip ticket lifetime hint */
|
||||
p = ssl_handshake_start(s) + 4;
|
||||
s2n(len - 6, p);
|
||||
if (!ssl_set_handshake_header(s, SSL3_MT_NEWSESSION_TICKET, len))
|
||||
goto err;
|
||||
OPENSSL_free(senc);
|
||||
|
||||
return 1;
|
||||
@@ -3122,42 +3901,34 @@ int tls_construct_new_session_ticket(SSL *s)
|
||||
OPENSSL_free(senc);
|
||||
EVP_CIPHER_CTX_free(ctx);
|
||||
HMAC_CTX_free(hctx);
|
||||
ossl_statem_set_error(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tls_construct_cert_status(SSL *s)
|
||||
/*
|
||||
* In TLSv1.3 this is called from the extensions code, otherwise it is used to
|
||||
* create a separate message. Returns 1 on success or 0 on failure.
|
||||
*/
|
||||
int tls_construct_cert_status_body(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
unsigned char *p;
|
||||
size_t msglen;
|
||||
|
||||
/*-
|
||||
* Grow buffer if need be: the length calculation is as
|
||||
* follows handshake_header_length +
|
||||
* 1 (ocsp response type) + 3 (ocsp response length)
|
||||
* + (ocsp response)
|
||||
*/
|
||||
msglen = 4 + s->tlsext_ocsp_resplen;
|
||||
if (!BUF_MEM_grow(s->init_buf, SSL_HM_HEADER_LENGTH(s) + msglen))
|
||||
goto err;
|
||||
|
||||
p = ssl_handshake_start(s);
|
||||
|
||||
/* status type */
|
||||
*(p++) = s->tlsext_status_type;
|
||||
/* length of OCSP response */
|
||||
l2n3(s->tlsext_ocsp_resplen, p);
|
||||
/* actual response */
|
||||
memcpy(p, s->tlsext_ocsp_resp, s->tlsext_ocsp_resplen);
|
||||
|
||||
if (!ssl_set_handshake_header(s, SSL3_MT_CERTIFICATE_STATUS, msglen))
|
||||
goto err;
|
||||
if (!WPACKET_put_bytes_u8(pkt, s->ext.status_type)
|
||||
|| !WPACKET_sub_memcpy_u24(pkt, s->ext.ocsp.resp,
|
||||
s->ext.ocsp.resp_len)) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
err:
|
||||
ossl_statem_set_error(s);
|
||||
return 0;
|
||||
int tls_construct_cert_status(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
if (!tls_construct_cert_status_body(s, pkt)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_NEXTPROTONEG
|
||||
@@ -3180,163 +3951,67 @@ MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt)
|
||||
if (!PACKET_get_length_prefixed_1(pkt, &next_proto)
|
||||
|| !PACKET_get_length_prefixed_1(pkt, &padding)
|
||||
|| PACKET_remaining(pkt) > 0) {
|
||||
SSLerr(SSL_F_TLS_PROCESS_NEXT_PROTO, SSL_R_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEXT_PROTO,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
if (!PACKET_memdup(&next_proto, &s->next_proto_negotiated, &next_proto_len)) {
|
||||
s->next_proto_negotiated_len = 0;
|
||||
goto err;
|
||||
if (!PACKET_memdup(&next_proto, &s->ext.npn, &next_proto_len)) {
|
||||
s->ext.npn_len = 0;
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEXT_PROTO,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
s->next_proto_negotiated_len = (unsigned char)next_proto_len;
|
||||
s->ext.npn_len = (unsigned char)next_proto_len;
|
||||
|
||||
return MSG_PROCESS_CONTINUE_READING;
|
||||
err:
|
||||
ossl_statem_set_error(s);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SSLV2_CIPHER_LEN 3
|
||||
|
||||
STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,
|
||||
PACKET *cipher_suites,
|
||||
STACK_OF(SSL_CIPHER) **skp,
|
||||
int sslv2format, int *al)
|
||||
static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt)
|
||||
{
|
||||
const SSL_CIPHER *c;
|
||||
STACK_OF(SSL_CIPHER) *sk;
|
||||
int n;
|
||||
/* 3 = SSLV2_CIPHER_LEN > TLS_CIPHER_LEN = 2. */
|
||||
unsigned char cipher[SSLV2_CIPHER_LEN];
|
||||
|
||||
s->s3->send_connection_binding = 0;
|
||||
|
||||
n = sslv2format ? SSLV2_CIPHER_LEN : TLS_CIPHER_LEN;
|
||||
|
||||
if (PACKET_remaining(cipher_suites) == 0) {
|
||||
SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, SSL_R_NO_CIPHERS_SPECIFIED);
|
||||
*al = SSL_AD_ILLEGAL_PARAMETER;
|
||||
return NULL;
|
||||
if (!tls_construct_extensions(s, pkt, SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
|
||||
NULL, 0)) {
|
||||
/* SSLfatal() already called */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (PACKET_remaining(cipher_suites) % n != 0) {
|
||||
SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,
|
||||
SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
|
||||
*al = SSL_AD_DECODE_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sk = sk_SSL_CIPHER_new_null();
|
||||
if (sk == NULL) {
|
||||
SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sslv2format) {
|
||||
size_t numciphers = PACKET_remaining(cipher_suites) / n;
|
||||
PACKET sslv2ciphers = *cipher_suites;
|
||||
unsigned int leadbyte;
|
||||
unsigned char *raw;
|
||||
|
||||
/*
|
||||
* We store the raw ciphers list in SSLv3+ format so we need to do some
|
||||
* preprocessing to convert the list first. If there are any SSLv2 only
|
||||
* ciphersuites with a non-zero leading byte then we are going to
|
||||
* slightly over allocate because we won't store those. But that isn't a
|
||||
* problem.
|
||||
*/
|
||||
raw = OPENSSL_malloc(numciphers * TLS_CIPHER_LEN);
|
||||
s->s3->tmp.ciphers_raw = raw;
|
||||
if (raw == NULL) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
goto err;
|
||||
}
|
||||
for (s->s3->tmp.ciphers_rawlen = 0;
|
||||
PACKET_remaining(&sslv2ciphers) > 0;
|
||||
raw += TLS_CIPHER_LEN) {
|
||||
if (!PACKET_get_1(&sslv2ciphers, &leadbyte)
|
||||
|| (leadbyte == 0
|
||||
&& !PACKET_copy_bytes(&sslv2ciphers, raw,
|
||||
TLS_CIPHER_LEN))
|
||||
|| (leadbyte != 0
|
||||
&& !PACKET_forward(&sslv2ciphers, TLS_CIPHER_LEN))) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
OPENSSL_free(s->s3->tmp.ciphers_raw);
|
||||
s->s3->tmp.ciphers_raw = NULL;
|
||||
s->s3->tmp.ciphers_rawlen = 0;
|
||||
goto err;
|
||||
}
|
||||
if (leadbyte == 0)
|
||||
s->s3->tmp.ciphers_rawlen += TLS_CIPHER_LEN;
|
||||
}
|
||||
} else if (!PACKET_memdup(cipher_suites, &s->s3->tmp.ciphers_raw,
|
||||
&s->s3->tmp.ciphers_rawlen)) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (PACKET_copy_bytes(cipher_suites, cipher, n)) {
|
||||
/*
|
||||
* SSLv3 ciphers wrapped in an SSLv2-compatible ClientHello have the
|
||||
* first byte set to zero, while true SSLv2 ciphers have a non-zero
|
||||
* first byte. We don't support any true SSLv2 ciphers, so skip them.
|
||||
*/
|
||||
if (sslv2format && cipher[0] != '\0')
|
||||
continue;
|
||||
|
||||
/* Check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV */
|
||||
if ((cipher[n - 2] == ((SSL3_CK_SCSV >> 8) & 0xff)) &&
|
||||
(cipher[n - 1] == (SSL3_CK_SCSV & 0xff))) {
|
||||
/* SCSV fatal if renegotiating */
|
||||
if (s->renegotiate) {
|
||||
SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,
|
||||
SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
|
||||
*al = SSL_AD_HANDSHAKE_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
s->s3->send_connection_binding = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check for TLS_FALLBACK_SCSV */
|
||||
if ((cipher[n - 2] == ((SSL3_CK_FALLBACK_SCSV >> 8) & 0xff)) &&
|
||||
(cipher[n - 1] == (SSL3_CK_FALLBACK_SCSV & 0xff))) {
|
||||
/*
|
||||
* The SCSV indicates that the client previously tried a higher
|
||||
* version. Fail if the current version is an unexpected
|
||||
* downgrade.
|
||||
*/
|
||||
if (!ssl_check_version_downgrade(s)) {
|
||||
SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,
|
||||
SSL_R_INAPPROPRIATE_FALLBACK);
|
||||
*al = SSL_AD_INAPPROPRIATE_FALLBACK;
|
||||
goto err;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* For SSLv2-compat, ignore leading 0-byte. */
|
||||
c = ssl_get_cipher_by_char(s, sslv2format ? &cipher[1] : cipher);
|
||||
if (c != NULL) {
|
||||
if (!sk_SSL_CIPHER_push(sk, c)) {
|
||||
SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (PACKET_remaining(cipher_suites) > 0) {
|
||||
*al = SSL_AD_INTERNAL_ERROR;
|
||||
SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
*skp = sk;
|
||||
return sk;
|
||||
err:
|
||||
sk_SSL_CIPHER_free(sk);
|
||||
return NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt)
|
||||
{
|
||||
if (PACKET_remaining(pkt) != 0) {
|
||||
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
|
||||
SSL_R_LENGTH_MISMATCH);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
if (s->early_data_state != SSL_EARLY_DATA_READING
|
||||
&& s->early_data_state != SSL_EARLY_DATA_READ_RETRY) {
|
||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
|
||||
ERR_R_INTERNAL_ERROR);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* EndOfEarlyData signals a key change so the end of the message must be on
|
||||
* a record boundary.
|
||||
*/
|
||||
if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
|
||||
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
|
||||
SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
|
||||
SSL_R_NOT_ON_RECORD_BOUNDARY);
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
|
||||
if (!s->method->ssl3_enc->change_cipher_state(s,
|
||||
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_READ)) {
|
||||
/* SSLfatal() already called */
|
||||
return MSG_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
return MSG_PROCESS_CONTINUE_READING;
|
||||
}
|
||||
Reference in New Issue
Block a user