107 lines
3.0 KiB
C++
107 lines
3.0 KiB
C++
|
//
|
||
|
// Process Resumption Tickets and external PSKs
|
||
|
//
|
||
|
|
||
|
#include "tls_tickets.h"
|
||
|
|
||
|
// Initialise a ticket. Also record the cipher-suite in use, and servers favourite key exchange group
|
||
|
void initTicketContext(ticket *T)
|
||
|
{
|
||
|
T->valid=false;
|
||
|
|
||
|
T->NONCE.len = 0;
|
||
|
T->NONCE.max = 256;
|
||
|
T->NONCE.val = T->nonce;
|
||
|
|
||
|
T->PSK.len = 0;
|
||
|
T->PSK.max = TLS_MAX_HASH;
|
||
|
T->PSK.val = T->psk;
|
||
|
|
||
|
T->TICK.len = 0;
|
||
|
T->TICK.max = TLS_MAX_TICKET_SIZE;
|
||
|
T->TICK.val = T->tick;
|
||
|
|
||
|
T->lifetime=0;
|
||
|
T->age_obfuscator=0;
|
||
|
T->max_early_data=0;
|
||
|
T->birth=0;
|
||
|
T->cipher_suite=0;
|
||
|
T->favourite_group=0;
|
||
|
T->origin=0;
|
||
|
}
|
||
|
|
||
|
// terminate a ticket
|
||
|
void endTicketContext(ticket *T)
|
||
|
{
|
||
|
OCT_kill(&T->NONCE);
|
||
|
OCT_kill(&T->PSK);
|
||
|
OCT_kill(&T->TICK);
|
||
|
|
||
|
T->lifetime=0;
|
||
|
T->age_obfuscator=0;
|
||
|
T->max_early_data=0;
|
||
|
T->birth=0;
|
||
|
T->cipher_suite=0;
|
||
|
T->favourite_group=0;
|
||
|
T->origin=0;
|
||
|
}
|
||
|
|
||
|
// Parse ticket data and birth time into a ticket structure
|
||
|
int parseTicket(octad *TICK,unsign32 birth,ticket *T)
|
||
|
{
|
||
|
ret r;
|
||
|
int ext,len,tmplen,ptr=0;
|
||
|
if (TICK->len==0) return BAD_TICKET;
|
||
|
r=parseInt(TICK,4,ptr); if (r.err) return r.err; T->lifetime=r.val;
|
||
|
r=parseInt(TICK,4,ptr); if (r.err) return r.err; T->age_obfuscator=r.val;
|
||
|
r=parseInt(TICK,1,ptr); len=r.val; if (r.err) return r.err;
|
||
|
r=parseoctad(&T->NONCE,len,TICK,ptr); if (r.err) return r.err; // could be a single byte 0,1,2,3,... incremented for each ticket issued on this connection
|
||
|
r=parseInt(TICK,2,ptr); len=r.val; if (r.err) return r.err;
|
||
|
r=parseoctad(&T->TICK,len,TICK,ptr); if (r.err) return r.err; // extract ticket
|
||
|
r=parseInt(TICK,2,ptr); len=r.val; if (r.err) return r.err; // length of extensions
|
||
|
|
||
|
T->birth=birth;
|
||
|
T->max_early_data=0;
|
||
|
while (len>0)
|
||
|
{
|
||
|
r=parseInt(TICK,2,ptr); ext=r.val; if (r.err) return r.err;
|
||
|
len-=2;
|
||
|
switch (ext)
|
||
|
{
|
||
|
case EARLY_DATA :
|
||
|
{
|
||
|
r=parseInt(TICK,2,ptr); if (r.err) return r.err; tmplen=r.val; if (tmplen!=4) return BAD_TICKET;
|
||
|
len-=2; // tmplen=4 - max_early data
|
||
|
r=parseInt(TICK,4,ptr); T->max_early_data=r.val;
|
||
|
len-=tmplen;
|
||
|
break;
|
||
|
}
|
||
|
default : // ignore other extensions // Probably GREASE extensions
|
||
|
|
||
|
r=parseInt(TICK,2,ptr); tmplen=r.val;
|
||
|
len-=2;
|
||
|
len-=tmplen; ptr+=tmplen;
|
||
|
break;
|
||
|
}
|
||
|
if (r.err) return r.err;
|
||
|
}
|
||
|
T->valid=true;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// check a ticket exists, its good, and its not out-of-date
|
||
|
bool ticket_still_good(ticket *T)
|
||
|
{
|
||
|
unsign32 time_ticket_received,time_ticket_used;
|
||
|
unsign32 age;
|
||
|
if (T->origin==TLS_EXTERNAL_PSK) return true;
|
||
|
if (T->lifetime<=0 || !T->valid)
|
||
|
return false;
|
||
|
time_ticket_received=T->birth;
|
||
|
time_ticket_used=(unsign32)millis();
|
||
|
age=time_ticket_used-time_ticket_received;
|
||
|
if (age>1000*T->lifetime)
|
||
|
return false;
|
||
|
return true;
|
||
|
}
|