Skip to content

Commit

Permalink
RT3870 Async TLSEXT servername support.
Browse files Browse the repository at this point in the history
Adds support for processing the servername TLSEXT asynchronously,
using the SSL_WANT_EVENT mechansism.

(cherry picked from commit 58ef21b)

Conflicts:
	include/openssl/ssl3.h
	ssl/s3_lib.c
	ssl/s3_srvr.c
	ssl/ssl_locl.h
	ssl/t1_lib.c
  • Loading branch information
Stefan Eissing authored and tmshort committed Jun 18, 2015
1 parent 246b86e commit 1f26946
Show file tree
Hide file tree
Showing 12 changed files with 341 additions and 15 deletions.
4 changes: 4 additions & 0 deletions doc/ssl/SSL_CTX_set_schedule_task_cb.pod
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ The task signs the certificate verification message on the client side.

The task signs the key verification message before it is sent to the client.

=item B<SSL_EVENT_TLSEXT_SERVERNAME_READY>

The task has procesed the servername extension from the client.

=head1 SEE ALSO

L<ssl(3)|ssl(3)>, L<SSL_signal_event(3)|SSL_signal_event(3)>
Expand Down
2 changes: 2 additions & 0 deletions include/openssl/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,8 @@ __owur int SSL_extension_supported(unsigned int ext_type);
# define SSL_EVENT_SETUP_CERT_VRFY_DONE 1002
/* server is siging the message for key exchange */
# define SSL_EVENT_KEY_EXCH_MSG_SIGNED 1003
/* tlsext servername has been processed */
# define SSL_EVENT_TLSEXT_SERVERNAME_READY 1004

