:-'Generic Commit'

This commit is contained in:
Your Name
2025-05-28 19:34:06 +12:00
parent e858ab18d1
commit f1944617e5
4355 changed files with 1238762 additions and 1 deletions

View File

@ -0,0 +1,63 @@
State Machine Design
====================
This file provides some guidance on the thinking behind the design of the
state machine code to aid future maintenance.
The state machine code replaces an older state machine present in OpenSSL
versions 1.0.2 and below. The new state machine has the following objectives:
- Remove duplication of state code between client and server
- Remove duplication of state code between TLS and DTLS
- Simplify transitions and bring the logic together in a single location
so that it is easier to validate
- Remove duplication of code between each of the message handling functions
- Receive a message first and then work out whether that is a valid
transition - not the other way around (the other way causes lots of issues
where we are expecting one type of message next but actually get something
else)
- Separate message flow state from handshake state (in order to better
understand each)
- message flow state = when to flush buffers; handling restarts in the
event of NBIO events; handling the common flow of steps for reading a
message and the common flow of steps for writing a message etc
- handshake state = what handshake message are we working on now
- Control complexity: only the state machine can change state: keep all
the state changes local to the state machine component
The message flow state machine is divided into a reading sub-state machine and a
writing sub-state machine. See the source comments in statem.c for a more
detailed description of the various states and transitions possible.
Conceptually the state machine component is designed as follows:
libssl
|
---------------------------|-----statem.h--------------------------------------
|
_______V____________________
| |
| statem.c |
| |
| Core state machine code |
|____________________________|
statem_local.h ^ ^
_________| |_______
| |
_____________|____________ _____________|____________
| | | |
| statem_clnt.c | | statem_srvr.c |
| | | |
| TLS/DTLS client specific | | TLS/DTLS server specific |
| state machine code | | state machine code |
|__________________________| |__________________________|
| |_______________|__ |
| ________________| | |
| | | |
____________V_______V________ ________V______V_______________
| | | |
| statem_lib.c | | statem_dtls.c |
| | | |
| Non core functions common | | Non core functions common to |
| to both servers and clients | | both DTLS servers and clients |
|_____________________________| |_______________________________|

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
ssl/statem/extensions.o: ssl/statem/extensions.c include/internal/nelem.h \
include/internal/cryptlib.h include/openssl/crypto.h \
include/openssl/e_os2.h include/openssl/opensslconf.h \
include/openssl/opensslv.h include/openssl/safestack.h \
include/openssl/stack.h include/openssl/ossl_typ.h \
include/openssl/cryptoerr.h include/openssl/symhacks.h \
include/openssl/buffer.h include/openssl/buffererr.h \
include/openssl/bio.h include/openssl/bioerr.h include/openssl/err.h \
include/openssl/lhash.h ssl/statem/../ssl_local.h e_os.h \
include/openssl/comp.h include/openssl/comperr.h include/openssl/rsa.h \
include/openssl/asn1.h include/openssl/asn1err.h include/openssl/bn.h \
include/openssl/bnerr.h include/openssl/rsaerr.h include/openssl/dsa.h \
include/openssl/dh.h include/openssl/dherr.h include/openssl/dsaerr.h \
include/openssl/ssl.h include/openssl/x509.h include/openssl/evp.h \
include/openssl/evperr.h include/openssl/objects.h \
include/openssl/obj_mac.h include/openssl/objectserr.h \
include/openssl/ec.h include/openssl/ecerr.h include/openssl/sha.h \
include/openssl/x509err.h include/openssl/x509_vfy.h \
include/openssl/pkcs7.h include/openssl/pkcs7err.h include/openssl/pem.h \
include/openssl/pemerr.h include/openssl/hmac.h include/openssl/async.h \
include/openssl/asyncerr.h include/openssl/ct.h include/openssl/cterr.h \
include/openssl/sslerr.h include/openssl/ssl2.h include/openssl/ssl3.h \
include/openssl/tls1.h include/openssl/dtls1.h include/openssl/srtp.h \
ssl/statem/../record/record.h ssl/statem/../statem/statem.h \
ssl/statem/../packet_local.h include/internal/numbers.h \
include/internal/dane.h include/internal/refcount.h \
include/internal/tsan_assist.h ssl/statem/statem_local.h

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,32 @@
ssl/statem/extensions_clnt.o: ssl/statem/extensions_clnt.c \
include/openssl/ocsp.h include/openssl/opensslconf.h \
include/openssl/opensslv.h include/openssl/ossl_typ.h \
include/openssl/e_os2.h include/openssl/x509.h \
include/openssl/symhacks.h include/openssl/buffer.h \
include/openssl/crypto.h include/openssl/safestack.h \
include/openssl/stack.h include/openssl/cryptoerr.h \
include/openssl/buffererr.h include/openssl/evp.h include/openssl/bio.h \
include/openssl/bioerr.h include/openssl/evperr.h \
include/openssl/objects.h include/openssl/obj_mac.h \
include/openssl/asn1.h include/openssl/asn1err.h include/openssl/bn.h \
include/openssl/bnerr.h include/openssl/objectserr.h \
include/openssl/ec.h include/openssl/ecerr.h include/openssl/rsa.h \
include/openssl/rsaerr.h include/openssl/dsa.h include/openssl/dh.h \
include/openssl/dherr.h include/openssl/dsaerr.h include/openssl/sha.h \
include/openssl/x509err.h include/openssl/x509_vfy.h \
include/openssl/lhash.h include/openssl/pkcs7.h \
include/openssl/pkcs7err.h include/openssl/x509v3.h \
include/openssl/conf.h include/openssl/conferr.h \
include/openssl/x509v3err.h include/openssl/ocsperr.h \
ssl/statem/../ssl_local.h e_os.h include/internal/nelem.h \
include/openssl/comp.h include/openssl/comperr.h include/openssl/err.h \
include/openssl/ssl.h include/openssl/pem.h include/openssl/pemerr.h \
include/openssl/hmac.h include/openssl/async.h \
include/openssl/asyncerr.h include/openssl/ct.h include/openssl/cterr.h \
include/openssl/sslerr.h include/openssl/ssl2.h include/openssl/ssl3.h \
include/openssl/tls1.h include/openssl/dtls1.h include/openssl/srtp.h \
ssl/statem/../record/record.h ssl/statem/../statem/statem.h \
ssl/statem/../packet_local.h include/internal/numbers.h \
include/internal/dane.h include/internal/refcount.h \
include/internal/tsan_assist.h include/internal/cryptlib.h \
ssl/statem/statem_local.h

