Detlef Vollmann dv at
Mon Aug 14 20:18:06 UTC 2023

On 8/10/23 16:25, Todd Short via openssl-users wrote:
> Short answer: No, the OpenSSL library is not able to do this AS-IS.
> Long answer:
> 1) This would require serialization/deserialization of the SSL structure, which is opaque. The process is similar to how the SSL_SESSION is serialized in ssl/ssl_asn1.c, but is much more complicated. It requires internal knowledge of the handshake process and the SSL data structure. It can be done in a separate source file (i.e. there’s very little integration required with the rest of the system), but it’s fragile. I have done this in another job, and it took a while (months) to get right.


My case is a bit different: we use DTLS, with reply attack not being
a problem due to sequence numbers in the application protocol.

And we have many DTLS (IoT) clients that only do a handshake at startup
and they should not notice if the server goes down.
So the idea is a UDP load balancer that redirects the packets
to a newly started server when the old server goes down.

The new server reads the session data from a store that's written
on each new connection.
This session data contains the serialized SSL_SESSION and also
the full hello message from the client and the server random.

The new server, when it receives a packet from a client it doesn't
have a DTLS session yet, reads the data from the store, injects
the (stored) ClientHello with included session id (this is DTLS 1.2),
so the resumption path is taken by OpenSSL (SSL_CTX_sess_set_get_cb).
It then overwrites the server random in the following info callback.
Then OpenSSL sends a ServerHello, which is eaten, and at this point
the session is set to connected, which is the point where all the
internal state must be set correctly.
It's actually a pretty short function:

int setSslConnected(SSL *s)
     PACKET p = {NULL, 0};
     int st = tls_process_change_cipher_spec(s, &p);

     // fix state
     s->rwstate = 1;
     s->statem.state = MSG_FLOW_FINISHED;
     s->statem.write_state = WRITE_STATE_PRE_WORK;
     s->statem.write_state_work = WORK_FINISHED_STOP;
     s->statem.read_state = READ_STATE_BODY;
     s->statem.read_state_work = WORK_FINISHED_STOP;
     s->statem.hand_state = TLS_ST_OK;
     s->statem.request_state = TLS_ST_BEFORE;
     s->statem.in_init = 0;
     s->statem.read_state_first_init = 0;
     s->statem.in_handshake = 0;
     s->statem.cleanuphand = 0;
     s->statem.enc_write_state = ENC_WRITE_STATE_VALID;
     s->statem.enc_read_state = ENC_READ_STATE_VALID;

     // more fixes
     s->s3.change_cipher_spec = 0;
     s->d1->handshake_write_seq = 0;
     s->d1->next_handshake_write_seq = 0;
     s->d1->handshake_read_seq = 0;
     s->rlayer.d-> = 1;

     return st;

But all this is internal OpenSSL data and may change with any
new version.

Finally the server sequence number must be set using some heuristic
specific for the application.

For now this is just a proof of concept (but it works)
and management doesn't have decided yet if they really want this.

In case management actually wants something like this,
would OpenSSL be interested in a patch that provides such a
functionality (in a clean way of course)?


More information about the openssl-users mailing list