Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Modify s2nd/c to do serialization/deserialization #4533

Merged
merged 9 commits into from
May 7, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions bin/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,17 @@ int s2n_set_common_server_config(int max_early_data, struct s2n_config *config,

int s2n_setup_server_connection(struct s2n_connection *conn, int fd, struct s2n_config *config, struct conn_settings settings)
{
if (settings.deserialize_in) {
size_t deserialize_length = 0;
GUARD_RETURN(get_file_size(settings.deserialize_in, &deserialize_length), "Failed to read deserialize-in file size");
ENSURE_RETURN(deserialize_length <= UINT32_MAX, "deserialize-in file size is too large");
uint8_t *mem = malloc(deserialize_length);
GUARD_RETURN_NULL(mem);
GUARD_RETURN(load_file_to_array(settings.deserialize_in, mem, deserialize_length), "Failed to read deserialize-in file");
GUARD_RETURN(s2n_connection_deserialize(conn, mem, (uint32_t) deserialize_length), "Failed to deserialize connection");
maddeleine marked this conversation as resolved.
Show resolved Hide resolved
free(mem);
}

if (settings.self_service_blinding) {
s2n_connection_set_blinding(conn, S2N_SELF_SERVICE_BLINDING);
}
Expand Down
30 changes: 28 additions & 2 deletions bin/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,30 @@
} \
} while (0)

#define GUARD_EXIT(x, msg) \
#define GUARD_EXIT(x, msg) \
do { \
if ((x) < 0) { \
fprintf(stderr, "%s\n", msg); \
maddeleine marked this conversation as resolved.
Show resolved Hide resolved
exit(1); \
} \
} while (0)

