Session ticket key rotation
Over on https://lists.gnupg.org/pipermail/gnutls-devel/2016-November/008231.html we discussed session key ticket rotation.
currently there is no way to smoothly rotate session ticket keys -- you have to invalidate all outstanding session tickets at once by just changing the session ticket key itself on the server side.
It would be nicer if there was some sort of pool that could do this job and just be arbitrarily, simply rotated by the server at some fixed schedule.
Summarizing the ideas from that thread:
struct gnutls_ticket_key_pool_int;
typedef struct gnutls_ticket_key_pool_int *gnutls_ticket_key_pool_t;
int gnutls_ticket_key_pool_init(gnutls_ticket_key_pool_t *pool, int numkeys);
int gnutls_ticket_key_pool_free(gnutls_ticket_key_pool_t pool);
int gnutls_ticket_key_pool_rotate(gnutls_ticket_key_pool_t pool);
/* new value for gnutls_credentials_type_t */
GNUTLS_CRD_SESTKT_KEYPOOL
Users would associate the ticket key pool with a session using
gnutls_credentials_get
and gnutls_credentials_set
, making the workflow
and memory ownership model aligned with existing use.
The caller would be responsible for invoking
gnutls_ticket_key_pool_rotate()
at their selected intervals.
The opacity of the object might cause trouble if you wanted to share the pool session ticket keys across a pool of front-end servers, or if you wanted session tickets to survive a server reboot. You could handle that situation by adding a pair of serialization/deserialization functions for the ticket key pool.
I think this could all be done without locking, risking only failed session resumptions if multiple threads happen to rotate the pool at the same time. here's a rough sketch:
1 typedef char[SESTKTKEYLEN] _session_ticket_key;
2
3 struct gnutls_ticket_key_pool_int {
4 int numkeys;
5 _session_ticket_key *keys;
6 int current_key;
7 }
8
9 int gnutls_ticket_key_pool_init(gnutls_ticket_key_pool_t *pool, int numkeys) {
10 *pool = malloc(sizeof(gnutls_ticket_key_pool_int));
11 (*pool)->numkeys = numkeys;
12 (*pool)->keys = malloc(sizeof(_session_ticket_key) * numkeys);
13 (*pool)->current_key = 0;
14 gnutls_rnd(GNUTLS_RND_KEY, (*pool)->keys, sizeof(_session_ticket_key) * numkeys);
15
16 }
17 int gnutls_ticket_key_pool_rotate(gnutls_ticket_key_pool_t pool) {
18 _session_ticket_key newkey;
19 gnutls_rnd(GNUTLS_RND_KEY, newkey, sizeof(newkey));
20 int newkeyidx = (pool->current_key + 1)%pool->numkeys;
21 memcpy(pool->keys[newkeyidx], newkey, sizeof(newkey));
22 pool->current_key = newkeyidx;
23 }