Skip to content

Commit 3b500b3

Browse files
Fix pem validation (#735)
1 parent dfbf8aa commit 3b500b3

File tree

3 files changed

+49
-55
lines changed

3 files changed

+49
-55
lines changed

source/pem.c

Lines changed: 36 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@
99

1010
#include <aws/io/logging.h>
1111

12-
enum aws_pem_parse_state {
13-
BEGIN,
14-
ON_DATA,
15-
END,
16-
};
12+
enum aws_pem_parse_state { BEGIN, ON_DATA };
1713

1814
static const struct aws_byte_cursor begin_header = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("-----BEGIN");
1915
static const struct aws_byte_cursor end_header = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("-----END");
@@ -29,63 +25,48 @@ int aws_sanitize_pem(struct aws_byte_buf *pem, struct aws_allocator *allocator)
2925
return AWS_OP_ERR;
3026
}
3127
struct aws_byte_cursor pem_cursor = aws_byte_cursor_from_buf(pem);
32-
enum aws_pem_parse_state state = BEGIN;
33-
34-
for (size_t i = 0; i < pem_cursor.len; i++) {
35-
/* parse through the pem once */
36-
char current = *(pem_cursor.ptr + i);
37-
switch (state) {
38-
case BEGIN:
39-
if (current == '-') {
40-
struct aws_byte_cursor compare_cursor = pem_cursor;
41-
compare_cursor.len = begin_header.len;
42-
compare_cursor.ptr += i;
43-
if (aws_byte_cursor_eq(&compare_cursor, &begin_header)) {
44-
state = ON_DATA;
45-
i--;
46-
}
47-
}
48-
break;
49-
case ON_DATA:
50-
/* start copying everything */
51-
if (current == '-') {
52-
struct aws_byte_cursor compare_cursor = pem_cursor;
53-
compare_cursor.len = end_header.len;
54-
compare_cursor.ptr += i;
55-
if (aws_byte_cursor_eq(&compare_cursor, &end_header)) {
56-
/* Copy the end header string and start to search for the end part of a pem */
57-
state = END;
58-
aws_byte_buf_append(&clean_pem_buf, &end_header);
59-
i += (end_header.len - 1);
60-
break;
61-
}
62-
}
63-
aws_byte_buf_append_byte_dynamic(&clean_pem_buf, (uint8_t)current);
64-
break;
65-
case END:
66-
if (current == '-') {
67-
struct aws_byte_cursor compare_cursor = pem_cursor;
68-
compare_cursor.len = dashes.len;
69-
compare_cursor.ptr += i;
70-
if (aws_byte_cursor_eq(&compare_cursor, &dashes)) {
71-
/* End part of a pem, copy the last 5 dashes and a new line, then ignore everything before next
72-
* begin header */
73-
state = BEGIN;
74-
aws_byte_buf_append(&clean_pem_buf, &dashes);
75-
i += (dashes.len - 1);
28+
bool is_on_data = false;
29+
30+
while (pem_cursor.len > 0) {
31+
if (!is_on_data) {
32+
if (aws_byte_cursor_starts_with(&pem_cursor, &begin_header)) {
33+
/* mini optimization - just copy over begin to avoid all the starts with checks */
34+
aws_byte_buf_append_dynamic(&clean_pem_buf, &begin_header);
35+
aws_byte_cursor_advance(&pem_cursor, begin_header.len);
36+
is_on_data = true;
37+
} else {
38+
aws_byte_cursor_advance(&pem_cursor, 1);
39+
}
40+
} else {
41+
/* Note this does not validate that end label is same as begin label. */
42+
if (aws_byte_cursor_starts_with(&pem_cursor, &end_header)) {
43+
/* copy over end */
44+
aws_byte_buf_append_dynamic(&clean_pem_buf, &end_header);
45+
aws_byte_cursor_advance(&pem_cursor, end_header.len);
46+
47+
/* copy over label until the closing 5 dashes */
48+
while (pem_cursor.len > 0) {
49+
aws_byte_buf_append_byte_dynamic(&clean_pem_buf, *pem_cursor.ptr);
50+
aws_byte_cursor_advance(&pem_cursor, 1);
51+
52+
if (aws_byte_cursor_starts_with(&pem_cursor, &dashes)) {
53+
aws_byte_buf_append_dynamic(&clean_pem_buf, &dashes);
54+
aws_byte_cursor_advance(&pem_cursor, dashes.len);
7655
aws_byte_buf_append_byte_dynamic(&clean_pem_buf, (uint8_t)'\n');
56+
is_on_data = false;
7757
break;
7858
}
7959
}
80-
aws_byte_buf_append_byte_dynamic(&clean_pem_buf, (uint8_t)current);
81-
break;
82-
default:
83-
break;
60+
} else {
61+
aws_byte_buf_append_byte_dynamic(&clean_pem_buf, *pem_cursor.ptr);
62+
aws_byte_cursor_advance(&pem_cursor, 1);
63+
}
8464
}
8565
}
8666

87-
if (clean_pem_buf.len == 0) {
88-
/* No valid data remains after sanitization. File might have been the wrong format */
67+
if (clean_pem_buf.len == 0 || is_on_data) {
68+
/* No valid data remains after sanitization or data block is left hanging.
69+
File might have been the wrong format */
8970
aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
9071
goto error;
9172
}

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ add_test_case(test_pem_invalid_in_chain_parse)
156156
add_test_case(pem_sanitize_comments_around_pem_object_removed)
157157
add_test_case(pem_sanitize_empty_file_rejected)
158158
add_test_case(pem_sanitize_wrong_format_rejected)
159+
add_test_case(pem_sanitize_bad_format_rejected)
159160

160161
add_test_case(socket_handler_echo_and_backpressure)
161162
add_test_case(socket_handler_close)

tests/pem_test.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,18 @@ static int s_test_pem_sanitize_empty_file_rejected(struct aws_allocator *allocat
5959

6060
AWS_TEST_CASE(pem_sanitize_empty_file_rejected, s_test_pem_sanitize_empty_file_rejected)
6161

62+
static int s_test_pem_sanitize_bad_format_rejected(struct aws_allocator *allocator, void *ctx) {
63+
(void)ctx;
64+
struct aws_byte_buf pem = aws_byte_buf_from_c_str("aaaaa-");
65+
66+
ASSERT_ERROR(AWS_ERROR_INVALID_ARGUMENT, aws_sanitize_pem(&pem, allocator));
67+
68+
aws_byte_buf_clean_up(&pem);
69+
return AWS_OP_SUCCESS;
70+
}
71+
72+
AWS_TEST_CASE(pem_sanitize_bad_format_rejected, s_test_pem_sanitize_bad_format_rejected)
73+
6274
AWS_TEST_CASE(pem_sanitize_wrong_format_rejected, s_test_pem_sanitize_wrong_format_rejected)
6375
static int s_test_pem_sanitize_wrong_format_rejected(struct aws_allocator *allocator, void *ctx) {
6476
(void)ctx;

0 commit comments

Comments
 (0)