diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 5c67bf7af0..5a4faa7c88 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -9836,16 +9836,17 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, /* * Serialize a session in the following format: + * (in the presentation language of TLS, RFC 8446 section 3) * - * - If MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is enabled: - * 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session) - * n . n+2 peer_cert length = m (0 if no certificate) - * n+3 . n+2+m peer cert ASN.1 + * opaque session_struct[n]; // n = sizeof(mbedtls_ssl_session) + * select (MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) { + * case enabled: opaque peer_cert<0..2^24-1>; // length 0 means no cert + * case disabled: uint8_t peer_cert_digest_type; + * opaque peer_cert_digest<0..2^8-1>; + * } + * opaque ticket<0..2^24-1>; // 0 means no ticket * - * - If MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is disabled: - * 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session) - * n . n length of peer certificate digest = k (0 if no digest) - * n+1 . n+k peer certificate digest (digest type encoded in session) + * Only the peer's certificate is saved, not the whole chain. */ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, unsigned char *buf, @@ -9862,16 +9863,22 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ + /* + * Shallow copy of the session structure + */ if( left < sizeof( mbedtls_ssl_session ) ) return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + left -= sizeof( mbedtls_ssl_session ); /* This also copies the values of pointer fields in the * session to be serialized, but they'll be ignored when * loading the session through ssl_load_session(). */ memcpy( p, session, sizeof( mbedtls_ssl_session ) ); p += sizeof( mbedtls_ssl_session ); - left -= sizeof( mbedtls_ssl_session ); + /* + * Copy of the peer's end-entity certificate + */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) if( session->peer_cert == NULL ) @@ -9881,6 +9888,7 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, if( left < 3 + cert_len ) return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + left -= 3 + cert_len; *p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF ); *p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF ); @@ -9888,7 +9896,10 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, left -= 3; if( session->peer_cert != NULL ) + { memcpy( p, session->peer_cert->raw.p, cert_len ); + p += cert_len; + } p += cert_len; left -= cert_len; @@ -9912,6 +9923,27 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session, #endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ + /* + * Copy of the session ticket if any + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if( left < 3 + session->ticket_len ) + return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL ); + left -= 3 + session->ticket_len; + + *p++ = (unsigned char)( ( session->ticket_len >> 16 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_len >> 8 ) & 0xFF ); + *p++ = (unsigned char)( ( session->ticket_len ) & 0xFF ); + + if( session->ticket != NULL ) + { + memcpy( p, session->ticket, session->ticket_len ); + p += session->ticket_len; + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + /* Done */ + (void) left; *olen = p - buf; return( 0 ); @@ -9934,6 +9966,9 @@ int mbedtls_ssl_session_load( mbedtls_ssl_session *session, #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ + /* + * Shallow session structure + */ if( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); @@ -9953,6 +9988,9 @@ int mbedtls_ssl_session_load( mbedtls_ssl_session *session, session->ticket = NULL; #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + /* + * Peer certificate + */ #if defined(MBEDTLS_X509_CRT_PARSE_C) #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) /* Deserialize CRT from the end of the ticket. */ @@ -10013,6 +10051,31 @@ int mbedtls_ssl_session_load( mbedtls_ssl_session *session, #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ + /* + * Session ticket + */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C) + if( 3 > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ticket_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2]; + p += 3; + + if( session->ticket_len != 0 ) + { + if( session->ticket_len > (size_t)( end - p ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + session->ticket = mbedtls_calloc( 1, session->ticket_len ); + if( session->ticket == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + + memcpy( session->ticket, p, session->ticket_len ); + p += session->ticket_len; + } +#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */ + + /* Done, should have consumed entire buffer */ if( p != end ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );