1 /**
2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 * SPDX-License-Identifier: Apache-2.0.
4 */
5 #include <aws/common/string.h>
6 #include <aws/io/private/pem_utils.h>
7
8 enum aws_pem_util_state {
9 BEGIN,
10 ON_DATA,
11 END,
12 };
13
14 static const struct aws_byte_cursor begin_header = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("-----BEGIN");
15 static const struct aws_byte_cursor end_header = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("-----END");
16 static const struct aws_byte_cursor dashes = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("-----");
17
aws_sanitize_pem(struct aws_byte_buf * pem,struct aws_allocator * allocator)18 int aws_sanitize_pem(struct aws_byte_buf *pem, struct aws_allocator *allocator) {
19 if (!pem->len) {
20 /* reject files with no PEM data */
21 return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
22 }
23 struct aws_byte_buf clean_pem_buf;
24 if (aws_byte_buf_init(&clean_pem_buf, allocator, pem->len)) {
25 return AWS_OP_ERR;
26 }
27 struct aws_byte_cursor pem_cursor = aws_byte_cursor_from_buf(pem);
28 int state = BEGIN;
29
30 for (size_t i = 0; i < pem_cursor.len; i++) {
31 /* parse through the pem once */
32 char current = *(pem_cursor.ptr + i);
33 switch (state) {
34 case BEGIN:
35 if (current == '-') {
36 struct aws_byte_cursor compare_cursor = pem_cursor;
37 compare_cursor.len = begin_header.len;
38 compare_cursor.ptr += i;
39 if (aws_byte_cursor_eq(&compare_cursor, &begin_header)) {
40 state = ON_DATA;
41 i--;
42 }
43 }
44 break;
45 case ON_DATA:
46 /* start copying everything */
47 if (current == '-') {
48 struct aws_byte_cursor compare_cursor = pem_cursor;
49 compare_cursor.len = end_header.len;
50 compare_cursor.ptr += i;
51 if (aws_byte_cursor_eq(&compare_cursor, &end_header)) {
52 /* Copy the end header string and start to search for the end part of a pem */
53 state = END;
54 aws_byte_buf_append(&clean_pem_buf, &end_header);
55 i += (end_header.len - 1);
56 break;
57 }
58 }
59 aws_byte_buf_append_byte_dynamic(&clean_pem_buf, (uint8_t)current);
60 break;
61 case END:
62 if (current == '-') {
63 struct aws_byte_cursor compare_cursor = pem_cursor;
64 compare_cursor.len = dashes.len;
65 compare_cursor.ptr += i;
66 if (aws_byte_cursor_eq(&compare_cursor, &dashes)) {
67 /* End part of a pem, copy the last 5 dashes and a new line, then ignore everything before next
68 * begin header */
69 state = BEGIN;
70 aws_byte_buf_append(&clean_pem_buf, &dashes);
71 i += (dashes.len - 1);
72 aws_byte_buf_append_byte_dynamic(&clean_pem_buf, (uint8_t)'\n');
73 break;
74 }
75 }
76 aws_byte_buf_append_byte_dynamic(&clean_pem_buf, (uint8_t)current);
77 break;
78 default:
79 break;
80 }
81 }
82
83 if (clean_pem_buf.len == 0) {
84 /* No valid data remains after sanitization. File might have been the wrong format */
85 aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
86 goto error;
87 }
88
89 struct aws_byte_cursor clean_pem_cursor = aws_byte_cursor_from_buf(&clean_pem_buf);
90 aws_byte_buf_reset(pem, true);
91 aws_byte_buf_append_dynamic(pem, &clean_pem_cursor);
92 aws_byte_buf_clean_up(&clean_pem_buf);
93 return AWS_OP_SUCCESS;
94
95 error:
96 aws_byte_buf_clean_up(&clean_pem_buf);
97 return AWS_OP_ERR;
98 }
99