pem_utils.c 3.8 KB

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