/*
* These will only be used when doing non-blocking IO or asynchronous
Expand Down
9 changes: 9 additions & 0 deletions include/openssl/ssl3.h
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,15 @@ extern "C" {
# define SSL3_CHANGE_CIPHER_CLIENT_READ (SSL3_CC_CLIENT|SSL3_CC_READ)
# define SSL3_CHANGE_CIPHER_SERVER_WRITE (SSL3_CC_SERVER|SSL3_CC_WRITE)

# define SSL3_ST_SUB_0 (0x00)
# define SSL3_ST_SUB_1 (0x01)
# define SSL3_ST_SUB_2 (0x02)
# define SSL3_ST_SUB_3 (0x03)
# define SSL3_ST_SUB_4 (0x04)
# define SSL3_ST_SUB_5 (0x05)
# define SSL3_ST_SUB_6 (0x06)
# define SSL3_ST_SUB_7 (0x07)

#ifdef __cplusplus
}
#endif
Expand Down
1 change: 1 addition & 0 deletions include/openssl/tls1.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,(void (*)(void))cb)
# define SSL_TLSEXT_ERR_ALERT_WARNING 1
# define SSL_TLSEXT_ERR_ALERT_FATAL 2
# define SSL_TLSEXT_ERR_NOACK 3
# define SSL_TLSEXT_ERR_WAIT_FOR_EVENT 4

# define SSL_CTX_set_tlsext_servername_arg(ctx, arg) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0, (void *)arg)
Expand Down
25 changes: 21 additions & 4 deletions ssl/d1_srvr.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,13 +313,30 @@ int dtls1_accept(SSL *s)
break;

case SSL3_ST_SR_CLNT_HELLO_A:
s->s3->tmp.sub_state = SSL3_ST_SUB_0;
case SSL3_ST_SR_CLNT_HELLO_B:
case SSL3_ST_SR_CLNT_HELLO_C:

s->shutdown = 0;
ret = ssl3_get_client_hello(s);
if (ret <= 0)
goto end;
if (s->s3->tmp.sub_state == SSL3_ST_SUB_0) {
s->shutdown = 0;
ret = ssl3_get_client_hello(s);
if (ret <= 0)
goto end;
s->s3->tmp.sub_state = SSL3_ST_SUB_1;
}
if (s->s3->tmp.sub_state == SSL3_ST_SUB_1) {
s->s3->tmp.sub_state = SSL3_ST_SUB_2;
ret = ssl_check_clienthello_tlsext_async(s);
if (ret <= 0)
goto end;
}
if (s->s3->tmp.sub_state == SSL3_ST_SUB_2) {
if (!ssl_event_did_succeed(s, SSL_EVENT_TLSEXT_SERVERNAME_READY, &ret))
goto end;
ret = ssl3_get_client_hello_post_app(s, 0);
if (ret <= 0)
goto end;
}
dtls1_stop_timer(s);

if (ret == 1 && (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE))
Expand Down
1 change: 1 addition & 0 deletions ssl/s3_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -2913,6 +2913,7 @@ void ssl3_free(SSL *s)
#ifndef OPENSSL_NO_SRP
SSL_SRP_CTX_free(s);
#endif
sk_SSL_CIPHER_free(s->s3->tmp.ciphers);
OPENSSL_clear_free(s->s3, sizeof(*s->s3));
s->s3 = NULL;
}
Expand Down
71 changes: 64 additions & 7 deletions ssl/s3_srvr.c
Original file line number Diff line number Diff line change
Expand Up @@ -343,14 +343,35 @@ int ssl3_accept(SSL *s)
break;

case SSL3_ST_SR_CLNT_HELLO_A:
s->s3->tmp.sub_state = SSL3_ST_SUB_0;
case SSL3_ST_SR_CLNT_HELLO_B:
case SSL3_ST_SR_CLNT_HELLO_C:

ret = ssl3_get_client_hello(s);
if (ret <= 0)
goto end;
if (s->s3->tmp.sub_state == SSL3_ST_SUB_0) {
s->shutdown = 0;
ret = ssl3_get_client_hello(s);
if (ret <= 0)
goto end;
s->s3->tmp.sub_state = SSL3_ST_SUB_1;
}
if (s->s3->tmp.sub_state == SSL3_ST_SUB_1) {
s->s3->tmp.sub_state = SSL3_ST_SUB_2;
ret = ssl_check_clienthello_tlsext_async(s);
if (ret <= 0)
goto end;
}
if (s->s3->tmp.sub_state == SSL3_ST_SUB_2) {
if (!ssl_event_did_succeed(s, SSL_EVENT_TLSEXT_SERVERNAME_READY, &ret)) {
goto end;
}
ret = ssl3_get_client_hello_post_app(s, 0);
if (ret <= 0)
goto end;
s->s3->tmp.sub_state = SSL3_ST_SUB_3;
}
#ifndef OPENSSL_NO_SRP
s->state = SSL3_ST_SR_CLNT_HELLO_D;
if (s->s3->tmp.sub_state == SSL3_ST_SUB_3)
s->state = SSL3_ST_SR_CLNT_HELLO_D;
case SSL3_ST_SR_CLNT_HELLO_D:
{
int al;
Expand Down Expand Up @@ -886,13 +907,14 @@ int ssl3_get_client_hello(SSL *s)
SSL_CIPHER *c;
#ifndef OPENSSL_NO_COMP
unsigned char *q = NULL;
SSL_COMP *comp = NULL;
#endif
STACK_OF(SSL_CIPHER) *ciphers = NULL;
int protverr = 1;

if (s->state == SSL3_ST_SR_CLNT_HELLO_C && !s->first_packet)
goto retry_cert;
if (s->state == SSL3_ST_SR_CLNT_HELLO_C && !s->first_packet) {
/* head over to post_app and goto retry_cert there */
return ssl3_get_client_hello_post_app(s, 1);
}

/*
* We do this so that we will respond with our native type. If we are
Expand Down Expand Up @@ -1356,14 +1378,49 @@ int ssl3_get_client_hello(SSL *s)
}
}

/* ssl3_get_client_hello_post_app will need these when called. */
if (ciphers != NULL)
s->s3->tmp.ciphers = sk_SSL_CIPHER_dup(ciphers);
s->s3->tmp.q = q;
s->s3->tmp.i = i;
s->s3->tmp.complen = complen;

/* TLS extensions */
if (s->version >= SSL3_VERSION) {
if (!ssl_parse_clienthello_tlsext(s, &p, d, n)) {
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_PARSE_TLSEXT);
goto err;
}
}
if (ret < 0)
ret = 1;
if (0) {
f_err:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
}
err:
sk_SSL_CIPHER_free(ciphers);
return ret < 0 ? -1 : ret;
}