#define ENSURE_EXIT(x, msg) \
do { \
if ((x) < 0) { \
if (!(x)) { \
print_s2n_error(msg); \
maddeleine marked this conversation as resolved.
Show resolved Hide resolved
exit(1); \
} \
} while (0)

#define GUARD_RETURN_NULL(x) \
do { \
if (x == NULL) { \
fprintf(stderr, "NULL pointer encountered\n"); \
return -1; \
} \
} while (0)

#define GUARD_RETURN(x, msg) \
do { \
if ((x) < 0) { \
Expand All @@ -43,6 +59,14 @@
} \
} while (0)

#define ENSURE_RETURN(x, msg) \
do { \
if (!(x)) { \
fprintf(stderr, "%s\n", msg); \
return -1; \
} \
} while (0)

#define S2N_MAX_PSK_LIST_LENGTH 10
#define MAX_KEY_LEN 32
#define MAX_VAL_LEN 255
Expand Down Expand Up @@ -74,6 +98,8 @@ struct conn_settings {
int max_conns;
const char *ca_dir;
const char *ca_file;
const char *serialize_out;
const char *deserialize_in;
maddeleine marked this conversation as resolved.
Show resolved Hide resolved
char *psk_optarg_list[S2N_MAX_PSK_LIST_LENGTH];
size_t psk_list_len;
};
Expand Down
48 changes: 45 additions & 3 deletions bin/s2nc.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
#define OPT_PREFER_LOW_LATENCY 1005
#define OPT_PREFER_THROUGHPUT 1006
#define OPT_BUFFERED_SEND 1007
#define OPT_SERIALIZE_OUT 1008
#define OPT_DESERIALIZE_IN 1009

/*
* s2nc is an example client that uses many s2n-tls APIs.
Expand Down Expand Up @@ -95,6 +97,11 @@ void usage()
fprintf(stderr, " Path to a file where the session ticket can be stored.\n");
fprintf(stderr, " --ticket-in [file path]\n");
fprintf(stderr, " Path to session ticket file to resume connection.\n");
fprintf(stderr, " --serialize-out [file path]\n");
fprintf(stderr, " Path to a file where a serialized connection can be stored. \n"
" Note that this feature is intended to be used with our integration test framework and therefore is not expected to work with s2nc alone.\n");
fprintf(stderr, " --deserialize-in [file path]\n");
fprintf(stderr, " Path to a file where a serialized connection lives. Will be used to skip the handshake and start sending encrypted data.\n");
maddeleine marked this conversation as resolved.
Show resolved Hide resolved
fprintf(stderr, " -D,--dynamic\n");
fprintf(stderr, " Set dynamic record resize threshold\n");
fprintf(stderr, " -t,--timeout\n");
Expand Down Expand Up @@ -292,6 +299,8 @@ int main(int argc, char *const *argv)
bool client_key_input = false;
const char *ticket_out = NULL;
char *ticket_in = NULL;
const char *serialize_out = NULL;
const char *deserialize_in = NULL;
uint16_t mfl_value = 0;
uint8_t insecure = 0;
int reconnect = 0;
Expand Down Expand Up @@ -340,6 +349,8 @@ int main(int argc, char *const *argv)
{ "ticket-out", required_argument, 0, OPT_TICKET_OUT },
{ "ticket-in", required_argument, 0, OPT_TICKET_IN },
{ "no-session-ticket", no_argument, 0, 'T' },
{ "serialize-out", required_argument, 0, OPT_SERIALIZE_OUT },
{ "deserialize-in", required_argument, 0, OPT_DESERIALIZE_IN },
{ "dynamic", required_argument, 0, 'D' },
{ "timeout", required_argument, 0, 't' },
{ "corked-io", no_argument, 0, 'C' },
Expand Down Expand Up @@ -419,6 +430,12 @@ int main(int argc, char *const *argv)
case OPT_TICKET_IN:
ticket_in = optarg;
break;
case OPT_SERIALIZE_OUT:
serialize_out = optarg;
break;
case OPT_DESERIALIZE_IN:
deserialize_in = optarg;
break;
case 'T':
session_ticket = 0;
break;
Expand Down Expand Up @@ -629,13 +646,29 @@ int main(int argc, char *const *argv)
GUARD_EXIT(s2n_config_set_npn(config, 1), "Error setting npn support");
}

if (serialize_out) {
GUARD_EXIT(s2n_config_set_serialization_version(config, S2N_SERIALIZED_CONN_V1),
"Error setting serialized version");
}

struct s2n_connection *conn = s2n_connection_new(S2N_CLIENT);

if (conn == NULL) {
print_s2n_error("Error getting new connection");
exit(1);
}

if (deserialize_in) {
size_t deserialize_length = 0;
GUARD_EXIT(get_file_size(deserialize_in, &deserialize_length), "Failed to read deserialize-in file size");
ENSURE_EXIT(deserialize_length <= UINT32_MAX, "deserialize-in file size is too large");
uint8_t *mem = malloc(deserialize_length);
GUARD_EXIT_NULL(mem);
GUARD_EXIT(load_file_to_array(deserialize_in, mem, deserialize_length), "Failed to read deserialize-in file");
GUARD_EXIT(s2n_connection_deserialize(conn, mem, (uint32_t) deserialize_length), "Failed to deserialize connection");
free(mem);
maddeleine marked this conversation as resolved.
Show resolved Hide resolved
}

GUARD_EXIT(s2n_connection_set_config(conn, config), "Error setting configuration");

GUARD_EXIT(s2n_set_server_name(conn, server_name), "Error setting server name");
Expand Down Expand Up @@ -684,8 +717,7 @@ int main(int argc, char *const *argv)
}
}

/* See echo.c */
if (negotiate(conn, sockfd) != 0) {
if (!deserialize_in && negotiate(conn, sockfd) != 0) {
/* Error is printed in negotiate */
S2N_ERROR_PRESERVE_ERRNO();
}
Expand Down Expand Up @@ -746,7 +778,17 @@ int main(int argc, char *const *argv)
GUARD_EXIT(renegotiate(conn, sockfd, reneg_ctx.wait), "Renegotiation failed");
}

GUARD_EXIT(wait_for_shutdown(conn, sockfd), "Error closing connection");
if (serialize_out) {
uint32_t serialize_length = 0;
GUARD_EXIT(s2n_connection_serialization_length(conn, &serialize_length), "Failed to get serialized connection length");
uint8_t *mem = malloc(serialize_length);
GUARD_EXIT_NULL(mem);
GUARD_EXIT(s2n_connection_serialize(conn, mem, serialize_length), "Failed to get serialized connection");
GUARD_EXIT(write_array_to_file(serialize_out, mem, serialize_length), "Failed to write serialized connection to file");
free(mem);
} else {
GUARD_EXIT(wait_for_shutdown(conn, sockfd), "Error closing connection");
}

GUARD_EXIT(s2n_connection_free(conn), "Error freeing connection");

Expand Down
38 changes: 34 additions & 4 deletions bin/s2nd.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,9 @@ static char default_private_key[] =
"ggF9KQ0xWz7Km3GXv5+bwM5bcgt1A/s6sZCimXuj3Fle3RqOTF0="
"-----END RSA PRIVATE KEY-----";

#define OPT_BUFFERED_SEND 1000
#define OPT_BUFFERED_SEND 1000
#define OPT_SERIALIZE_OUT 1001
#define OPT_DESERIALIZE_IN 1002

void usage()
{
Expand Down Expand Up @@ -185,6 +187,11 @@ void usage()
fprintf(stderr, " Location of key file used for encryption and decryption of session ticket.\n");
fprintf(stderr, " -T,--no-session-ticket\n");
fprintf(stderr, " Disable session ticket for resumption.\n");
fprintf(stderr, " --serialize-out [file path]\n");
fprintf(stderr, " Path to a file where a serialized connection can be stored.\n"
" Note that this feature is intended to be used with our integration test framework and therefore is not expected to work with s2nd alone.\n");
fprintf(stderr, " --deserialize-in [file path]\n");
fprintf(stderr, " Path to a file where a serialized connection lives. Will be used to skip the handshake and start sending encrypted data.\n");
maddeleine marked this conversation as resolved.
Show resolved Hide resolved
fprintf(stderr, " -C,--corked-io\n");
fprintf(stderr, " Turn on corked io\n");
fprintf(stderr, " --non-blocking\n");
Expand Down Expand Up @@ -221,9 +228,9 @@ int handle_connection(int fd, struct s2n_config *config, struct conn_settings se
S2N_ERROR_PRESERVE_ERRNO();
}

s2n_setup_server_connection(conn, fd, config, settings);
GUARD_EXIT(s2n_setup_server_connection(conn, fd, config, settings), "Error setting up connection");

if (negotiate(conn, fd) != S2N_SUCCESS) {
if (!settings.deserialize_in && negotiate(conn, fd) != S2N_SUCCESS) {
if (settings.mutual_auth) {
if (!s2n_connection_client_cert_used(conn)) {
print_s2n_error("Error: Mutual Auth was required, but not negotiated");
Expand All @@ -243,7 +250,17 @@ int handle_connection(int fd, struct s2n_config *config, struct conn_settings se
echo(conn, fd, &stop_echo);
}

GUARD_RETURN(wait_for_shutdown(conn, fd), "Error closing connection");
if (settings.serialize_out) {
uint32_t serialize_length = 0;
GUARD_EXIT(s2n_connection_serialization_length(conn, &serialize_length), "Failed to get serialized connection length");
uint8_t *mem = malloc(serialize_length);
GUARD_EXIT_NULL(mem);
GUARD_EXIT(s2n_connection_serialize(conn, mem, serialize_length), "Failed to get serialized connection");
GUARD_EXIT(write_array_to_file(settings.serialize_out, mem, serialize_length), "Failed to write serialized connection to file");
free(mem);
} else {
GUARD_RETURN(wait_for_shutdown(conn, fd), "Error closing connection");
}

GUARD_RETURN(s2n_connection_wipe(conn), "Error wiping connection");

Expand Down Expand Up @@ -307,6 +324,8 @@ int main(int argc, char *const *argv)
{ "ca-file", required_argument, 0, 't' },
{ "insecure", no_argument, 0, 'i' },
{ "stk-file", required_argument, 0, 'a' },
{ "serialize-out", required_argument, 0, OPT_SERIALIZE_OUT },
{ "deserialize-in", required_argument, 0, OPT_DESERIALIZE_IN },
{ "no-session-ticket", no_argument, 0, 'T' },
{ "corked-io", no_argument, 0, 'C' },
{ "max-conns", optional_argument, 0, 'X' },
Expand Down Expand Up @@ -426,6 +445,12 @@ int main(int argc, char *const *argv)
send_buffer_size = (uint32_t) send_buffer_size_scanned_value;
break;
}
case OPT_SERIALIZE_OUT:
conn_settings.serialize_out = optarg;
break;
case OPT_DESERIALIZE_IN:
conn_settings.deserialize_in = optarg;
break;
case 'A':
alpn = optarg;
break;
Expand Down Expand Up @@ -616,6 +641,11 @@ int main(int argc, char *const *argv)
GUARD_EXIT(s2n_config_set_npn(config, 1), "Error setting npn support");
}

if (conn_settings.serialize_out) {
GUARD_EXIT(s2n_config_set_serialization_version(config, S2N_SERIALIZED_CONN_V1),
"Error setting serialized version");
}

FILE *key_log_file = NULL;

if (key_log_path) {
Expand Down
Loading