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