int ssl3_get_client_hello_post_app(SSL *s, int retry_cert)
{
int al = SSL_AD_INTERNAL_ERROR, ret= -1;
int complen = s->s3->tmp.complen;
unsigned char *q = s->s3->tmp.q;
SSL_CIPHER *c;
STACK_OF(SSL_CIPHER) *ciphers = s->s3->tmp.ciphers;

#ifndef OPENSSL_NO_COMP
SSL_COMP *comp = NULL;
#endif

/* we have already copied tmp_ciphers into ciphers. */
s->s3->tmp.ciphers = NULL;
if (retry_cert) {
/* we likely came through the regular function in this state */
goto retry_cert;
}
/*
* Check if we want to use external pre-shared secret for this handshake
* for not reused session only. We need to generate server_random before
Expand Down
14 changes: 14 additions & 0 deletions ssl/ssl_locl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,18 @@ typedef struct ssl3_state_st {
unsigned long mask_ssl;

int skip_client_verify;
/* managing micro state inside SSL3_ST_xxx states */
int sub_state;
/*
* Next three variables are temporary variables that store various information
* between call to ssl3_get_client_hello and ssl3_get_client_hello_post_app.
* I couldn't figure out a better way to break ssl3_get_client_hello into
* two parts without having to store this information.
*/
STACK_OF(SSL_CIPHER) *ciphers;
unsigned char *q;
int i;
int complen;
} tmp;

/* Connection binding to prevent renegotiation attacks */
Expand Down Expand Up @@ -2104,6 +2116,7 @@ int dtls1_client_hello(SSL *s);

/* some server-only functions */
__owur int ssl3_get_client_hello(SSL *s);
__owur int ssl3_get_client_hello_post_app(SSL *s, int retry_cert);
__owur int ssl3_send_server_hello(SSL *s);
__owur int ssl3_send_hello_request(SSL *s);
__owur int ssl3_send_server_key_exchange(SSL *s);
Expand Down Expand Up @@ -2179,6 +2192,7 @@ __owur unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
__owur int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data,
unsigned char *d, int n);
__owur int tls1_set_server_sigalgs(SSL *s);
__owur int ssl_check_clienthello_tlsext_async(SSL *s);
__owur int ssl_check_clienthello_tlsext_late(SSL *s);
__owur int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data,
unsigned char *d, int n);
Expand Down
37 changes: 37 additions & 0 deletions ssl/t1_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -2693,6 +2693,43 @@ static void ssl_set_default_md(SSL *s)
#endif
}

int ssl_check_clienthello_tlsext_async(SSL *s)
{
int ret = SSL_TLSEXT_ERR_NOACK;
int al = SSL_AD_UNRECOGNIZED_NAME;

s->rwstate = SSL_EVENT_TLSEXT_SERVERNAME_READY;
if (s->ctx != NULL && s->ctx->tlsext_servername_callback != 0)
ret =
s->ctx->tlsext_servername_callback(s, &al,
s->ctx->tlsext_servername_arg);
else if (s->initial_ctx != NULL
&& s->initial_ctx->tlsext_servername_callback != 0)
ret =
s->initial_ctx->tlsext_servername_callback(s, &al,
s->
initial_ctx->tlsext_servername_arg);
if (ret == SSL_TLSEXT_ERR_WAIT_FOR_EVENT)
/* we shall wait for event SSL_EVENT_TLSEXT_SERVERNAME_READY */
return -1;
SSL_signal_event(s, SSL_EVENT_TLSEXT_SERVERNAME_READY, 1);

switch (ret) {
case SSL_TLSEXT_ERR_ALERT_FATAL:
ssl3_send_alert(s, SSL3_AL_FATAL, al);
return 0;

case SSL_TLSEXT_ERR_ALERT_WARNING:
ssl3_send_alert(s, SSL3_AL_WARNING, al);
return 1;

case SSL_TLSEXT_ERR_NOACK:
s->servername_done = 0;
default:
return 1;
}
}

