in source/pki_utils.c [36:138]
static int s_convert_pem_to_raw_base64(
struct aws_allocator *allocator,
const struct aws_byte_cursor *pem,
struct aws_array_list *cert_chain_or_key) {
enum PEM_PARSE_STATE state = BEGIN;
struct aws_byte_buf current_cert;
const char *begin_header = "-----BEGIN";
const char *end_header = "-----END";
size_t begin_header_len = strlen(begin_header);
size_t end_header_len = strlen(end_header);
bool on_length_calc = true;
struct aws_array_list split_buffers;
if (aws_array_list_init_dynamic(&split_buffers, allocator, 16, sizeof(struct aws_byte_cursor))) {
return AWS_OP_ERR;
}
if (aws_byte_cursor_split_on_char(pem, '\n', &split_buffers)) {
aws_array_list_clean_up(&split_buffers);
AWS_LOGF_ERROR(AWS_LS_IO_PKI, "static: Invalid PEM buffer: failed to split on newline");
return AWS_OP_ERR;
}
size_t split_count = aws_array_list_length(&split_buffers);
size_t i = 0;
size_t index_of_current_cert_start = 0;
size_t current_cert_len = 0;
while (i < split_count) {
struct aws_byte_cursor *current_cur_ptr = NULL;
aws_array_list_get_at_ptr(&split_buffers, (void **)¤t_cur_ptr, i);
/* burn off the padding in the buffer first.
* Worst case we'll only have to do this once per line in the buffer. */
while (current_cur_ptr->len && aws_isspace(*current_cur_ptr->ptr)) {
aws_byte_cursor_advance(current_cur_ptr, 1);
}
/* handle CRLF on Windows by burning '\r' off the end of the buffer */
if (current_cur_ptr->len && (current_cur_ptr->ptr[current_cur_ptr->len - 1] == '\r')) {
current_cur_ptr->len--;
}
switch (state) {
case BEGIN:
if (current_cur_ptr->len > begin_header_len &&
!strncmp((const char *)current_cur_ptr->ptr, begin_header, begin_header_len)) {
state = ON_DATA;
index_of_current_cert_start = i + 1;
}
++i;
break;
/* this loops through the lines containing data twice. First to figure out the length, a second
* time to actually copy the data. */
case ON_DATA:
/* Found end tag. */
if (current_cur_ptr->len > end_header_len &&
!strncmp((const char *)current_cur_ptr->ptr, end_header, end_header_len)) {
if (on_length_calc) {
on_length_calc = false;
state = ON_DATA;
i = index_of_current_cert_start;
if (aws_byte_buf_init(¤t_cert, allocator, current_cert_len)) {
goto end_of_loop;
}
} else {
if (aws_array_list_push_back(cert_chain_or_key, ¤t_cert)) {
aws_secure_zero(¤t_cert.buffer, current_cert.len);
aws_byte_buf_clean_up(¤t_cert);
goto end_of_loop;
}
state = BEGIN;
on_length_calc = true;
current_cert_len = 0;
++i;
}
/* actually on a line with data in it. */
} else {
if (!on_length_calc) {
aws_byte_buf_write(¤t_cert, current_cur_ptr->ptr, current_cur_ptr->len);
} else {
current_cert_len += current_cur_ptr->len;
}
++i;
}
break;
}
}
end_of_loop:
aws_array_list_clean_up(&split_buffers);
if (state == BEGIN && aws_array_list_length(cert_chain_or_key) > 0) {
return AWS_OP_SUCCESS;
}
AWS_LOGF_ERROR(AWS_LS_IO_PKI, "static: Invalid PEM buffer.");
aws_cert_chain_clean_up(cert_chain_or_key);
return aws_raise_error(AWS_IO_FILE_VALIDATION_FAILURE);
}