View File

@ -0,0 +1,534 @@
/*
* Copyright 2014-2021 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_local.h"
#include "internal/cryptlib.h"
#include "statem_local.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 or CertificateRequest are marked
* with the SSL_EXT_FLAG_RECEIVED. This is so we know to add the equivalent
* extensions in the response messages
*/
if ((context & (SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST))
!= 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/CertificateRequest */
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;
}
}

View File

@ -0,0 +1,30 @@
ssl/statem/extensions_cust.o: ssl/statem/extensions_cust.c \
include/openssl/ct.h include/openssl/opensslconf.h \
include/openssl/opensslv.h include/openssl/ossl_typ.h \
include/openssl/e_os2.h include/openssl/safestack.h \
include/openssl/stack.h include/openssl/x509.h \
include/openssl/symhacks.h include/openssl/buffer.h \
include/openssl/crypto.h include/openssl/cryptoerr.h \
include/openssl/buffererr.h include/openssl/evp.h include/openssl/bio.h \
include/openssl/bioerr.h include/openssl/evperr.h \
include/openssl/objects.h include/openssl/obj_mac.h \
include/openssl/asn1.h include/openssl/asn1err.h include/openssl/bn.h \
include/openssl/bnerr.h include/openssl/objectserr.h \
include/openssl/ec.h include/openssl/ecerr.h include/openssl/rsa.h \
include/openssl/rsaerr.h include/openssl/dsa.h include/openssl/dh.h \
include/openssl/dherr.h include/openssl/dsaerr.h include/openssl/sha.h \
include/openssl/x509err.h include/openssl/x509_vfy.h \
include/openssl/lhash.h include/openssl/pkcs7.h \
include/openssl/pkcs7err.h include/openssl/cterr.h \
ssl/statem/../ssl_local.h e_os.h include/internal/nelem.h \
include/openssl/comp.h include/openssl/comperr.h include/openssl/err.h \
include/openssl/ssl.h include/openssl/pem.h include/openssl/pemerr.h \
include/openssl/hmac.h include/openssl/async.h \
include/openssl/asyncerr.h include/openssl/sslerr.h \
include/openssl/ssl2.h include/openssl/ssl3.h include/openssl/tls1.h \
include/openssl/dtls1.h include/openssl/srtp.h \
ssl/statem/../record/record.h ssl/statem/../statem/statem.h \
ssl/statem/../packet_local.h include/internal/numbers.h \
include/internal/dane.h include/internal/refcount.h \
include/internal/tsan_assist.h include/internal/cryptlib.h \
ssl/statem/statem_local.h

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,32 @@
ssl/statem/extensions_srvr.o: ssl/statem/extensions_srvr.c \
include/openssl/ocsp.h include/openssl/opensslconf.h \
include/openssl/opensslv.h include/openssl/ossl_typ.h \
include/openssl/e_os2.h include/openssl/x509.h \
include/openssl/symhacks.h include/openssl/buffer.h \
include/openssl/crypto.h include/openssl/safestack.h \
include/openssl/stack.h include/openssl/cryptoerr.h \
include/openssl/buffererr.h include/openssl/evp.h include/openssl/bio.h \
include/openssl/bioerr.h include/openssl/evperr.h \
include/openssl/objects.h include/openssl/obj_mac.h \
include/openssl/asn1.h include/openssl/asn1err.h include/openssl/bn.h \
include/openssl/bnerr.h include/openssl/objectserr.h \
include/openssl/ec.h include/openssl/ecerr.h include/openssl/rsa.h \
include/openssl/rsaerr.h include/openssl/dsa.h include/openssl/dh.h \
include/openssl/dherr.h include/openssl/dsaerr.h include/openssl/sha.h \
include/openssl/x509err.h include/openssl/x509_vfy.h \
include/openssl/lhash.h include/openssl/pkcs7.h \
include/openssl/pkcs7err.h include/openssl/x509v3.h \
include/openssl/conf.h include/openssl/conferr.h \
include/openssl/x509v3err.h include/openssl/ocsperr.h \
ssl/statem/../ssl_local.h e_os.h include/internal/nelem.h \
include/openssl/comp.h include/openssl/comperr.h include/openssl/err.h \
include/openssl/ssl.h include/openssl/pem.h include/openssl/pemerr.h \
include/openssl/hmac.h include/openssl/async.h \
include/openssl/asyncerr.h include/openssl/ct.h include/openssl/cterr.h \
include/openssl/sslerr.h include/openssl/ssl2.h include/openssl/ssl3.h \
include/openssl/tls1.h include/openssl/dtls1.h include/openssl/srtp.h \
ssl/statem/../record/record.h ssl/statem/../statem/statem.h \
ssl/statem/../packet_local.h include/internal/numbers.h \
include/internal/dane.h include/internal/refcount.h \
include/internal/tsan_assist.h ssl/statem/statem_local.h \
include/internal/cryptlib.h

View File

@ -0,0 +1,972 @@
/*
* Copyright 2015-2019 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 "internal/cryptlib.h"
#include <openssl/rand.h>
#include "../ssl_local.h"
#include "statem_local.h"
#include <assert.h>
/*
* This file implements the SSL/TLS/DTLS state machines.
*
* There are two primary state machines:
*
* 1) Message flow state machine
* 2) Handshake state machine
*
* The Message flow state machine controls the reading and sending of messages
* including handling of non-blocking IO events, flushing of the underlying
* write BIO, handling unexpected messages, etc. It is itself broken into two
* separate sub-state machines which control reading and writing respectively.
*
* The Handshake state machine keeps track of the current SSL/TLS handshake
* state. Transitions of the handshake state are the result of events that
* occur within the Message flow state machine.
*
* Overall it looks like this:
*
* --------------------------------------------- -------------------
* | | | |
* | Message flow state machine | | |
* | | | |
* | -------------------- -------------------- | Transition | Handshake state |
* | | MSG_FLOW_READING | | MSG_FLOW_WRITING | | Event | machine |
* | | sub-state | | sub-state | |----------->| |
* | | machine for | | machine for | | | |
* | | reading messages | | writing messages | | | |
* | -------------------- -------------------- | | |
* | | | |
* --------------------------------------------- -------------------
*
*/
/* Sub state machine return values */
typedef enum {
/* Something bad happened or NBIO */
SUB_STATE_ERROR,
/* Sub state finished go to the next sub state */
SUB_STATE_FINISHED,
/* Sub state finished and handshake was completed */
SUB_STATE_END_HANDSHAKE
} SUB_STATE_RETURN;
static int state_machine(SSL *s, int server);
static void init_read_state_machine(SSL *s);
static SUB_STATE_RETURN read_state_machine(SSL *s);
static void init_write_state_machine(SSL *s);
static SUB_STATE_RETURN write_state_machine(SSL *s);
OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl)
{
return ssl->statem.hand_state;
}
int SSL_in_init(const SSL *s)
{
return s->statem.in_init;
}
int SSL_is_init_finished(const SSL *s)
{
return !(s->statem.in_init) && (s->statem.hand_state == TLS_ST_OK);
}
int SSL_in_before(const SSL *s)
{
/*
* Historically being "in before" meant before anything had happened. In the
* current code though we remain in the "before" state for a while after we
* have started the handshake process (e.g. as a server waiting for the
* first message to arrive). There "in before" is taken to mean "in before"
* and not started any handshake process yet.
*/
return (s->statem.hand_state == TLS_ST_BEFORE)
&& (s->statem.state == MSG_FLOW_UNINITED);
}
/*
* Clear the state machine state and reset back to MSG_FLOW_UNINITED
*/
void ossl_statem_clear(SSL *s)
{
s->statem.state = MSG_FLOW_UNINITED;
s->statem.hand_state = TLS_ST_BEFORE;
s->statem.in_init = 1;
s->statem.no_cert_verify = 0;
}
/*
* Set the state machine up ready for a renegotiation handshake
*/
void ossl_statem_set_renegotiate(SSL *s)
{
s->statem.in_init = 1;
s->statem.request_state = TLS_ST_SW_HELLO_REQ;
}
/*
* 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_fatal(SSL *s, int al, int func, int reason, const char *file,
int line)
{
ERR_put_error(ERR_LIB_SSL, func, reason, file, line);
/* We shouldn't call SSLfatal() twice. Once is enough */
if (s->statem.in_init && s->statem.state == MSG_FLOW_ERROR)
return;
s->statem.in_init = 1;
s->statem.state = MSG_FLOW_ERROR;
if (al != SSL_AD_NO_ALERT
&& s->statem.enc_write_state != ENC_WRITE_STATE_INVALID)
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.
*
* Valid return values are:
* 1: Yes
* 0: No
*/
int ossl_statem_in_error(const SSL *s)
{
if (s->statem.state == MSG_FLOW_ERROR)
return 1;
return 0;
}
void ossl_statem_set_in_init(SSL *s, int init)
{
s->statem.in_init = init;
}
int ossl_statem_get_in_handshake(SSL *s)
{
return s->statem.in_handshake;
}
void ossl_statem_set_in_handshake(SSL *s, int inhand)
{
if (inhand)
s->statem.in_handshake++;
else
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
|| s->hello_retry_request == SSL_HRR_COMPLETE)
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;
s->statem.in_init = 1;
/*
* This will get reset (briefly) back to TLS_ST_BEFORE when we enter
* state_machine() because |state| is MSG_FLOW_UNINITED, but until then any
* calls to SSL_in_before() will return false. Also calls to
* SSL_state_string() and SSL_state_string_long() will return something
* sensible.
*/
s->statem.hand_state = TLS_ST_SR_CLNT_HELLO;
}
int ossl_statem_connect(SSL *s)
{
return state_machine(s, 0);
}
int ossl_statem_accept(SSL *s)
{
return state_machine(s, 1);
}
typedef void (*info_cb) (const SSL *, int, int);
static info_cb get_callback(SSL *s)
{
if (s->info_callback != NULL)
return s->info_callback;
else if (s->ctx->info_callback != NULL)
return s->ctx->info_callback;
return NULL;
}
/*
* The main message flow state machine. We start in the MSG_FLOW_UNINITED or
* MSG_FLOW_FINISHED state and finish in MSG_FLOW_FINISHED. Valid states and
* transitions are as follows:
*
* MSG_FLOW_UNINITED MSG_FLOW_FINISHED
* | |
* +-----------------------+
* v
* MSG_FLOW_WRITING <---> MSG_FLOW_READING
* |
* V
* MSG_FLOW_FINISHED
* |
* V
* [SUCCESS]
*
* We may exit at any point due to an error or NBIO event. If an NBIO event
* occurs then we restart at the point we left off when we are recalled.
* MSG_FLOW_WRITING and MSG_FLOW_READING have sub-state machines associated with them.
*
* In addition to the above there is also the MSG_FLOW_ERROR state. We can move
* into that state at any point in the event that an irrecoverable error occurs.
*
* Valid return values are:
* 1: Success
* <=0: NBIO or error
*/
static int state_machine(SSL *s, int server)
{
BUF_MEM *buf = NULL;
void (*cb) (const SSL *ssl, int type, int val) = NULL;
OSSL_STATEM *st = &s->statem;
int ret = -1;
int ssret;
if (st->state == MSG_FLOW_ERROR) {
/* Shouldn't have been called if we're already in the error state */
return -1;
}
ERR_clear_error();
clear_sys_error();
cb = get_callback(s);
st->in_handshake++;
if (!SSL_in_init(s) || SSL_in_before(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
if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
/*
* Notify SCTP BIO socket to enter handshake mode and prevent stream
* identifier other than 0.
*/
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
st->in_handshake, NULL);
}
#endif
/* Initialise state machine */
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) {
if (SSL_IS_FIRST_HANDSHAKE(s) || !SSL_IS_TLS13(s))
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))) {
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
goto end;
}
} else {
if ((s->version >> 8) != SSL3_VERSION_MAJOR) {
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)) {
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;
buf = NULL;
}
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;
/*
* Should have been reset by tls_process_finished, too.
*/
s->s3->change_cipher_spec = 0;
/*
* Ok, we now need to push on a buffering BIO ...but not with
* SCTP
*/
#ifndef OPENSSL_NO_SCTP
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 ((SSL_in_before(s))
|| s->renegotiate) {
if (!tls_setup_handshake(s)) {
/* SSLfatal() already called */
goto end;
}
if (SSL_IS_FIRST_HANDSHAKE(s))
st->read_state_first_init = 1;
}
st->state = MSG_FLOW_WRITING;
init_write_state_machine(s);
}
while (st->state != MSG_FLOW_FINISHED) {
if (st->state == MSG_FLOW_READING) {
ssret = read_state_machine(s);
if (ssret == SUB_STATE_FINISHED) {
st->state = MSG_FLOW_WRITING;
init_write_state_machine(s);
} else {
/* NBIO or error */
goto end;
}
} else if (st->state == MSG_FLOW_WRITING) {
ssret = write_state_machine(s);
if (ssret == SUB_STATE_FINISHED) {
st->state = MSG_FLOW_READING;
init_read_state_machine(s);
} else if (ssret == SUB_STATE_END_HANDSHAKE) {
st->state = MSG_FLOW_FINISHED;
} else {
/* NBIO or error */
goto end;
}
} else {
/* Error */
check_fatal(s, SSL_F_STATE_MACHINE);
SSLerr(SSL_F_STATE_MACHINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
goto end;
}
}
ret = 1;
end:
st->in_handshake--;
#ifndef OPENSSL_NO_SCTP
if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
/*
* Notify SCTP BIO socket to leave handshake mode and allow stream
* identifier other than 0.
*/
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_SET_IN_HANDSHAKE,
st->in_handshake, NULL);
}
#endif
BUF_MEM_free(buf);
if (cb != NULL) {
if (server)
cb(s, SSL_CB_ACCEPT_EXIT, ret);
else
cb(s, SSL_CB_CONNECT_EXIT, ret);
}
return ret;
}
/*
* Initialise the MSG_FLOW_READING sub-state machine
*/
static void init_read_state_machine(SSL *s)
{
OSSL_STATEM *st = &s->statem;
st->read_state = READ_STATE_HEADER;
}
static int grow_init_buf(SSL *s, size_t size) {
size_t msg_offset = (char *)s->init_msg - s->init_buf->data;
if (!BUF_MEM_grow_clean(s->init_buf, (int)size))
return 0;
if (size < msg_offset)
return 0;
s->init_msg = s->init_buf->data + msg_offset;
return 1;
}
/*
* This function implements the sub-state machine when the message flow is in
* MSG_FLOW_READING. The valid sub-states and transitions are:
*
* READ_STATE_HEADER <--+<-------------+
* | | |
* v | |
* READ_STATE_BODY -----+-->READ_STATE_POST_PROCESS
* | |
* +----------------------------+
* v
* [SUB_STATE_FINISHED]
*
* READ_STATE_HEADER has the responsibility for reading in the message header
* and transitioning the state of the handshake state machine.
*
* READ_STATE_BODY reads in the rest of the message and then subsequently
* processes it.
*
* READ_STATE_POST_PROCESS is an optional step that may occur if some post
* processing activity performed on the message may block.
*
* Any of the above states could result in an NBIO event occurring in which case
* control returns to the calling application. When this function is recalled we
* will resume in the same state where we left off.
*/
static SUB_STATE_RETURN read_state_machine(SSL *s)
{
OSSL_STATEM *st = &s->statem;
int ret, mt;
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);
size_t (*max_message_size) (SSL *s);
void (*cb) (const SSL *ssl, int type, int val) = NULL;
cb = get_callback(s);
if (s->server) {
transition = ossl_statem_server_read_transition;
process_message = ossl_statem_server_process_message;
max_message_size = ossl_statem_server_max_message_size;
post_process_message = ossl_statem_server_post_process_message;
} else {
transition = ossl_statem_client_read_transition;
process_message = ossl_statem_client_process_message;
max_message_size = ossl_statem_client_max_message_size;
post_process_message = ossl_statem_client_post_process_message;
}
if (st->read_state_first_init) {
s->first_packet = 1;
st->read_state_first_init = 0;
}
while (1) {
switch (st->read_state) {
case READ_STATE_HEADER:
/* Get the state the peer wants to move to */
if (SSL_IS_DTLS(s)) {
/*
* In DTLS we get the whole message in one go - header and body
*/
ret = dtls_get_message(s, &mt, &len);
} else {
ret = tls_get_message_header(s, &mt);
}
if (ret == 0) {
/* Could be non-blocking IO */
return SUB_STATE_ERROR;
}
if (cb != NULL) {
/* Notify callback of an impending state change */
if (s->server)
cb(s, SSL_CB_ACCEPT_LOOP, 1);
else
cb(s, SSL_CB_CONNECT_LOOP, 1);
}
/*
* Validate that we are allowed to move to the new state and move
* to that state if so
*/
if (!transition(s, mt))
return SUB_STATE_ERROR;
if (s->s3->tmp.message_size > max_message_size(s)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_READ_STATE_MACHINE,
SSL_R_EXCESSIVE_MESSAGE_SIZE);
return SUB_STATE_ERROR;
}
/* dtls_get_message already did this */
if (!SSL_IS_DTLS(s)
&& s->s3->tmp.message_size > 0
&& !grow_init_buf(s, s->s3->tmp.message_size
+ SSL3_HM_HEADER_LENGTH)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
ERR_R_BUF_LIB);
return SUB_STATE_ERROR;
}
st->read_state = READ_STATE_BODY;
/* Fall through */
case READ_STATE_BODY:
if (!SSL_IS_DTLS(s)) {
/* We already got this above for DTLS */
ret = tls_get_message_body(s, &len);
if (ret == 0) {
/* Could be non-blocking IO */
return SUB_STATE_ERROR;
}
}
s->first_packet = 0;
if (!PACKET_buf_init(&pkt, s->init_msg, len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
return SUB_STATE_ERROR;
}
ret = process_message(s, &pkt);
/* Discard the packet data */
s->init_num = 0;
switch (ret) {
case MSG_PROCESS_ERROR:
check_fatal(s, SSL_F_READ_STATE_MACHINE);
return SUB_STATE_ERROR;
case MSG_PROCESS_FINISHED_READING:
if (SSL_IS_DTLS(s)) {
dtls1_stop_timer(s);
}
return SUB_STATE_FINISHED;
case MSG_PROCESS_CONTINUE_PROCESSING:
st->read_state = READ_STATE_POST_PROCESS;
st->read_state_work = WORK_MORE_A;
break;
default:
st->read_state = READ_STATE_HEADER;
break;
}
break;
case READ_STATE_POST_PROCESS:
st->read_state_work = post_process_message(s, st->read_state_work);
switch (st->read_state_work) {
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:
st->read_state = READ_STATE_HEADER;
break;
case WORK_FINISHED_STOP:
if (SSL_IS_DTLS(s)) {
dtls1_stop_timer(s);
}
return SUB_STATE_FINISHED;
}
break;
default:
/* Shouldn't happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_READ_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
return SUB_STATE_ERROR;
}
}
}
/*
* Send a previously constructed message to the peer.
*/
static int statem_do_write(SSL *s)
{
OSSL_STATEM *st = &s->statem;
if (st->hand_state == TLS_ST_CW_CHANGE
|| st->hand_state == TLS_ST_SW_CHANGE) {
if (SSL_IS_DTLS(s))
return dtls1_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC);
else
return ssl3_do_write(s, SSL3_RT_CHANGE_CIPHER_SPEC);
} else {
return ssl_do_write(s);
}
}
/*
* Initialise the MSG_FLOW_WRITING sub-state machine
*/
static void init_write_state_machine(SSL *s)
{
OSSL_STATEM *st = &s->statem;
st->write_state = WRITE_STATE_TRANSITION;
}
/*
* This function implements the sub-state machine when the message flow is in
* MSG_FLOW_WRITING. The valid sub-states and transitions are:
*
* +-> WRITE_STATE_TRANSITION ------> [SUB_STATE_FINISHED]
* | |
* | v
* | WRITE_STATE_PRE_WORK -----> [SUB_STATE_END_HANDSHAKE]
* | |
* | v
* | WRITE_STATE_SEND
* | |
* | v
* | WRITE_STATE_POST_WORK
* | |
* +-------------+
*
* WRITE_STATE_TRANSITION transitions the state of the handshake state machine
* WRITE_STATE_PRE_WORK performs any work necessary to prepare the later
* sending of the message. This could result in an NBIO event occurring in
* which case control returns to the calling application. When this function
* is recalled we will resume in the same state where we left off.
*
* WRITE_STATE_SEND sends the message and performs any work to be done after
* sending.
*
* WRITE_STATE_POST_WORK performs any work necessary after the sending of the
* message has been completed. As for WRITE_STATE_PRE_WORK this could also
* result in an NBIO event.
*/
static SUB_STATE_RETURN write_state_machine(SSL *s)
{
OSSL_STATEM *st = &s->statem;
int ret;
WRITE_TRAN(*transition) (SSL *s);
WORK_STATE(*pre_work) (SSL *s, WORK_STATE wst);
WORK_STATE(*post_work) (SSL *s, WORK_STATE wst);
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);
if (s->server) {
transition = ossl_statem_server_write_transition;
pre_work = ossl_statem_server_pre_work;
post_work = ossl_statem_server_post_work;
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;
get_construct_message_f = ossl_statem_client_construct_message;
}
while (1) {
switch (st->write_state) {
case WRITE_STATE_TRANSITION:
if (cb != NULL) {
/* Notify callback of an impending state change */
if (s->server)
cb(s, SSL_CB_ACCEPT_LOOP, 1);
else
cb(s, SSL_CB_CONNECT_LOOP, 1);
}
switch (transition(s)) {
case WRITE_TRAN_CONTINUE:
st->write_state = WRITE_STATE_PRE_WORK;
st->write_state_work = WORK_MORE_A;
break;
case WRITE_TRAN_FINISHED:
return SUB_STATE_FINISHED;
break;
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)) {
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:
st->write_state = WRITE_STATE_SEND;
break;
case WORK_FINISHED_STOP:
return SUB_STATE_END_HANDSHAKE;
}
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 */
case WRITE_STATE_SEND:
if (SSL_IS_DTLS(s) && st->use_timer) {
dtls1_start_timer(s);
}
ret = statem_do_write(s);
if (ret <= 0) {
return SUB_STATE_ERROR;
}
st->write_state = WRITE_STATE_POST_WORK;
st->write_state_work = WORK_MORE_A;
/* Fall through */
case WRITE_STATE_POST_WORK:
switch (st->write_state_work = post_work(s, st->write_state_work)) {
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:
st->write_state = WRITE_STATE_TRANSITION;
break;
case WORK_FINISHED_STOP:
return SUB_STATE_END_HANDSHAKE;
}
break;
default:
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_WRITE_STATE_MACHINE,
ERR_R_INTERNAL_ERROR);
return SUB_STATE_ERROR;
}
}
}
/*
* Flush the write BIO
*/
int statem_flush(SSL *s)
{
s->rwstate = SSL_WRITING;
if (BIO_flush(s->wbio) <= 0) {
return 0;
}
s->rwstate = SSL_NOTHING;
return 1;
}
/*
* Called by the record layer to determine whether application data is
* allowed to be received in the current handshake state or not.
*
* Return values are:
* 1: Yes (application data allowed)
* 0: No (application data not allowed)
*/
int ossl_statem_app_data_allowed(SSL *s)
{
OSSL_STATEM *st = &s->statem;
if (st->state == MSG_FLOW_UNINITED)
return 0;
if (!s->s3->in_read_app_data || (s->s3->total_renegotiations == 0))
return 0;
if (s->server) {
/*
* If we're a server and we haven't got as far as writing our
* ServerHello yet then we allow app data
*/
if (st->hand_state == TLS_ST_BEFORE
|| st->hand_state == TLS_ST_SR_CLNT_HELLO)
return 1;
} else {
/*
* If we're a client and we haven't read the ServerHello yet then we
* allow app data
*/
if (st->hand_state == TLS_ST_CW_CLNT_HELLO)
return 1;
}
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);
}

