diff options
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | doc/cha-gtls-app.texi | 13 | ||||
-rw-r--r-- | lib/db.c | 23 | ||||
-rw-r--r-- | lib/ext/pre_shared_key.c | 2 | ||||
-rw-r--r-- | lib/gnutls_int.h | 1 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 13 | ||||
-rw-r--r-- | lib/libgnutls.map | 3 | ||||
-rw-r--r-- | lib/tls13/anti_replay.c | 59 | ||||
-rw-r--r-- | lib/tls13/anti_replay.h | 2 | ||||
-rw-r--r-- | src/serv.c | 17 | ||||
-rw-r--r-- | tests/tls13-early-data-neg.c | 18 | ||||
-rw-r--r-- | tests/tls13-early-data.c | 17 | ||||
-rw-r--r-- | tests/tls13/anti_replay.c | 32 |
13 files changed, 117 insertions, 87 deletions
@@ -39,8 +39,8 @@ GNUTLS_MAC_AES_CMAC_256: Added gnutls_record_get_max_early_data_size: Added gnutls_record_send_early_data: Added gnutls_record_recv_early_data: Added -gnutls_db_entry_is_expired: Added -gnutls_db_set_add_function: Added +gnutls_db_check_entry_expire_time: Added +gnutls_anti_replay_set_add_function: Added gnutls_anti_replay_init: Added gnutls_anti_replay_deinit: Added gnutls_anti_replay_set_window: Added diff --git a/doc/cha-gtls-app.texi b/doc/cha-gtls-app.texi index b7b6d6a87e..da21995cb7 100644 --- a/doc/cha-gtls-app.texi +++ b/doc/cha-gtls-app.texi @@ -980,7 +980,8 @@ The anti-replay mechanism shall be globally initialized with The server must also set up a database back-end to store ClientHello messages. That can be achieved using -@funcref{gnutls_db_set_add_function} (see @ref{Session resumption}). +@funcref{gnutls_anti_replay_set_add_function} and +@funcref{gnutls_anti_replay_set_ptr}. Note that, if the back-end stores arbitrary number of ClientHello, it needs to periodically clean up the stored entries based on the time @@ -1028,15 +1029,15 @@ int main() */ gnutls_anti_replay_init(&anti_replay); + /* Set the database back-end function for the anti-replay data. */ + gnutls_anti_replay_set_add_function(anti_replay, db_add_func); + gnutls_anti_replay_set_ptr(anti_replay, NULL); + ... gnutls_init(&server, GNUTLS_SERVER | GNUTLS_ENABLE_EARLY_DATA); gnutls_record_set_max_early_data_size(server, MAX_EARLY_DATA_SIZE); - ... - /* Set the database back-end function for the session. - */ - gnutls_db_set_add_function(server, db_add_func); ... /* Set the anti-replay measure to the session. @@ -1850,7 +1851,7 @@ A storing server needs to specify callback functions to store, retrieve and dele registered with the functions below. The stored sessions in the database can be checked using @funcref{gnutls_db_check_entry} for expiration. -@showfuncE{gnutls_db_set_retrieve_function,gnutls_db_set_store_function,gnutls_db_set_ptr,gnutls_db_set_remove_function,gnutls_db_set_add_function} +@showfuncD{gnutls_db_set_retrieve_function,gnutls_db_set_store_function,gnutls_db_set_ptr,gnutls_db_set_remove_function} @showfuncA{gnutls_db_check_entry} A server supporting session tickets must generate ticket encryption @@ -56,29 +56,6 @@ gnutls_db_set_retrieve_function(gnutls_session_t session, } /** - * gnutls_db_set_add_function: - * @session: is a #gnutls_session_t type. - * @add_func: is the function. - * - * Sets the function that will be used to store an entry if it is not - * already present in the resumed sessions database. This function returns 0 - * if the entry is successfully stored, and a negative error code - * otherwise. In particular, if the entry is found in the database, - * it returns %GNUTLS_E_DB_ENTRY_EXISTS. - * - * The first argument to @add_func will be null unless - * gnutls_db_set_ptr() has been called. - * - * Since: 3.6.5 - **/ -void -gnutls_db_set_add_function(gnutls_session_t session, - gnutls_db_add_func add_func) -{ - session->internals.db_add_func = add_func; -} - -/** * gnutls_db_set_remove_function: * @session: is a #gnutls_session_t type. * @rem_func: is the function. diff --git a/lib/ext/pre_shared_key.c b/lib/ext/pre_shared_key.c index bc7fc8aa95..c42bd1646b 100644 --- a/lib/ext/pre_shared_key.c +++ b/lib/ext/pre_shared_key.c @@ -621,7 +621,7 @@ static int server_recv_params(gnutls_session_t session, } else { if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) { if (session->internals.anti_replay) { - ret = _gnutls_anti_replay_check(session, + ret = _gnutls_anti_replay_check(session->internals.anti_replay, ticket_age, &ticket_creation_time, &binder_recvd); diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index e34bea85b8..16881d8827 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -1216,7 +1216,6 @@ typedef struct { gnutls_db_store_func db_store_func; gnutls_db_retr_func db_retrieve_func; gnutls_db_remove_func db_remove_func; - gnutls_db_add_func db_add_func; void *db_ptr; /* post client hello callback (server side only) diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 2af09bb24a..789e374315 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -1783,8 +1783,6 @@ typedef int (*gnutls_db_store_func) (void *, gnutls_datum_t key, gnutls_datum_t data); typedef int (*gnutls_db_remove_func) (void *, gnutls_datum_t key); typedef gnutls_datum_t(*gnutls_db_retr_func) (void *, gnutls_datum_t key); -typedef int (*gnutls_db_add_func) (void *, gnutls_datum_t key, - gnutls_datum_t data); void gnutls_db_set_cache_expiration(gnutls_session_t session, int seconds); unsigned gnutls_db_get_default_cache_expiration(void); @@ -1796,8 +1794,6 @@ void gnutls_db_set_remove_function(gnutls_session_t session, gnutls_db_remove_func rem_func); void gnutls_db_set_store_function(gnutls_session_t session, gnutls_db_store_func store_func); -void gnutls_db_set_add_function(gnutls_session_t session, - gnutls_db_add_func add_func); void gnutls_db_set_ptr(gnutls_session_t session, void *ptr); void *gnutls_db_get_ptr(gnutls_session_t session); int gnutls_db_check_entry(gnutls_session_t session, @@ -3002,6 +2998,15 @@ void gnutls_anti_replay_set_window(gnutls_anti_replay_t anti_replay, void gnutls_anti_replay_enable(gnutls_session_t session, gnutls_anti_replay_t anti_replay); +typedef int (*gnutls_db_add_func) (void *, time_t exp_time, const gnutls_datum_t *key, + const gnutls_datum_t *data); + +void gnutls_anti_replay_set_add_function(gnutls_anti_replay_t, + gnutls_db_add_func add_func); + +void gnutls_anti_replay_set_ptr(gnutls_anti_replay_t, void *ptr); + + /* FIPS140-2 related functions */ unsigned gnutls_fips140_mode_enabled(void); diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 3cfc0c450b..06181f04ee 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -1255,7 +1255,8 @@ GNUTLS_3_6_5 gnutls_record_send_early_data; gnutls_record_recv_early_data; gnutls_db_check_entry_expire_time; - gnutls_db_set_add_function; + gnutls_anti_replay_set_add_function; + gnutls_anti_replay_set_ptr; gnutls_anti_replay_init; gnutls_anti_replay_deinit; gnutls_anti_replay_set_window; diff --git a/lib/tls13/anti_replay.c b/lib/tls13/anti_replay.c index 5ae9926afd..a99266928c 100644 --- a/lib/tls13/anti_replay.c +++ b/lib/tls13/anti_replay.c @@ -32,6 +32,8 @@ struct gnutls_anti_replay_st { uint32_t window; struct timespec start_time; + gnutls_db_add_func db_add_func; + void *db_ptr; }; /** @@ -121,13 +123,13 @@ gnutls_anti_replay_enable(gnutls_session_t session, } int -_gnutls_anti_replay_check(gnutls_session_t session, +_gnutls_anti_replay_check(gnutls_anti_replay_t anti_replay, uint32_t client_ticket_age, struct timespec *ticket_creation_time, gnutls_datum_t *id) { - gnutls_anti_replay_t anti_replay = session->internals.anti_replay; struct timespec now; + time_t window; uint32_t server_ticket_age, diff; gnutls_datum_t key = { NULL, 0 }; gnutls_datum_t entry = { NULL, 0 }; @@ -176,7 +178,7 @@ _gnutls_anti_replay_check(gnutls_session_t session, /* Check if the ClientHello is stored in the database. */ - if (!session->internals.db_add_func) + if (!anti_replay->db_add_func) return gnutls_assert_val(GNUTLS_E_EARLY_DATA_REJECTED); /* Create a key for database lookup, prefixing window start @@ -198,20 +200,21 @@ _gnutls_anti_replay_check(gnutls_session_t session, /* Create an entry to be stored on database if the lookup * failed. This is formatted so that - * gnutls_db_entry_is_expired() work. + * gnutls_db_check_entry_expire_time() work. */ p = entry_buffer; _gnutls_write_uint32(PACKED_SESSION_MAGIC, p); p += 4; _gnutls_write_uint32(now.tv_sec, p); p += 4; - _gnutls_write_uint32(anti_replay->window / 1000, p); + window = anti_replay->window / 1000; + _gnutls_write_uint32(window, p); p += 4; entry.data = entry_buffer; entry.size = p - entry_buffer; - ret = session->internals.db_add_func(session->internals.db_ptr, - key, entry); + ret = anti_replay->db_add_func(anti_replay->db_ptr, + (uint64_t)now.tv_sec+(uint64_t)window, &key, &entry); if (ret < 0) { _gnutls_handshake_log("anti_replay: duplicate ClientHello found\n"); return gnutls_assert_val(GNUTLS_E_EARLY_DATA_REJECTED); @@ -219,3 +222,45 @@ _gnutls_anti_replay_check(gnutls_session_t session, return 0; } + +/** + * gnutls_anti_replay_set_ptr: + * @anti_replay: is a #gnutls_anti_replay_t type. + * @ptr: is the pointer + * + * Sets the pointer that will be provided to db add function + * as the first argument. + **/ +void gnutls_anti_replay_set_ptr(gnutls_anti_replay_t anti_replay, void *ptr) +{ + anti_replay->db_ptr = ptr; +} + +/** + * gnutls_anti_replay_set_add_function: + * @anti_replay: is a #gnutls_anti_replay_t type. + * @add_func: is the function. + * + * Sets the function that will be used to store an entry if it is not + * already present in the resumed sessions database. This function returns 0 + * if the entry is successfully stored, and a negative error code + * otherwise. In particular, if the entry is found in the database, + * it returns %GNUTLS_E_DB_ENTRY_EXISTS. + * + * The arguments to the @add_func are: + * - %ptr: the pointer set with gnutls_anti_replay_set_ptr() + * - %exp_time: the expiration time of the entry + * - %key: a pointer to the key + * - %data: a pointer to data to store + * + * The data set by this function can be examined using + * gnutls_db_check_entry_expire_time() and gnutls_db_check_entry_time(). + * + * Since: 3.6.5 + **/ +void +gnutls_anti_replay_set_add_function(gnutls_anti_replay_t anti_replay, + gnutls_db_add_func add_func) +{ + anti_replay->db_add_func = add_func; +} diff --git a/lib/tls13/anti_replay.h b/lib/tls13/anti_replay.h index e44186c910..8d9bea4b5c 100644 --- a/lib/tls13/anti_replay.h +++ b/lib/tls13/anti_replay.h @@ -20,7 +20,7 @@ * */ -int _gnutls_anti_replay_check(gnutls_session_t session, +int _gnutls_anti_replay_check(gnutls_anti_replay_t, uint32_t client_ticket_age, struct timespec *ticket_creation_time, gnutls_datum_t *id); diff --git a/src/serv.c b/src/serv.c index 75871270a5..d0b5914bc0 100644 --- a/src/serv.c +++ b/src/serv.c @@ -126,8 +126,8 @@ static int wrap_db_store(void *dbf, gnutls_datum_t key, gnutls_datum_t data); static gnutls_datum_t wrap_db_fetch(void *dbf, gnutls_datum_t key); static int wrap_db_delete(void *dbf, gnutls_datum_t key); -static int wrap_db_add(void *dbf, gnutls_datum_t key, - gnutls_datum_t data); +static int anti_replay_db_add(void *dbf, time_t exp, const gnutls_datum_t *key, + const gnutls_datum_t *data); static void cmd_parser(int argc, char **argv); @@ -401,7 +401,6 @@ gnutls_session_t initialize_session(int dtls) gnutls_db_set_retrieve_function(session, wrap_db_fetch); gnutls_db_set_remove_function(session, wrap_db_delete); gnutls_db_set_store_function(session, wrap_db_store); - gnutls_db_set_add_function(session, wrap_db_add); gnutls_db_set_ptr(session, NULL); } @@ -1270,6 +1269,8 @@ int main(int argc, char **argv) fprintf(stderr, "Error while initializing anti-replay: %s\n", gnutls_strerror(ret)); exit(1); } + gnutls_anti_replay_set_add_function(anti_replay, anti_replay_db_add); + gnutls_anti_replay_set_ptr(anti_replay, NULL); } if (HAVE_OPT(MTU)) @@ -1897,19 +1898,19 @@ static int wrap_db_delete(void *dbf, gnutls_datum_t key) } static int -wrap_db_add(void *dbf, gnutls_datum_t key, gnutls_datum_t data) +anti_replay_db_add(void *dbf, time_t exp, const gnutls_datum_t *key, const gnutls_datum_t *data) { time_t now = time(0); int i; for (i = 0; i < cache_db_ptr; i++) { - if (key.size == cache_db[i].session_id_size && - memcmp(key.data, cache_db[i].session_id, - key.size) == 0 && + if (key->size == cache_db[i].session_id_size && + memcmp(key->data, cache_db[i].session_id, + key->size) == 0 && now < gnutls_db_check_entry_expire_time(&cache_db[i]. session_data)) return GNUTLS_E_DB_ENTRY_EXISTS; } - return wrap_db_store(dbf, key, data); + return wrap_db_store(dbf, *key, *data); } diff --git a/tests/tls13-early-data-neg.c b/tests/tls13-early-data-neg.c index 6c7a1f492d..35c635f63c 100644 --- a/tests/tls13-early-data-neg.c +++ b/tests/tls13-early-data-neg.c @@ -235,15 +235,15 @@ struct storage_st { }; static int -storage_add(void *ptr, gnutls_datum_t key, gnutls_datum_t value) +storage_add(void *ptr, time_t expires, const gnutls_datum_t *key, const gnutls_datum_t *value) { struct storage_st *storage = ptr; gnutls_datum_t *datum; size_t i; for (i = 0; i < storage->num_entries; i++) { - if (key.size == storage->entries[i].size && - memcmp(storage->entries[i].data, key.data, key.size) == 0) { + if (key->size == storage->entries[i].size && + memcmp(storage->entries[i].data, key->data, key->size) == 0) { return GNUTLS_E_DB_ENTRY_EXISTS; } } @@ -255,11 +255,11 @@ storage_add(void *ptr, gnutls_datum_t key, gnutls_datum_t value) return GNUTLS_E_DB_ERROR; datum = &storage->entries[storage->num_entries]; - datum->data = gnutls_malloc(key.size); + datum->data = gnutls_malloc(key->size); if (!datum->data) return GNUTLS_E_MEMORY_ERROR; - memcpy(datum->data, key.data, key.size); - datum->size = key.size; + memcpy(datum->data, key->data, key->size); + datum->size = key->size; storage->num_entries++; @@ -308,6 +308,8 @@ static void server(int sds[]) ret = gnutls_anti_replay_init(&anti_replay); if (ret < 0) fail("server: failed to initialize anti-replay\n"); + gnutls_anti_replay_set_add_function(anti_replay, storage_add); + gnutls_anti_replay_set_ptr(anti_replay, &storage); for (t = 0; t < SESSIONS; t++) { int sd = sds[t]; @@ -323,8 +325,6 @@ static void server(int sds[]) gnutls_session_ticket_enable_server(session, &session_ticket_key); - gnutls_db_set_add_function(session, storage_add); - gnutls_db_set_ptr(session, &storage); gnutls_anti_replay_enable(session, anti_replay); gnutls_transport_set_int(session, sd); @@ -435,7 +435,7 @@ static void server(int sds[]) void doit(void) { int client_sds[SESSIONS], server_sds[SESSIONS]; - int i, status; + int i, status = 0; int ret; signal(SIGCHLD, SIG_IGN); diff --git a/tests/tls13-early-data.c b/tests/tls13-early-data.c index f23aec77fa..c922ae0ba6 100644 --- a/tests/tls13-early-data.c +++ b/tests/tls13-early-data.c @@ -201,15 +201,15 @@ struct storage_st { }; static int -storage_add(void *ptr, gnutls_datum_t key, gnutls_datum_t value) +storage_add(void *ptr, time_t expires, const gnutls_datum_t *key, const gnutls_datum_t *value) { struct storage_st *storage = ptr; gnutls_datum_t *datum; size_t i; for (i = 0; i < storage->num_entries; i++) { - if (key.size == storage->entries[i].size && - memcmp(storage->entries[i].data, key.data, key.size) == 0) { + if (key->size == storage->entries[i].size && + memcmp(storage->entries[i].data, key->data, key->size) == 0) { return GNUTLS_E_DB_ENTRY_EXISTS; } } @@ -221,11 +221,11 @@ storage_add(void *ptr, gnutls_datum_t key, gnutls_datum_t value) return GNUTLS_E_DB_ERROR; datum = &storage->entries[storage->num_entries]; - datum->data = gnutls_malloc(key.size); + datum->data = gnutls_malloc(key->size); if (!datum->data) return GNUTLS_E_MEMORY_ERROR; - memcpy(datum->data, key.data, key.size); - datum->size = key.size; + memcpy(datum->data, key->data, key->size); + datum->size = key->size; storage->num_entries++; @@ -275,6 +275,9 @@ static void server(int sds[]) if (ret < 0) fail("server: failed to initialize anti-replay\n"); + gnutls_anti_replay_set_add_function(anti_replay, storage_add); + gnutls_anti_replay_set_ptr(anti_replay, &storage); + for (t = 0; t < SESSIONS; t++) { int sd = sds[t]; @@ -287,8 +290,6 @@ static void server(int sds[]) gnutls_session_ticket_enable_server(session, &session_ticket_key); - gnutls_db_set_add_function(session, storage_add); - gnutls_db_set_ptr(session, &storage); gnutls_anti_replay_enable(session, anti_replay); gnutls_transport_set_int(session, sd); diff --git a/tests/tls13/anti_replay.c b/tests/tls13/anti_replay.c index 090dcabbdb..31ab517151 100644 --- a/tests/tls13/anti_replay.c +++ b/tests/tls13/anti_replay.c @@ -37,15 +37,15 @@ struct storage_st { }; static int -storage_add(void *ptr, gnutls_datum_t key, gnutls_datum_t value) +storage_add(void *ptr, time_t expires, const gnutls_datum_t *key, const gnutls_datum_t *value) { struct storage_st *storage = ptr; gnutls_datum_t *datum; size_t i; for (i = 0; i < storage->num_entries; i++) { - if (key.size == storage->entries[i].size && - memcmp(storage->entries[i].data, key.data, key.size) == 0) { + if (key->size == storage->entries[i].size && + memcmp(storage->entries[i].data, key->data, key->size) == 0) { return GNUTLS_E_DB_ENTRY_EXISTS; } } @@ -57,11 +57,11 @@ storage_add(void *ptr, gnutls_datum_t key, gnutls_datum_t value) return GNUTLS_E_DB_ERROR; datum = &storage->entries[storage->num_entries]; - datum->data = gnutls_malloc(key.size); + datum->data = gnutls_malloc(key->size); if (!datum->data) return GNUTLS_E_MEMORY_ERROR; - memcpy(datum->data, key.data, key.size); - datum->size = key.size; + memcpy(datum->data, key->data, key->size); + datum->size = key->size; storage->num_entries++; @@ -94,12 +94,12 @@ void doit(void) ret = gnutls_anti_replay_init(&anti_replay); assert(ret == 0); gnutls_anti_replay_set_window(anti_replay, 10000); + gnutls_anti_replay_set_add_function(anti_replay, storage_add); + gnutls_anti_replay_set_ptr(anti_replay, &storage); gnutls_init(&session, GNUTLS_SERVER); - gnutls_db_set_add_function(session, storage_add); - gnutls_db_set_ptr(session, &storage); gnutls_anti_replay_enable(session, anti_replay); mygettime(&creation_time); - ret = _gnutls_anti_replay_check(session, 10000, &creation_time, &key); + ret = _gnutls_anti_replay_check(anti_replay, 10000, &creation_time, &key); if (ret != GNUTLS_E_ILLEGAL_PARAMETER) fail("error is not returned, while server_ticket_age < client_ticket_age\n"); gnutls_deinit(session); @@ -109,14 +109,14 @@ void doit(void) /* server_ticket_age - client_ticket_age > window */ ret = gnutls_anti_replay_init(&anti_replay); assert(ret == 0); + gnutls_anti_replay_set_add_function(anti_replay, storage_add); + gnutls_anti_replay_set_ptr(anti_replay, &storage); gnutls_anti_replay_set_window(anti_replay, 10000); gnutls_init(&session, GNUTLS_SERVER); - gnutls_db_set_add_function(session, storage_add); - gnutls_db_set_ptr(session, &storage); gnutls_anti_replay_enable(session, anti_replay); mygettime(&creation_time); virt_sec_sleep(30); - ret = _gnutls_anti_replay_check(session, 10000, &creation_time, &key); + ret = _gnutls_anti_replay_check(anti_replay, 10000, &creation_time, &key); if (ret != GNUTLS_E_EARLY_DATA_REJECTED) fail("early data is NOT rejected, while freshness check fails\n"); gnutls_deinit(session); @@ -126,17 +126,17 @@ void doit(void) /* server_ticket_age - client_ticket_age < window */ ret = gnutls_anti_replay_init(&anti_replay); assert(ret == 0); + gnutls_anti_replay_set_add_function(anti_replay, storage_add); + gnutls_anti_replay_set_ptr(anti_replay, &storage); gnutls_anti_replay_set_window(anti_replay, 10000); gnutls_init(&session, GNUTLS_SERVER); - gnutls_db_set_add_function(session, storage_add); - gnutls_db_set_ptr(session, &storage); gnutls_anti_replay_enable(session, anti_replay); mygettime(&creation_time); virt_sec_sleep(15); - ret = _gnutls_anti_replay_check(session, 10000, &creation_time, &key); + ret = _gnutls_anti_replay_check(anti_replay, 10000, &creation_time, &key); if (ret != 0) fail("early data is rejected, while freshness check succeeds\n"); - ret = _gnutls_anti_replay_check(session, 10000, &creation_time, &key); + ret = _gnutls_anti_replay_check(anti_replay, 10000, &creation_time, &key); if (ret != GNUTLS_E_EARLY_DATA_REJECTED) fail("early data is NOT rejected for a duplicate key\n"); gnutls_deinit(session); |