Just replying to my own post in case anyone will ever google this question, the change we made to the library did actually work and is compliant with IEC-62351.
Im gonna leave as much info as i can because to be honest trying to find information about this topic was very hard (there was in fact no information available at all actually) and it seems like a good idea to spare some poor engineer in the future some time.
This only applies to mbedtls 2.28 but im sure a similiar fix can be applied to later versions.
Basically just modify the function ssl_handle_id_based_session_resumption() in ssl_srv.c like this:
static void ssl_handle_id_based_session_resumption(mbedtls_ssl_context *ssl)
{
int ret;
mbedtls_ssl_session session_tmp;
mbedtls_ssl_session * const session = ssl->session_negotiate;
// Resume is 0 by default, see ssl_handshake_init().
//It may be already set to 1 by ssl_parse_session_ticket_ext().
if (ssl->handshake->resume == 1) {
return;
}
if (session->id_len == 0) {
return;
}
#if defined(MBEDTLS_SSL_RENEGOTIATION)
if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {
if (ssl->session != NULL &&
ssl->session->id_len == session->id_len &&
memcmp(ssl->session->id, session->id, session->id_len) == 0 &&
mbedtls_ssl_session_copy(session, ssl->session) == 0) {
printf("resuming existing session\n");
ssl->handshake->resume = 1;
ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION;
return;
}
return;
}
#endif
if (ssl->conf->f_get_cache == NULL) {
return;
}
mbedtls_ssl_session_init(&session_tmp);
session_tmp.id_len = session->id_len;
memcpy(session_tmp.id, session->id, session->id_len);
ret = ssl->conf->f_get_cache(ssl->conf->p_cache,
&session_tmp);
if (ret != 0) {
goto exit;
}
if (session->ciphersuite != session_tmp.ciphersuite ||
session->compression != session_tmp.compression) {
// Mismatch between cached and negotiated session
goto exit;
}
// Move semantics
mbedtls_ssl_session_free(session);
*session = session_tmp;
memset(&session_tmp, 0, sizeof(session_tmp));
MBEDTLS_SSL_DEBUG_MSG(3, ("session successfully restored from cache"));
ssl->handshake->resume = 1;
exit:
mbedtls_ssl_session_free(&session_tmp);
}
we decided to go with this version but you can also just remove the if statement and it also does seem to work, so something like this:
#if (0)
if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {
if (ssl->session != NULL &&
ssl->session->id_len == session->id_len &&
memcmp(ssl->session->id, session->id, session->id_len) == 0 &&
mbedtls_ssl_session_copy(session, ssl->session) == 0) {
printf("resuming existing session\n");
ssl->handshake->resume = 1;
ssl->secure_renegotiation = MBEDTLS_SSL_SECURE_RENEGOTIATION;
return;
}
return;
}
#endif
It’s a bit of a hacky solution but it manages to pass certification tests and does not break renegotiation or normal resumption for mbedtls 2.28.
If you are on later versions of mbedtls you might have to work a bit harder because they renamed some files and moved some functions around.
To test this behaviour i suggest you write an openssl client using openssllib and perform a “resumption” using the function SSL_renegotiate_abbreviated(), which simulates the behaviour of the test cases from the standard and seems be compliant to the RFC aswell.
Good luck, hope this is useful to someone out there!