View File

@ -0,0 +1,28 @@
ssl/statem/statem.o: ssl/statem/statem.c include/internal/cryptlib.h \
include/openssl/crypto.h include/openssl/e_os2.h \
include/openssl/opensslconf.h include/openssl/opensslv.h \
include/openssl/safestack.h include/openssl/stack.h \
include/openssl/ossl_typ.h include/openssl/cryptoerr.h \
include/openssl/symhacks.h include/openssl/buffer.h \
include/openssl/buffererr.h include/openssl/bio.h \
include/openssl/bioerr.h include/openssl/err.h include/openssl/lhash.h \
include/internal/nelem.h include/openssl/rand.h \
include/openssl/randerr.h ssl/statem/../ssl_local.h e_os.h \
include/openssl/comp.h include/openssl/comperr.h include/openssl/rsa.h \
include/openssl/asn1.h include/openssl/asn1err.h include/openssl/bn.h \
include/openssl/bnerr.h include/openssl/rsaerr.h include/openssl/dsa.h \
include/openssl/dh.h include/openssl/dherr.h include/openssl/dsaerr.h \
include/openssl/ssl.h include/openssl/x509.h include/openssl/evp.h \
include/openssl/evperr.h include/openssl/objects.h \
include/openssl/obj_mac.h include/openssl/objectserr.h \
include/openssl/ec.h include/openssl/ecerr.h include/openssl/sha.h \
include/openssl/x509err.h include/openssl/x509_vfy.h \
include/openssl/pkcs7.h include/openssl/pkcs7err.h include/openssl/pem.h \
include/openssl/pemerr.h include/openssl/hmac.h include/openssl/async.h \
include/openssl/asyncerr.h include/openssl/ct.h include/openssl/cterr.h \
include/openssl/sslerr.h include/openssl/ssl2.h include/openssl/ssl3.h \
include/openssl/tls1.h include/openssl/dtls1.h include/openssl/srtp.h \
ssl/statem/../record/record.h ssl/statem/../statem/statem.h \
ssl/statem/../packet_local.h include/internal/numbers.h \
include/internal/dane.h include/internal/refcount.h \
include/internal/tsan_assist.h ssl/statem/statem_local.h