int tls1_set_server_sigalgs(SSL *s)
{
int al;
Expand Down
15 changes: 11 additions & 4 deletions test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ V3NAMETEST= v3nametest
HEARTBEATTEST= heartbeat_test
CONSTTIMETEST= constant_time_test
TASKTEST= tasktest
TLSEXTTEST= tlsexttest

TESTS= alltests

Expand All @@ -84,7 +85,7 @@ EXE= $(BNTEST)$(EXE_EXT) $(ECTEST)$(EXE_EXT) $(ECDSATEST)$(EXE_EXT) $(ECDHTEST)
$(JPAKETEST)$(EXE_EXT) $(SRPTEST)$(EXE_EXT) $(V3NAMETEST)$(EXE_EXT) \
$(HEARTBEATTEST)$(EXE_EXT) $(P5_CRPT2_TEST)$(EXE_EXT) \
$(CONSTTIMETEST)$(EXE_EXT) \
$(TASKTEST)$(EXE_EXT)
$(TASKTEST)$(EXE_EXT) $(TLSEXTTEST)$(EXE_EXT)

# $(METHTEST)$(EXE_EXT)

Expand All @@ -99,7 +100,7 @@ OBJ= $(BNTEST).o $(ECTEST).o $(ECDSATEST).o $(ECDHTEST).o $(IDEATEST).o \
$(EVPTEST).o $(EVPEXTRATEST).o $(IGETEST).o $(JPAKETEST).o $(V3NAMETEST).o \
$(GOST2814789TEST).o $(HEARTBEATTEST).o $(P5_CRPT2_TEST).o \
$(CONSTTIMETEST).o testutil.o \
$(TASKTEST).o
$(TASKTEST).o $(TLSEXTTEST).o

SRC= $(BNTEST).c $(ECTEST).c $(ECDSATEST).c $(ECDHTEST).c $(IDEATEST).c \
$(MD2TEST).c $(MD4TEST).c $(MD5TEST).c \
Expand All @@ -111,7 +112,7 @@ SRC= $(BNTEST).c $(ECTEST).c $(ECDSATEST).c $(ECDHTEST).c $(IDEATEST).c \
$(EVPTEST).c $(EVPEXTRATEST).c $(IGETEST).c $(JPAKETEST).c $(V3NAMETEST).c \
$(GOST2814789TEST).c $(HEARTBEATTEST).c $(P5_CRPT2_TEST).c \
$(CONSTTIMETEST).c testutil.c \
$(TASKTEST).c
$(TASKTEST).c $(TLSEXTTEST).c

HEADER= testutil.h

Expand Down Expand Up @@ -152,7 +153,7 @@ alltests: \
test_ige test_jpake test_srp test_cms test_v3name test_ocsp \
test_gost2814789 test_heartbeat test_p5_crpt2 \
test_constant_time \
test_task
test_task test_tlsext

test_evp: $(EVPTEST)$(EXE_EXT) evptests.txt
@echo $(START) $@
Expand Down Expand Up @@ -400,6 +401,9 @@ test_constant_time: $(CONSTTIMETEST)$(EXE_EXT)
test_task: $(TASKTEST)$(EXE_EXT) testtask
@sh ./testtask

test_tlsext: $(TLSEXTTEST)$(EXE_EXT) testtlsext
@sh ./testtlsext

update: local_depend
@if [ -z "$(THIS)" ]; then $(MAKE) -f $(TOP)/Makefile reflect THIS=$@; fi

Expand Down Expand Up @@ -588,6 +592,9 @@ $(CONSTTIMETEST)$(EXE_EXT): $(CONSTTIMETEST).o
$(TASKTEST)$(EXE_EXT): $(TASKTEST).o
@target=$(TASKTEST) $(BUILD_CMD)

$(TLSEXTTEST)$(EXE_EXT): $(TLSEXTTEST).o
@target=$(TLSEXTTEST) $(BUILD_CMD)

#$(AESTEST).o: $(AESTEST).c
# $(CC) -c $(CFLAGS) -DINTERMEDIATE_VALUE_KAT -DTRACE_KAT_MCT $(AESTEST).c

Expand Down
17 changes: 17 additions & 0 deletions test/testtlsext
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/sh

tlsexttest="../util/shlib_wrap.sh ./tlsexttest"

#############################################################################

echo Test TLSEXT Callbacks
if [ ! -d gen ]; then
./gen_cert.sh server
fi

# test openssl tlsext callback extension
$tlsexttest --tlsv1_2 || echo 1
$tlsexttest --tlsv1_1 || echo 1
$tlsexttest --sslv3 || echo 1

exit 0

0 comments on commit 1f26946

Please sign in to comment.