Skip to content

Commit

Permalink
PR comments
Browse files Browse the repository at this point in the history
  • Loading branch information
lrstewart committed Jun 14, 2024
1 parent 59548ec commit 62ebbaa
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 43 deletions.
106 changes: 73 additions & 33 deletions tests/unit/s2n_fingerprint_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,8 @@
#define S2N_TEST_HASH S2N_HASH_SHA256
#define TEST_COUNT 10

static S2N_RESULT s2n_test_hash_new(struct s2n_fingerprint_hash *hash,
struct s2n_hash_state *hash_state)
static S2N_RESULT s2n_test_hash_state_new(struct s2n_hash_state *hash_state)
{
hash->hash = hash_state;
hash->do_digest = true;
EXPECT_SUCCESS(s2n_hash_new(hash_state));
EXPECT_SUCCESS(s2n_hash_init(hash_state, S2N_TEST_HASH));
return S2N_RESULT_OK;
Expand All @@ -41,6 +38,12 @@ int main(int argc, char **argv)
const size_t test_str_len = strlen(test_str);
EXPECT_NOT_EQUAL(test_char, test_str[0]);

const uint8_t test_str_digest[] = {
0x2c, 0xf2, 0x4d, 0xba, 0x5f, 0xb0, 0xa3, 0xe, 0x26, 0xe8, 0x3b,
0x2a, 0xc5, 0xb9, 0xe2, 0x9e, 0x1b, 0x16, 0x1e, 0x5c, 0x1f, 0xa7,
0x42, 0x5e, 0x73, 0x4, 0x33, 0x62, 0x93, 0x8b, 0x98, 0x24
};

/* Test s2n_fingerprint_hash_add_char */
{
/* Safety */
Expand All @@ -66,8 +69,8 @@ int main(int argc, char **argv)
/* Add to hash */
{
DEFER_CLEANUP(struct s2n_hash_state hash_state = { 0 }, s2n_hash_free);
struct s2n_fingerprint_hash hash = { 0 };
EXPECT_OK(s2n_test_hash_new(&hash, &hash_state));
EXPECT_OK(s2n_test_hash_state_new(&hash_state));
struct s2n_fingerprint_hash hash = { .hash = &hash_state };

for (size_t i = 1; i <= TEST_COUNT; i++) {
EXPECT_OK(s2n_fingerprint_hash_add_char(&hash, test_char));
Expand All @@ -92,8 +95,31 @@ int main(int argc, char **argv)
/* Test s2n_fingerprint_hash_add_str */
{
/* Safety */
EXPECT_ERROR_WITH_ERRNO(s2n_fingerprint_hash_add_str(NULL, test_str),
S2N_ERR_NULL);
{
/* Null hash */
EXPECT_ERROR_WITH_ERRNO(s2n_fingerprint_hash_add_str(NULL, test_str, 0),
S2N_ERR_NULL);

/* Null str with stuffer */
{
DEFER_CLEANUP(struct s2n_stuffer output = { 0 }, s2n_stuffer_free);
EXPECT_SUCCESS(s2n_stuffer_alloc(&output, 100));
struct s2n_fingerprint_hash hash = { .buffer = &output };
EXPECT_ERROR_WITH_ERRNO(s2n_fingerprint_hash_add_str(&hash, NULL, 10),
S2N_ERR_NULL);
EXPECT_OK(s2n_fingerprint_hash_add_str(&hash, NULL, 0));
}

/* Null str with hash */
{
DEFER_CLEANUP(struct s2n_hash_state hash_state = { 0 }, s2n_hash_free);
EXPECT_OK(s2n_test_hash_state_new(&hash_state));
struct s2n_fingerprint_hash hash = { .hash = &hash_state };
EXPECT_ERROR_WITH_ERRNO(s2n_fingerprint_hash_add_str(&hash, NULL, 10),
S2N_ERR_NULL);
EXPECT_OK(s2n_fingerprint_hash_add_str(&hash, NULL, 0));
}
}

/* Add to stuffer */
{
Expand All @@ -102,7 +128,7 @@ int main(int argc, char **argv)
struct s2n_fingerprint_hash hash = { .buffer = &output };

for (size_t i = 1; i <= TEST_COUNT; i++) {
EXPECT_OK(s2n_fingerprint_hash_add_str(&hash, test_str));
EXPECT_OK(s2n_fingerprint_hash_add_str(&hash, test_str, test_str_len));
EXPECT_EQUAL(s2n_stuffer_data_available(&output), test_str_len);

uint8_t actual_value[sizeof(test_str)] = { 0 };
Expand All @@ -114,11 +140,11 @@ int main(int argc, char **argv)
/* Add to hash */
{
DEFER_CLEANUP(struct s2n_hash_state hash_state = { 0 }, s2n_hash_free);
struct s2n_fingerprint_hash hash = { 0 };
EXPECT_OK(s2n_test_hash_new(&hash, &hash_state));
EXPECT_OK(s2n_test_hash_state_new(&hash_state));
struct s2n_fingerprint_hash hash = { .hash = &hash_state };

for (size_t i = 1; i <= TEST_COUNT; i++) {
EXPECT_OK(s2n_fingerprint_hash_add_str(&hash, test_str));
EXPECT_OK(s2n_fingerprint_hash_add_str(&hash, test_str, test_str_len));
EXPECT_EQUAL(hash.hash->currently_in_hash, test_str_len * i);
}
}
Expand All @@ -127,36 +153,33 @@ int main(int argc, char **argv)
{
struct s2n_stuffer output = { 0 };
struct s2n_fingerprint_hash hash = { .buffer = &output };
EXPECT_ERROR_WITH_ERRNO(s2n_fingerprint_hash_add_str(&hash, test_str),
EXPECT_ERROR_WITH_ERRNO(
s2n_fingerprint_hash_add_str(&hash, test_str, test_str_len),
S2N_ERR_INSUFFICIENT_MEM_SIZE);

EXPECT_SUCCESS(s2n_stuffer_alloc(&output, 1));
EXPECT_ERROR_WITH_ERRNO(s2n_fingerprint_hash_add_str(&hash, test_str),
EXPECT_ERROR_WITH_ERRNO(
s2n_fingerprint_hash_add_str(&hash, test_str, test_str_len),
S2N_ERR_INSUFFICIENT_MEM_SIZE);
EXPECT_SUCCESS(s2n_stuffer_free(&output));

EXPECT_SUCCESS(s2n_stuffer_alloc(&output, test_str_len - 1));
EXPECT_ERROR_WITH_ERRNO(s2n_fingerprint_hash_add_str(&hash, test_str),
EXPECT_ERROR_WITH_ERRNO(
s2n_fingerprint_hash_add_str(&hash, test_str, test_str_len),
S2N_ERR_INSUFFICIENT_MEM_SIZE);
EXPECT_SUCCESS(s2n_stuffer_free(&output));

EXPECT_SUCCESS(s2n_stuffer_alloc(&output, test_str_len));
EXPECT_OK(s2n_fingerprint_hash_add_char(&hash, test_char));
EXPECT_ERROR_WITH_ERRNO(s2n_fingerprint_hash_add_str(&hash, test_str),
EXPECT_ERROR_WITH_ERRNO(
s2n_fingerprint_hash_add_str(&hash, test_str, test_str_len),
S2N_ERR_INSUFFICIENT_MEM_SIZE);
EXPECT_SUCCESS(s2n_stuffer_free(&output));
}
}

/* Test s2n_fingerprint_hash_digest */
{
const char test_value[] = "hello";
const uint8_t digest_value[] = {
0x2c, 0xf2, 0x4d, 0xba, 0x5f, 0xb0, 0xa3, 0xe, 0x26, 0xe8, 0x3b,
0x2a, 0xc5, 0xb9, 0xe2, 0x9e, 0x1b, 0x16, 0x1e, 0x5c, 0x1f, 0xa7,
0x42, 0x5e, 0x73, 0x4, 0x33, 0x62, 0x93, 0x8b, 0x98, 0x24
};

/* Safety */
{
uint8_t output_value[1] = { 0 };
Expand All @@ -168,35 +191,52 @@ int main(int argc, char **argv)
/* Digest successfully calculated */
{
DEFER_CLEANUP(struct s2n_hash_state hash_state = { 0 }, s2n_hash_free);
struct s2n_fingerprint_hash hash = { 0 };
EXPECT_OK(s2n_test_hash_new(&hash, &hash_state));
EXPECT_OK(s2n_test_hash_state_new(&hash_state));
struct s2n_fingerprint_hash hash = { .hash = &hash_state };

EXPECT_OK(s2n_fingerprint_hash_add_str(&hash, test_value));
EXPECT_OK(s2n_fingerprint_hash_add_str(&hash, test_str, test_str_len));
EXPECT_EQUAL(hash.hash->currently_in_hash, test_str_len);

uint8_t actual_digest[sizeof(digest_value)] = { 0 };
uint8_t actual_digest[sizeof(test_str_digest)] = { 0 };
EXPECT_OK(s2n_fingerprint_hash_digest(&hash, actual_digest, sizeof(actual_digest)));
EXPECT_BYTEARRAY_EQUAL(actual_digest, digest_value, sizeof(digest_value));
EXPECT_BYTEARRAY_EQUAL(actual_digest, test_str_digest, sizeof(test_str_digest));
EXPECT_EQUAL(hash.bytes_digested, test_str_len);
}

/* Hash can be reused after digest */
{
DEFER_CLEANUP(struct s2n_hash_state hash_state = { 0 }, s2n_hash_free);
struct s2n_fingerprint_hash hash = { 0 };
EXPECT_OK(s2n_test_hash_new(&hash, &hash_state));
EXPECT_OK(s2n_test_hash_state_new(&hash_state));
struct s2n_fingerprint_hash hash = { .hash = &hash_state };

const size_t count = 10;
for (size_t i = 0; i < count; i++) {
uint8_t actual_digest[sizeof(digest_value)] = { 0 };
EXPECT_OK(s2n_fingerprint_hash_add_str(&hash, test_value));
uint8_t actual_digest[sizeof(test_str_digest)] = { 0 };
EXPECT_OK(s2n_fingerprint_hash_add_str(&hash, test_str, test_str_len));
EXPECT_OK(s2n_fingerprint_hash_digest(&hash, actual_digest, sizeof(actual_digest)));
EXPECT_BYTEARRAY_EQUAL(actual_digest, digest_value, sizeof(digest_value));
EXPECT_BYTEARRAY_EQUAL(actual_digest, test_str_digest, sizeof(test_str_digest));
}
EXPECT_EQUAL(hash.bytes_digested, test_str_len * count);
}
}

/* Test s2n_fingerprint_hash_supports_digest */
{
/* Safety */
EXPECT_FALSE(s2n_fingerprint_hash_supports_digest(NULL));

struct s2n_fingerprint_hash hash = { 0 };
EXPECT_FALSE(s2n_fingerprint_hash_supports_digest(&hash));

struct s2n_stuffer output = { 0 };
hash.buffer = &output;
EXPECT_FALSE(s2n_fingerprint_hash_supports_digest(&hash));

struct s2n_hash_state hash_state = { 0 };
hash.hash = &hash_state;
EXPECT_TRUE(s2n_fingerprint_hash_supports_digest(&hash));
}

/* Test s2n_assert_grease_value */
{
EXPECT_TRUE(s2n_is_grease_value(0x0A0A));
Expand Down
23 changes: 17 additions & 6 deletions tls/s2n_fingerprint.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,26 @@ S2N_RESULT s2n_fingerprint_hash_add_char(struct s2n_fingerprint_hash *hash, char
if (hash->hash) {
RESULT_GUARD_POSIX(s2n_hash_update(hash->hash, &c, 1));
} else {
RESULT_ENSURE_REF(hash->buffer);
RESULT_ENSURE(s2n_stuffer_space_remaining(hash->buffer) >= 1,
S2N_ERR_INSUFFICIENT_MEM_SIZE);
RESULT_GUARD_POSIX(s2n_stuffer_write_char(hash->buffer, c));
}
return S2N_RESULT_OK;
}

S2N_RESULT s2n_fingerprint_hash_add_str(struct s2n_fingerprint_hash *hash, const char *str)
S2N_RESULT s2n_fingerprint_hash_add_str(struct s2n_fingerprint_hash *hash,
const char *str, size_t str_size)
{
RESULT_ENSURE_REF(hash);
RESULT_ENSURE(S2N_MEM_IS_READABLE(str, str_size), S2N_ERR_NULL);
if (hash->hash) {
RESULT_GUARD_POSIX(s2n_hash_update(hash->hash, str, strlen(str)));
RESULT_GUARD_POSIX(s2n_hash_update(hash->hash, str, str_size));
} else {
RESULT_ENSURE(s2n_stuffer_space_remaining(hash->buffer) >= strlen(str),
RESULT_ENSURE_REF(hash->buffer);
RESULT_ENSURE(s2n_stuffer_space_remaining(hash->buffer) >= str_size,
S2N_ERR_INSUFFICIENT_MEM_SIZE);
RESULT_GUARD_POSIX(s2n_stuffer_write_str(hash->buffer, str));
RESULT_GUARD_POSIX(s2n_stuffer_write_text(hash->buffer, str, str_size));
}
return S2N_RESULT_OK;
}
Expand All @@ -69,13 +73,21 @@ S2N_RESULT s2n_fingerprint_hash_digest(struct s2n_fingerprint_hash *hash, uint8_
{
RESULT_ENSURE_REF(hash);
RESULT_ENSURE_REF(hash->hash);
hash->bytes_digested += hash->hash->currently_in_hash;

uint64_t bytes = 0;
RESULT_GUARD_POSIX(s2n_hash_get_currently_in_hash_total(hash->hash, &bytes));
hash->bytes_digested += bytes;

RESULT_GUARD_POSIX(s2n_hash_digest(hash->hash, out, out_size));
RESULT_GUARD_POSIX(s2n_hash_reset(hash->hash));
return S2N_RESULT_OK;
}

bool s2n_fingerprint_hash_supports_digest(struct s2n_fingerprint_hash *hash)
{
return hash && hash->hash;
}

int s2n_client_hello_get_fingerprint_hash(struct s2n_client_hello *ch, s2n_fingerprint_type type,
uint32_t max_output_size, uint8_t *output, uint32_t *output_size, uint32_t *str_size)
{
Expand Down Expand Up @@ -104,7 +116,6 @@ int s2n_client_hello_get_fingerprint_hash(struct s2n_client_hello *ch, s2n_finge

struct s2n_fingerprint_hash hash = {
.hash = &hash_state,
.do_digest = true,
};

POSIX_GUARD_RESULT(method->fingerprint(ch, &hash, &output_stuffer));
Expand Down
4 changes: 2 additions & 2 deletions tls/s2n_fingerprint.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ struct s2n_fingerprint_hash {
uint32_t bytes_digested;
struct s2n_stuffer *buffer;
struct s2n_hash_state *hash;
unsigned int do_digest : 1;
};
S2N_RESULT s2n_fingerprint_hash_add_char(struct s2n_fingerprint_hash *hash, char c);
S2N_RESULT s2n_fingerprint_hash_add_str(struct s2n_fingerprint_hash *hash, const char *str);
S2N_RESULT s2n_fingerprint_hash_add_str(struct s2n_fingerprint_hash *hash, const char *str, size_t str_size);
S2N_RESULT s2n_fingerprint_hash_digest(struct s2n_fingerprint_hash *hash, uint8_t *out, size_t out_size);
bool s2n_fingerprint_hash_supports_digest(struct s2n_fingerprint_hash *hash);

struct s2n_fingerprint_method {
s2n_hash_algorithm hash;
Expand Down
4 changes: 2 additions & 2 deletions tls/s2n_fingerprint_ja3.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
static S2N_RESULT s2n_fingerprint_ja3_digest(struct s2n_fingerprint_hash *hash,
struct s2n_stuffer *out)
{
if (!hash->do_digest) {
if (!s2n_fingerprint_hash_supports_digest(hash)) {
return S2N_RESULT_OK;
}

Expand Down Expand Up @@ -56,7 +56,7 @@ static S2N_RESULT s2n_fingerprint_ja3_iana(struct s2n_fingerprint_hash *hash,
RESULT_ENSURE_GT(written, 0);
RESULT_ENSURE_LTE(written, S2N_UINT16_STR_MAX_SIZE);

RESULT_GUARD(s2n_fingerprint_hash_add_str(hash, str));
RESULT_GUARD(s2n_fingerprint_hash_add_str(hash, str, written));
return S2N_RESULT_OK;
}

Expand Down

0 comments on commit 62ebbaa

Please sign in to comment.