View File

@ -0,0 +1,157 @@
/*
* 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
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*****************************************************************************
* *
* These enums should be considered PRIVATE to the state machine. No *
* non-state machine code should need to use these *
* *
*****************************************************************************/
/*
* Valid return codes used for functions performing work prior to or after
* sending or receiving a message
*/
typedef enum {
/* Something went wrong */
WORK_ERROR,
/* We're done working and there shouldn't be anything else to do after */
WORK_FINISHED_STOP,
/* We're done working move onto the next thing */
WORK_FINISHED_CONTINUE,
/* We're working on phase A */
WORK_MORE_A,
/* We're working on phase B */
WORK_MORE_B,
/* We're working on phase C */
WORK_MORE_C
} WORK_STATE;
/* Write transition return codes */
typedef enum {
/* Something went wrong */
WRITE_TRAN_ERROR,
/* A transition was successfully completed and we should continue */
WRITE_TRAN_CONTINUE,
/* There is no more write work to be done */
WRITE_TRAN_FINISHED
} WRITE_TRAN;
/* Message flow states */
typedef enum {
/* No handshake in progress */
MSG_FLOW_UNINITED,
/* A permanent error with this connection */
MSG_FLOW_ERROR,
/* We are reading messages */
MSG_FLOW_READING,
/* We are writing messages */
MSG_FLOW_WRITING,
/* Handshake has finished */
MSG_FLOW_FINISHED
} MSG_FLOW_STATE;
/* Read states */
typedef enum {
READ_STATE_HEADER,
READ_STATE_BODY,
READ_STATE_POST_PROCESS
} READ_STATE;
/* Write states */
typedef enum {
WRITE_STATE_TRANSITION,
WRITE_STATE_PRE_WORK,
WRITE_STATE_SEND,
WRITE_STATE_POST_WORK
} WRITE_STATE;
typedef enum {
/* The enc_write_ctx can be used normally */
ENC_WRITE_STATE_VALID,
/* The enc_write_ctx cannot be used */
ENC_WRITE_STATE_INVALID,
/* Write alerts in plaintext, but otherwise use the enc_write_ctx */
ENC_WRITE_STATE_WRITE_PLAIN_ALERTS
} ENC_WRITE_STATES;
typedef enum {
/* The enc_read_ctx can be used normally */
ENC_READ_STATE_VALID,
/* We may receive encrypted or plaintext alerts */
ENC_READ_STATE_ALLOW_PLAIN_ALERTS
} ENC_READ_STATES;
/*****************************************************************************
* *
* This structure should be considered "opaque" to anything outside of the *
* state machine. No non-state machine code should be accessing the members *
* of this structure. *
* *
*****************************************************************************/
struct ossl_statem_st {
MSG_FLOW_STATE state;
WRITE_STATE write_state;
WORK_STATE write_state_work;
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;
ENC_WRITE_STATES enc_write_state;
ENC_READ_STATES enc_read_state;
};
typedef struct ossl_statem_st OSSL_STATEM;
/*****************************************************************************
* *
* The following macros/functions represent the libssl internal API to the *
* state machine. Any libssl code may call these functions/macros *
* *
*****************************************************************************/
__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_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);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
ssl/statem/statem_clnt.o: ssl/statem/statem_clnt.c \
ssl/statem/../ssl_local.h e_os.h include/openssl/opensslconf.h \
include/openssl/opensslv.h include/openssl/e_os2.h \
include/openssl/crypto.h include/openssl/safestack.h \
include/openssl/stack.h include/openssl/ossl_typ.h \
include/openssl/cryptoerr.h include/openssl/symhacks.h \
include/internal/nelem.h include/openssl/buffer.h \
include/openssl/buffererr.h include/openssl/comp.h \
include/openssl/comperr.h include/openssl/bio.h include/openssl/bioerr.h \
include/openssl/rsa.h include/openssl/asn1.h include/openssl/asn1err.h \
include/openssl/bn.h include/openssl/bnerr.h include/openssl/rsaerr.h \
include/openssl/dsa.h include/openssl/dh.h include/openssl/dherr.h \
include/openssl/dsaerr.h include/openssl/err.h include/openssl/lhash.h \
include/openssl/ssl.h include/openssl/x509.h include/openssl/evp.h \
include/openssl/evperr.h include/openssl/objects.h \
include/openssl/obj_mac.h include/openssl/objectserr.h \
include/openssl/ec.h include/openssl/ecerr.h include/openssl/sha.h \
include/openssl/x509err.h include/openssl/x509_vfy.h \
include/openssl/pkcs7.h include/openssl/pkcs7err.h include/openssl/pem.h \
include/openssl/pemerr.h include/openssl/hmac.h include/openssl/async.h \
include/openssl/asyncerr.h include/openssl/ct.h include/openssl/cterr.h \
include/openssl/sslerr.h include/openssl/ssl2.h include/openssl/ssl3.h \
include/openssl/tls1.h include/openssl/dtls1.h include/openssl/srtp.h \
ssl/statem/../record/record.h ssl/statem/../statem/statem.h \
ssl/statem/../packet_local.h include/internal/numbers.h \
include/internal/dane.h include/internal/refcount.h \
include/internal/tsan_assist.h ssl/statem/statem_local.h \
include/openssl/rand.h include/openssl/randerr.h include/openssl/md5.h \
include/openssl/engine.h include/openssl/ui.h include/openssl/uierr.h \
include/openssl/engineerr.h include/internal/cryptlib.h

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
ssl/statem/statem_dtls.o: ssl/statem/statem_dtls.c \
ssl/statem/../ssl_local.h e_os.h include/openssl/opensslconf.h \
include/openssl/opensslv.h include/openssl/e_os2.h \
include/openssl/crypto.h include/openssl/safestack.h \
include/openssl/stack.h include/openssl/ossl_typ.h \
include/openssl/cryptoerr.h include/openssl/symhacks.h \
include/internal/nelem.h include/openssl/buffer.h \
include/openssl/buffererr.h include/openssl/comp.h \
include/openssl/comperr.h include/openssl/bio.h include/openssl/bioerr.h \
include/openssl/rsa.h include/openssl/asn1.h include/openssl/asn1err.h \
include/openssl/bn.h include/openssl/bnerr.h include/openssl/rsaerr.h \
include/openssl/dsa.h include/openssl/dh.h include/openssl/dherr.h \
include/openssl/dsaerr.h include/openssl/err.h include/openssl/lhash.h \
include/openssl/ssl.h include/openssl/x509.h include/openssl/evp.h \
include/openssl/evperr.h include/openssl/objects.h \
include/openssl/obj_mac.h include/openssl/objectserr.h \
include/openssl/ec.h include/openssl/ecerr.h include/openssl/sha.h \
include/openssl/x509err.h include/openssl/x509_vfy.h \
include/openssl/pkcs7.h include/openssl/pkcs7err.h include/openssl/pem.h \
include/openssl/pemerr.h include/openssl/hmac.h include/openssl/async.h \
include/openssl/asyncerr.h include/openssl/ct.h include/openssl/cterr.h \
include/openssl/sslerr.h include/openssl/ssl2.h include/openssl/ssl3.h \
include/openssl/tls1.h include/openssl/dtls1.h include/openssl/srtp.h \
ssl/statem/../record/record.h ssl/statem/../statem/statem.h \
ssl/statem/../packet_local.h include/internal/numbers.h \
include/internal/dane.h include/internal/refcount.h \
include/internal/tsan_assist.h ssl/statem/statem_local.h \
include/internal/cryptlib.h

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
ssl/statem/statem_lib.o: ssl/statem/statem_lib.c \
ssl/statem/../ssl_local.h e_os.h include/openssl/opensslconf.h \
include/openssl/opensslv.h include/openssl/e_os2.h \
include/openssl/crypto.h include/openssl/safestack.h \
include/openssl/stack.h include/openssl/ossl_typ.h \
include/openssl/cryptoerr.h include/openssl/symhacks.h \
include/internal/nelem.h include/openssl/buffer.h \
include/openssl/buffererr.h include/openssl/comp.h \
include/openssl/comperr.h include/openssl/bio.h include/openssl/bioerr.h \
include/openssl/rsa.h include/openssl/asn1.h include/openssl/asn1err.h \
include/openssl/bn.h include/openssl/bnerr.h include/openssl/rsaerr.h \
include/openssl/dsa.h include/openssl/dh.h include/openssl/dherr.h \
include/openssl/dsaerr.h include/openssl/err.h include/openssl/lhash.h \
include/openssl/ssl.h include/openssl/x509.h include/openssl/evp.h \
include/openssl/evperr.h include/openssl/objects.h \
include/openssl/obj_mac.h include/openssl/objectserr.h \
include/openssl/ec.h include/openssl/ecerr.h include/openssl/sha.h \
include/openssl/x509err.h include/openssl/x509_vfy.h \
include/openssl/pkcs7.h include/openssl/pkcs7err.h include/openssl/pem.h \
include/openssl/pemerr.h include/openssl/hmac.h include/openssl/async.h \
include/openssl/asyncerr.h include/openssl/ct.h include/openssl/cterr.h \
include/openssl/sslerr.h include/openssl/ssl2.h include/openssl/ssl3.h \
include/openssl/tls1.h include/openssl/dtls1.h include/openssl/srtp.h \
ssl/statem/../record/record.h ssl/statem/../statem/statem.h \
ssl/statem/../packet_local.h include/internal/numbers.h \
include/internal/dane.h include/internal/refcount.h \
include/internal/tsan_assist.h ssl/statem/statem_local.h \
include/internal/cryptlib.h

