Introduce SSL_CTX_set_stateless_cookie_{generate,verify}_cb
These functions are similar to SSL_CTX_set_cookie_{generate,verify}_cb, but used for the application-controlled portion of TLS1.3 stateless handshake cookies rather than entire DTLSv1 cookies. Reviewed-by: Ben Kaduk <kaduk@mit.edu> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/5463)
This commit is contained in:
parent
4718f449a3
commit
3fa2812f32
11 changed files with 149 additions and 12 deletions
|
@ -58,6 +58,11 @@ int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
|
||||||
int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
|
int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
|
||||||
unsigned int cookie_len);
|
unsigned int cookie_len);
|
||||||
|
|
||||||
|
int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie,
|
||||||
|
size_t *cookie_len);
|
||||||
|
int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie,
|
||||||
|
size_t cookie_len);
|
||||||
|
|
||||||
typedef struct ssl_excert_st SSL_EXCERT;
|
typedef struct ssl_excert_st SSL_EXCERT;
|
||||||
|
|
||||||
void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc);
|
void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc);
|
||||||
|
|
16
apps/s_cb.c
16
apps/s_cb.c
|
@ -755,6 +755,22 @@ int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie,
|
||||||
|
size_t *cookie_len)
|
||||||
|
{
|
||||||
|
unsigned int temp;
|
||||||
|
int res = generate_cookie_callback(ssl, cookie, &temp);
|
||||||
|
*cookie_len = temp;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie,
|
||||||
|
size_t cookie_len)
|
||||||
|
{
|
||||||
|
return verify_cookie_callback(ssl, cookie, cookie_len);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -2038,6 +2038,10 @@ int s_server_main(int argc, char *argv[])
|
||||||
SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie_callback);
|
SSL_CTX_set_cookie_generate_cb(ctx, generate_cookie_callback);
|
||||||
SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie_callback);
|
SSL_CTX_set_cookie_verify_cb(ctx, verify_cookie_callback);
|
||||||
|
|
||||||
|
/* Set TLS1.3 cookie generation and verification callbacks */
|
||||||
|
SSL_CTX_set_stateless_cookie_generate_cb(ctx, generate_stateless_cookie_callback);
|
||||||
|
SSL_CTX_set_stateless_cookie_verify_cb(ctx, verify_stateless_cookie_callback);
|
||||||
|
|
||||||
if (ctx2 != NULL) {
|
if (ctx2 != NULL) {
|
||||||
SSL_CTX_set_verify(ctx2, s_server_verify, verify_callback);
|
SSL_CTX_set_verify(ctx2, s_server_verify, verify_callback);
|
||||||
if (!SSL_CTX_set_session_id_context(ctx2,
|
if (!SSL_CTX_set_session_id_context(ctx2,
|
||||||
|
|
|
@ -64,10 +64,11 @@ does not support this), then B<*peer> will be cleared and the family set to
|
||||||
AF_UNSPEC. Typically user code is expected to "connect" the underlying socket to
|
AF_UNSPEC. Typically user code is expected to "connect" the underlying socket to
|
||||||
the peer and continue the handshake in a connected state.
|
the peer and continue the handshake in a connected state.
|
||||||
|
|
||||||
Prior to calling these functions user code must ensure that cookie generation
|
Prior to calling DTLSv1_listen() user code must ensure that cookie generation
|
||||||
and verification callbacks have been set up using
|
and verification callbacks have been set up using
|
||||||
SSL_CTX_set_cookie_generate_cb() and SSL_CTX_set_cookie_verify_cb()
|
SSL_CTX_set_cookie_generate_cb() and SSL_CTX_set_cookie_verify_cb()
|
||||||
respectively.
|
respectively. For SSL_stateless(), SSL_CTX_set_stateless_cookie_generate_cb()
|
||||||
|
and SSL_CTX_set_stateless_cookie_verify_cb() must be used instead.
|
||||||
|
|
||||||
Since DTLSv1_listen() operates entirely statelessly whilst processing incoming
|
Since DTLSv1_listen() operates entirely statelessly whilst processing incoming
|
||||||
ClientHellos it is unable to process fragmented messages (since this would
|
ClientHellos it is unable to process fragmented messages (since this would
|
||||||
|
|
58
doc/man3/SSL_CTX_set_stateless_cookie_generate_cb.pod
Normal file
58
doc/man3/SSL_CTX_set_stateless_cookie_generate_cb.pod
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
SSL_CTX_set_stateless_cookie_generate_cb,
|
||||||
|
SSL_CTX_set_stateless_cookie_verify_cb
|
||||||
|
- Callback functions for stateless TLS1.3 cookies
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
|
||||||
|
void SSL_CTX_set_stateless_cookie_generate_cb(
|
||||||
|
SSL_CTX *ctx,
|
||||||
|
int (*gen_stateless_cookie_cb) (SSL *ssl,
|
||||||
|
unsigned char *cookie,
|
||||||
|
size_t *cookie_len));
|
||||||
|
void SSL_CTX_set_stateless_cookie_verify_cb(
|
||||||
|
SSL_CTX *ctx,
|
||||||
|
int (*verify_stateless_cookie_cb) (SSL *ssl,
|
||||||
|
const unsigned char *cookie,
|
||||||
|
size_t cookie_len));
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
SSL_CTX_set_cookie_generate_cb() sets the callback used by L<SSL_stateless(3)>
|
||||||
|
to generate the application-controlled portion of the cookie provided to clients
|
||||||
|
in the HelloRetryRequest transmitted as a response to a ClientHello with a
|
||||||
|
missing or invalid cookie. gen_stateless_cookie_cb() must write at most
|
||||||
|
SSL_COOKIE_LENGTH bytes into B<cookie>, and must write the number of bytes
|
||||||
|
written to B<cookie_len>. If a cookie cannot be generated, a zero return value
|
||||||
|
can be used to abort the handshake.
|
||||||
|
|
||||||
|
SSL_CTX_set_cookie_verify_cb() sets the callback used by L<SSL_stateless(3)> to
|
||||||
|
determine whether the application-controlled portion of a ClientHello cookie is
|
||||||
|
valid. A nonzero return value from app_verify_cookie_cb() communicates that the
|
||||||
|
cookie is valid. The integrity of the entire cookie, including the
|
||||||
|
application-controlled portion, is automatically verified by HMAC before
|
||||||
|
verify_stateless_cookie_cb() is called.
|
||||||
|
|
||||||
|
=head1 RETURN VALUES
|
||||||
|
|
||||||
|
Neither function returns a value.
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
L<SSL_stateless(3)>
|
||||||
|
|
||||||
|
=head1 COPYRIGHT
|
||||||
|
|
||||||
|
Copyright 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
|
||||||
|
L<https://www.openssl.org/source/license.html>.
|
||||||
|
|
||||||
|
=cut
|
|
@ -546,8 +546,8 @@ typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx);
|
||||||
# define SSL_CONF_TYPE_DIR 0x3
|
# define SSL_CONF_TYPE_DIR 0x3
|
||||||
# define SSL_CONF_TYPE_NONE 0x4
|
# define SSL_CONF_TYPE_NONE 0x4
|
||||||
|
|
||||||
/* Length of a TLSv1.3 cookie */
|
/* Maximum length of the application-controlled segment of a a TLSv1.3 cookie */
|
||||||
# define SSL_COOKIE_LENGTH 255
|
# define SSL_COOKIE_LENGTH 4096
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, they
|
* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, they
|
||||||
|
@ -726,6 +726,17 @@ void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
|
||||||
*cookie,
|
*cookie,
|
||||||
unsigned int
|
unsigned int
|
||||||
cookie_len));
|
cookie_len));
|
||||||
|
|
||||||
|
void SSL_CTX_set_stateless_cookie_generate_cb(
|
||||||
|
SSL_CTX *ctx,
|
||||||
|
int (*gen_stateless_cookie_cb) (SSL *ssl,
|
||||||
|
unsigned char *cookie,
|
||||||
|
size_t *cookie_len));
|
||||||
|
void SSL_CTX_set_stateless_cookie_verify_cb(
|
||||||
|
SSL_CTX *ctx,
|
||||||
|
int (*verify_stateless_cookie_cb) (SSL *ssl,
|
||||||
|
const unsigned char *cookie,
|
||||||
|
size_t cookie_len));
|
||||||
# ifndef OPENSSL_NO_NEXTPROTONEG
|
# ifndef OPENSSL_NO_NEXTPROTONEG
|
||||||
|
|
||||||
typedef int (*SSL_CTX_npn_advertised_cb_func)(SSL *ssl,
|
typedef int (*SSL_CTX_npn_advertised_cb_func)(SSL *ssl,
|
||||||
|
|
|
@ -820,6 +820,14 @@ struct ssl_ctx_st {
|
||||||
int (*app_verify_cookie_cb) (SSL *ssl, const unsigned char *cookie,
|
int (*app_verify_cookie_cb) (SSL *ssl, const unsigned char *cookie,
|
||||||
unsigned int cookie_len);
|
unsigned int cookie_len);
|
||||||
|
|
||||||
|
/* TLS1.3 app-controlled cookie generate callback */
|
||||||
|
int (*gen_stateless_cookie_cb) (SSL *ssl, unsigned char *cookie,
|
||||||
|
size_t *cookie_len);
|
||||||
|
|
||||||
|
/* TLS1.3 verify app-controlled cookie callback */
|
||||||
|
int (*verify_stateless_cookie_cb) (SSL *ssl, const unsigned char *cookie,
|
||||||
|
size_t cookie_len);
|
||||||
|
|
||||||
CRYPTO_EX_DATA ex_data;
|
CRYPTO_EX_DATA ex_data;
|
||||||
|
|
||||||
const EVP_MD *md5; /* For SSLv3/TLSv1 'ssl3-md5' */
|
const EVP_MD *md5; /* For SSLv3/TLSv1 'ssl3-md5' */
|
||||||
|
|
|
@ -1301,4 +1301,22 @@ int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SSL_CTX_set_stateless_cookie_generate_cb(
|
||||||
|
SSL_CTX *ctx,
|
||||||
|
int (*cb) (SSL *ssl,
|
||||||
|
unsigned char *cookie,
|
||||||
|
size_t *cookie_len))
|
||||||
|
{
|
||||||
|
ctx->gen_stateless_cookie_cb = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SSL_CTX_set_stateless_cookie_verify_cb(
|
||||||
|
SSL_CTX *ctx,
|
||||||
|
int (*cb) (SSL *ssl,
|
||||||
|
const unsigned char *cookie,
|
||||||
|
size_t cookie_len))
|
||||||
|
{
|
||||||
|
ctx->verify_stateless_cookie_cb = cb;
|
||||||
|
}
|
||||||
|
|
||||||
IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)
|
IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)
|
||||||
|
|
|
@ -729,7 +729,7 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||||
unsigned long tm, now;
|
unsigned long tm, now;
|
||||||
|
|
||||||
/* Ignore any cookie if we're not set up to verify it */
|
/* Ignore any cookie if we're not set up to verify it */
|
||||||
if (s->ctx->app_verify_cookie_cb == NULL
|
if (s->ctx->verify_stateless_cookie_cb == NULL
|
||||||
|| (s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
|
|| (s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -852,7 +852,7 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify the app cookie */
|
/* Verify the app cookie */
|
||||||
if (s->ctx->app_verify_cookie_cb(s, PACKET_data(&appcookie),
|
if (s->ctx->verify_stateless_cookie_cb(s, PACKET_data(&appcookie),
|
||||||
PACKET_remaining(&appcookie)) == 0) {
|
PACKET_remaining(&appcookie)) == 0) {
|
||||||
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
|
||||||
SSL_R_COOKIE_MISMATCH);
|
SSL_R_COOKIE_MISMATCH);
|
||||||
|
@ -1676,8 +1676,7 @@ EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
|
||||||
{
|
{
|
||||||
unsigned char *hashval1, *hashval2, *appcookie1, *appcookie2, *cookie;
|
unsigned char *hashval1, *hashval2, *appcookie1, *appcookie2, *cookie;
|
||||||
unsigned char *hmac, *hmac2;
|
unsigned char *hmac, *hmac2;
|
||||||
size_t startlen, ciphlen, totcookielen, hashlen, hmaclen;
|
size_t startlen, ciphlen, totcookielen, hashlen, hmaclen, appcookielen;
|
||||||
unsigned int appcookielen;
|
|
||||||
EVP_MD_CTX *hctx;
|
EVP_MD_CTX *hctx;
|
||||||
EVP_PKEY *pkey;
|
EVP_PKEY *pkey;
|
||||||
int ret = EXT_RETURN_FAIL;
|
int ret = EXT_RETURN_FAIL;
|
||||||
|
@ -1685,7 +1684,7 @@ EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
|
||||||
if ((s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
|
if ((s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
|
||||||
return EXT_RETURN_NOT_SENT;
|
return EXT_RETURN_NOT_SENT;
|
||||||
|
|
||||||
if (s->ctx->app_gen_cookie_cb == NULL) {
|
if (s->ctx->gen_stateless_cookie_cb == NULL) {
|
||||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
|
||||||
SSL_R_NO_COOKIE_CALLBACK_SET);
|
SSL_R_NO_COOKIE_CALLBACK_SET);
|
||||||
return EXT_RETURN_FAIL;
|
return EXT_RETURN_FAIL;
|
||||||
|
@ -1733,7 +1732,7 @@ EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate the application cookie */
|
/* Generate the application cookie */
|
||||||
if (s->ctx->app_gen_cookie_cb(s, appcookie1, &appcookielen) == 0) {
|
if (s->ctx->gen_stateless_cookie_cb(s, appcookie1, &appcookielen) == 0) {
|
||||||
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
|
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
|
||||||
SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
|
SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
|
||||||
return EXT_RETURN_FAIL;
|
return EXT_RETURN_FAIL;
|
||||||
|
|
|
@ -2723,6 +2723,21 @@ static int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie,
|
||||||
|
size_t *cookie_len)
|
||||||
|
{
|
||||||
|
unsigned int temp;
|
||||||
|
int res = generate_cookie_callback(ssl, cookie, &temp);
|
||||||
|
*cookie_len = temp;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie,
|
||||||
|
size_t cookie_len)
|
||||||
|
{
|
||||||
|
return verify_cookie_callback(ssl, cookie, cookie_len);
|
||||||
|
}
|
||||||
|
|
||||||
static int test_stateless(void)
|
static int test_stateless(void)
|
||||||
{
|
{
|
||||||
SSL_CTX *sctx = NULL, *cctx = NULL;
|
SSL_CTX *sctx = NULL, *cctx = NULL;
|
||||||
|
@ -2754,8 +2769,8 @@ static int test_stateless(void)
|
||||||
clientssl = NULL;
|
clientssl = NULL;
|
||||||
|
|
||||||
/* Set up the cookie generation and verification callbacks */
|
/* Set up the cookie generation and verification callbacks */
|
||||||
SSL_CTX_set_cookie_generate_cb(sctx, generate_cookie_callback);
|
SSL_CTX_set_stateless_cookie_generate_cb(sctx, generate_stateless_cookie_callback);
|
||||||
SSL_CTX_set_cookie_verify_cb(sctx, verify_cookie_callback);
|
SSL_CTX_set_stateless_cookie_verify_cb(sctx, verify_stateless_cookie_callback);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a new connection from the client (we can reuse the server SSL
|
* Create a new connection from the client (we can reuse the server SSL
|
||||||
|
|
|
@ -482,3 +482,5 @@ SSL_use_cert_and_key 482 1_1_1 EXIST::FUNCTION:
|
||||||
SSL_SESSION_get0_ticket_appdata 483 1_1_1 EXIST::FUNCTION:
|
SSL_SESSION_get0_ticket_appdata 483 1_1_1 EXIST::FUNCTION:
|
||||||
SSL_SESSION_set1_ticket_appdata 484 1_1_1 EXIST::FUNCTION:
|
SSL_SESSION_set1_ticket_appdata 484 1_1_1 EXIST::FUNCTION:
|
||||||
SSL_CTX_set_session_ticket_cb 485 1_1_1 EXIST::FUNCTION:
|
SSL_CTX_set_session_ticket_cb 485 1_1_1 EXIST::FUNCTION:
|
||||||
|
SSL_CTX_set_stateless_cookie_generate_cb 486 1_1_1 EXIST::FUNCTION:
|
||||||
|
SSL_CTX_set_stateless_cookie_verify_cb 487 1_1_1 EXIST::FUNCTION:
|
||||||
|
|
Loading…
Reference in a new issue