View File

@ -0,0 +1,422 @@
/*
* Copyright 2015-2021 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
*/
/*****************************************************************************
* *
* The following definitions are PRIVATE to the state machine. They should *
* NOT be used outside of the state machine. *
* *
*****************************************************************************/
/* Max message length definitions */
/* 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 SESSION_TICKET_MAX_LENGTH_TLS13 131338
#define SESSION_TICKET_MAX_LENGTH_TLS12 65541
#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
/* Dummy message type */
#define SSL3_MT_DUMMY -1
extern const unsigned char hrrrandom[];
/* Message processing return codes */
typedef enum {
/* Something bad happened */
MSG_PROCESS_ERROR,
/* We've finished reading - swap to writing */
MSG_PROCESS_FINISHED_READING,
/*
* We've completed the main processing of this message but there is some
* post processing to be done.
*/
MSG_PROCESS_CONTINUE_PROCESSING,
/* We've finished this message - read the next message */
MSG_PROCESS_CONTINUE_READING
} MSG_PROCESS_RETURN;
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);
const STACK_OF(X509_NAME) *get_ca_names(SSL *s);
int construct_ca_names(SSL *s, const STACK_OF(X509_NAME) *ca_sk, 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
*/
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, 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);
/*
* TLS/DTLS server state machine functions
*/
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, 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, 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, WPACKET *pkt);
__owur int dtls_construct_change_cipher_spec(SSL *s, WPACKET *pkt);
__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, 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_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, 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, WPACKET *pkt);
__owur int tls_client_key_exchange_post_work(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, 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, 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);
__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, 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);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
ssl/statem/statem_srvr.o: ssl/statem/statem_srvr.c \
ssl/statem/../ssl_local.h e_os.h include/openssl/opensslconf.h \
include/openssl/opensslv.h include/openssl/e_os2.h \
include/openssl/crypto.h include/openssl/safestack.h \
include/openssl/stack.h include/openssl/ossl_typ.h \
include/openssl/cryptoerr.h include/openssl/symhacks.h \
include/internal/nelem.h include/openssl/buffer.h \
include/openssl/buffererr.h include/openssl/comp.h \
include/openssl/comperr.h include/openssl/bio.h include/openssl/bioerr.h \
include/openssl/rsa.h include/openssl/asn1.h include/openssl/asn1err.h \
include/openssl/bn.h include/openssl/bnerr.h include/openssl/rsaerr.h \
include/openssl/dsa.h include/openssl/dh.h include/openssl/dherr.h \
include/openssl/dsaerr.h include/openssl/err.h include/openssl/lhash.h \
include/openssl/ssl.h include/openssl/x509.h include/openssl/evp.h \
include/openssl/evperr.h include/openssl/objects.h \
include/openssl/obj_mac.h include/openssl/objectserr.h \
include/openssl/ec.h include/openssl/ecerr.h include/openssl/sha.h \
include/openssl/x509err.h include/openssl/x509_vfy.h \
include/openssl/pkcs7.h include/openssl/pkcs7err.h include/openssl/pem.h \
include/openssl/pemerr.h include/openssl/hmac.h include/openssl/async.h \
include/openssl/asyncerr.h include/openssl/ct.h include/openssl/cterr.h \
include/openssl/sslerr.h include/openssl/ssl2.h include/openssl/ssl3.h \
include/openssl/tls1.h include/openssl/dtls1.h include/openssl/srtp.h \
ssl/statem/../record/record.h ssl/statem/../statem/statem.h \
ssl/statem/../packet_local.h include/internal/numbers.h \
include/internal/dane.h include/internal/refcount.h \
include/internal/tsan_assist.h ssl/statem/statem_local.h \
include/internal/constant_time.h include/internal/cryptlib.h \
include/openssl/rand.h include/openssl/randerr.h include/openssl/md5.h \
include/openssl/asn1t.h