pq_crypto 0.6.7 → 0.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -783,13 +783,46 @@ static const pq_serialization_algorithm_t *pq_find_serialization_algorithm_by_oi
783
783
  return NULL;
784
784
  }
785
785
 
786
+ static int pq_serialized_key_size(size_t oid_len, size_t key_len, size_t *total_len) {
787
+ const size_t parts[] = {8, oid_len, 4, key_len};
788
+ size_t total = 0;
789
+
790
+ for (size_t i = 0; i < sizeof(parts) / sizeof(parts[0]); ++i) {
791
+ if (pq_size_add(total, parts[i], &total) != PQ_SUCCESS)
792
+ return PQ_ERROR_BUFFER;
793
+ }
794
+ *total_len = total;
795
+ return PQ_SUCCESS;
796
+ }
797
+
798
+ static void pq_write_u16be(uint8_t *output, uint16_t value) {
799
+ output[0] = (uint8_t)(value >> 8);
800
+ output[1] = (uint8_t)value;
801
+ }
802
+
803
+ static void pq_write_u32be(uint8_t *output, uint32_t value) {
804
+ output[0] = (uint8_t)(value >> 24);
805
+ output[1] = (uint8_t)(value >> 16);
806
+ output[2] = (uint8_t)(value >> 8);
807
+ output[3] = (uint8_t)value;
808
+ }
809
+
810
+ static uint16_t pq_read_u16be(const uint8_t *input) {
811
+ return (uint16_t)(((uint16_t)input[0] << 8) | input[1]);
812
+ }
813
+
814
+ static uint32_t pq_read_u32be(const uint8_t *input) {
815
+ return ((uint32_t)input[0] << 24) | ((uint32_t)input[1] << 16) | ((uint32_t)input[2] << 8) |
816
+ input[3];
817
+ }
818
+
786
819
  static int pq_encode_serialized_key(uint8_t **output, size_t *output_len, uint8_t type,
787
820
  const uint8_t *key_bytes, size_t key_len,
788
821
  const char *algorithm) {
789
822
  const pq_serialization_algorithm_t *entry;
790
823
  size_t expected_len;
791
824
  size_t oid_len;
792
- size_t total_len = 0;
825
+ size_t total_len;
793
826
  uint8_t *buf;
794
827
  int ret;
795
828
 
@@ -814,19 +847,7 @@ static int pq_encode_serialized_key(uint8_t **output, size_t *output_len, uint8_
814
847
  if (key_len > UINT32_MAX)
815
848
  return PQ_ERROR_BUFFER;
816
849
 
817
- ret = pq_size_add(total_len, 4, &total_len);
818
- if (ret != PQ_SUCCESS)
819
- return ret;
820
- ret = pq_size_add(total_len, 1 + 1 + 2, &total_len);
821
- if (ret != PQ_SUCCESS)
822
- return ret;
823
- ret = pq_size_add(total_len, oid_len, &total_len);
824
- if (ret != PQ_SUCCESS)
825
- return ret;
826
- ret = pq_size_add(total_len, 4, &total_len);
827
- if (ret != PQ_SUCCESS)
828
- return ret;
829
- ret = pq_size_add(total_len, key_len, &total_len);
850
+ ret = pq_serialized_key_size(oid_len, key_len, &total_len);
830
851
  if (ret != PQ_SUCCESS)
831
852
  return ret;
832
853
 
@@ -840,13 +861,9 @@ static int pq_encode_serialized_key(uint8_t **output, size_t *output_len, uint8_
840
861
  buf[3] = PQC_SERIALIZATION_MAGIC_3;
841
862
  buf[4] = PQC_SERIALIZATION_VERSION;
842
863
  buf[5] = type;
843
- buf[6] = (uint8_t)((oid_len >> 8) & 0xFF);
844
- buf[7] = (uint8_t)(oid_len & 0xFF);
864
+ pq_write_u16be(buf + 6, (uint16_t)oid_len);
845
865
  memcpy(buf + 8, entry->oid, oid_len);
846
- buf[8 + oid_len + 0] = (uint8_t)((key_len >> 24) & 0xFF);
847
- buf[8 + oid_len + 1] = (uint8_t)((key_len >> 16) & 0xFF);
848
- buf[8 + oid_len + 2] = (uint8_t)((key_len >> 8) & 0xFF);
849
- buf[8 + oid_len + 3] = (uint8_t)(key_len & 0xFF);
866
+ pq_write_u32be(buf + 8 + oid_len, (uint32_t)key_len);
850
867
  memcpy(buf + 8 + oid_len + 4, key_bytes, key_len);
851
868
 
852
869
  *output = buf;
@@ -854,62 +871,92 @@ static int pq_encode_serialized_key(uint8_t **output, size_t *output_len, uint8_
854
871
  return PQ_SUCCESS;
855
872
  }
856
873
 
857
- static int pq_decode_serialized_key(const uint8_t *input, size_t input_len, uint8_t expected_type,
858
- char **algorithm_out, uint8_t **key_out, size_t *key_len_out) {
859
- uint16_t oid_len;
860
- uint32_t key_len;
861
- const pq_serialization_algorithm_t *entry;
862
- size_t offset;
863
- size_t expected_len = 0;
864
- uint8_t *key_copy = NULL;
865
- char *algorithm_copy = NULL;
866
-
867
- if (!input || !algorithm_out || !key_out || !key_len_out)
874
+ static int pq_serialized_key_header(uint8_t expected_type, const uint8_t *input, size_t input_len,
875
+ uint16_t *oid_len_out) {
876
+ if (!input || !oid_len_out)
868
877
  return PQ_ERROR_BUFFER;
869
-
870
- *algorithm_out = NULL;
871
- *key_out = NULL;
872
- *key_len_out = 0;
873
-
874
878
  if (input_len < 12)
875
879
  return PQ_ERROR_BUFFER;
876
880
  if (input[0] != PQC_SERIALIZATION_MAGIC_0 || input[1] != PQC_SERIALIZATION_MAGIC_1 ||
877
- input[2] != PQC_SERIALIZATION_MAGIC_2 || input[3] != PQC_SERIALIZATION_MAGIC_3) {
881
+ input[2] != PQC_SERIALIZATION_MAGIC_2 || input[3] != PQC_SERIALIZATION_MAGIC_3)
878
882
  return PQ_ERROR_BUFFER;
879
- }
880
883
  if (input[4] != PQC_SERIALIZATION_VERSION || input[5] != expected_type)
881
884
  return PQ_ERROR_BUFFER;
882
885
 
883
- oid_len = ((uint16_t)input[6] << 8) | (uint16_t)input[7];
884
- if (oid_len == 0)
886
+ *oid_len_out = pq_read_u16be(input + 6);
887
+ if (*oid_len_out == 0 || input_len - 8 < (size_t)*oid_len_out + 4)
885
888
  return PQ_ERROR_BUFFER;
886
- offset = 8;
887
- if (input_len < offset || input_len - offset < (size_t)oid_len + 4)
889
+ return PQ_SUCCESS;
890
+ }
891
+
892
+ static int pq_serialized_key_payload(const uint8_t *input, size_t input_len, uint8_t expected_type,
893
+ const pq_serialization_algorithm_t **entry_out,
894
+ const uint8_t **key_out, size_t *key_len_out) {
895
+ uint16_t oid_len;
896
+ uint32_t key_len;
897
+ const pq_serialization_algorithm_t *entry;
898
+ size_t offset = 8;
899
+ size_t expected_len;
900
+ int ret;
901
+
902
+ if (!entry_out || !key_out || !key_len_out)
888
903
  return PQ_ERROR_BUFFER;
904
+ *entry_out = NULL;
905
+ *key_out = NULL;
906
+ *key_len_out = 0;
907
+
908
+ ret = pq_serialized_key_header(expected_type, input, input_len, &oid_len);
909
+ if (ret != PQ_SUCCESS)
910
+ return ret;
889
911
  entry = pq_find_serialization_algorithm_by_oid((const char *)(input + offset), oid_len);
890
912
  if (!entry)
891
913
  return PQ_ERROR_BUFFER;
892
914
  offset += oid_len;
893
- key_len = ((uint32_t)input[offset + 0] << 24) | ((uint32_t)input[offset + 1] << 16) |
894
- ((uint32_t)input[offset + 2] << 8) | (uint32_t)input[offset + 3];
915
+ key_len = pq_read_u32be(input + offset);
895
916
  offset += 4;
896
- if (input_len < offset || input_len - offset != (size_t)key_len)
917
+ if (input_len - offset != (size_t)key_len)
897
918
  return PQ_ERROR_BUFFER;
898
919
  expected_len = (expected_type == PQC_SERIALIZATION_TYPE_PUBLIC) ? entry->public_key_len
899
920
  : entry->secret_key_len;
900
921
  if ((size_t)key_len != expected_len)
901
922
  return PQ_ERROR_BUFFER;
902
923
 
903
- key_copy = malloc((size_t)key_len);
924
+ *entry_out = entry;
925
+ *key_out = input + offset;
926
+ *key_len_out = (size_t)key_len;
927
+ return PQ_SUCCESS;
928
+ }
929
+
930
+ static int pq_decode_serialized_key(const uint8_t *input, size_t input_len, uint8_t expected_type,
931
+ char **algorithm_out, uint8_t **key_out, size_t *key_len_out) {
932
+ const pq_serialization_algorithm_t *entry = NULL;
933
+ const uint8_t *key_data = NULL;
934
+ size_t key_len = 0;
935
+ uint8_t *key_copy = NULL;
936
+ char *algorithm_copy = NULL;
937
+ int ret;
938
+
939
+ if (!input || !algorithm_out || !key_out || !key_len_out)
940
+ return PQ_ERROR_BUFFER;
941
+
942
+ *algorithm_out = NULL;
943
+ *key_out = NULL;
944
+ *key_len_out = 0;
945
+
946
+ ret = pq_serialized_key_payload(input, input_len, expected_type, &entry, &key_data, &key_len);
947
+ if (ret != PQ_SUCCESS)
948
+ return ret;
949
+
950
+ key_copy = malloc(key_len);
904
951
  if (!key_copy)
905
952
  return PQ_ERROR_NOMEM;
906
- memcpy(key_copy, input + offset, (size_t)key_len);
953
+ memcpy(key_copy, key_data, key_len);
907
954
 
908
955
  {
909
956
  size_t algorithm_len = strlen(entry->algorithm);
910
957
  algorithm_copy = malloc(algorithm_len + 1);
911
958
  if (!algorithm_copy) {
912
- pq_secure_wipe(key_copy, (size_t)key_len);
959
+ pq_secure_wipe(key_copy, key_len);
913
960
  free(key_copy);
914
961
  return PQ_ERROR_NOMEM;
915
962
  }
@@ -918,7 +965,7 @@ static int pq_decode_serialized_key(const uint8_t *input, size_t input_len, uint
918
965
 
919
966
  *algorithm_out = algorithm_copy;
920
967
  *key_out = key_copy;
921
- *key_len_out = (size_t)key_len;
968
+ *key_len_out = key_len;
922
969
  return PQ_SUCCESS;
923
970
  }
924
971
 
@@ -950,6 +997,143 @@ static const char *pq_find_pem_footer(const char *start, size_t len, const char
950
997
  return NULL;
951
998
  }
952
999
 
1000
+ static int pq_pem_body_bounds(const char *label, const char *input, size_t input_len,
1001
+ const char **body_start_out, size_t *body_len_out) {
1002
+ char header[64], footer[64];
1003
+ int header_len, footer_len;
1004
+ const char *body_start, *footer_pos, *tail;
1005
+
1006
+ if (!label || !input || !body_start_out || !body_len_out)
1007
+ return PQ_ERROR_BUFFER;
1008
+ header_len = snprintf(header, sizeof(header), "-----BEGIN %s-----", label);
1009
+ footer_len = snprintf(footer, sizeof(footer), "-----END %s-----", label);
1010
+ if (header_len <= 0 || footer_len <= 0 ||
1011
+ input_len < (size_t)header_len + (size_t)footer_len + 2 ||
1012
+ strncmp(input, header, (size_t)header_len) != 0)
1013
+ return PQ_ERROR_BUFFER;
1014
+
1015
+ body_start = input + header_len;
1016
+ while ((size_t)(body_start - input) < input_len && pq_is_pem_whitespace(*body_start))
1017
+ body_start++;
1018
+ footer_pos = pq_find_pem_footer(body_start, input_len - (size_t)(body_start - input), footer,
1019
+ (size_t)footer_len);
1020
+ if (!footer_pos)
1021
+ return PQ_ERROR_BUFFER;
1022
+
1023
+ tail = footer_pos + footer_len;
1024
+ while ((size_t)(tail - input) < input_len) {
1025
+ if (!pq_is_pem_whitespace(*tail))
1026
+ return PQ_ERROR_BUFFER;
1027
+ tail++;
1028
+ }
1029
+
1030
+ *body_len_out = (size_t)(footer_pos - body_start);
1031
+ if (*body_len_out > (size_t)INT_MAX)
1032
+ return PQ_ERROR_BUFFER;
1033
+ *body_start_out = body_start;
1034
+ return PQ_SUCCESS;
1035
+ }
1036
+
1037
+ static int pq_pem_compact_body(const char *body_start, size_t body_len, unsigned char **compact_out,
1038
+ size_t *compact_len_out) {
1039
+ unsigned char *compact;
1040
+ size_t compact_len = 0;
1041
+ int padding = 0;
1042
+ int saw_padding = 0;
1043
+
1044
+ compact = malloc(body_len ? body_len : 1);
1045
+ if (!compact)
1046
+ return PQ_ERROR_NOMEM;
1047
+
1048
+ for (size_t i = 0; i < body_len; ++i) {
1049
+ unsigned char c = (unsigned char)body_start[i];
1050
+ int value;
1051
+
1052
+ if (pq_is_pem_whitespace((char)c))
1053
+ continue;
1054
+ value = pq_base64_char_value(c);
1055
+ if (value < 0)
1056
+ goto invalid;
1057
+ if (c == '=') {
1058
+ saw_padding = 1;
1059
+ if (++padding > 2)
1060
+ goto invalid;
1061
+ } else if (saw_padding)
1062
+ goto invalid;
1063
+ compact[compact_len++] = c;
1064
+ }
1065
+
1066
+ if (compact_len == 0 || (compact_len % 4) != 0 || compact_len > (size_t)INT_MAX) {
1067
+ goto invalid;
1068
+ }
1069
+ *compact_out = compact;
1070
+ *compact_len_out = compact_len;
1071
+ return PQ_SUCCESS;
1072
+
1073
+ invalid:
1074
+ pq_secure_wipe(compact, body_len);
1075
+ free(compact);
1076
+ return PQ_ERROR_BUFFER;
1077
+ }
1078
+
1079
+ static int pq_base64_encode_der(const uint8_t *der, size_t der_len, unsigned char **encoded_out,
1080
+ size_t *encoded_len_out) {
1081
+ size_t encoded_len;
1082
+ unsigned char *encoded;
1083
+
1084
+ if (der_len > (size_t)INT_MAX)
1085
+ return PQ_ERROR_BUFFER;
1086
+ encoded_len = 4 * ((der_len + 2) / 3);
1087
+ if (encoded_len > (size_t)INT_MAX)
1088
+ return PQ_ERROR_BUFFER;
1089
+ encoded = malloc(encoded_len + 1);
1090
+ if (!encoded)
1091
+ return PQ_ERROR_NOMEM;
1092
+ if (EVP_EncodeBlock(encoded, der, (int)der_len) != (int)encoded_len) {
1093
+ pq_secure_wipe(encoded, encoded_len + 1);
1094
+ free(encoded);
1095
+ return PQ_ERROR_OPENSSL;
1096
+ }
1097
+ *encoded_out = encoded;
1098
+ *encoded_len_out = encoded_len;
1099
+ return PQ_SUCCESS;
1100
+ }
1101
+
1102
+ static int pq_pem_encoded_size(size_t header_len, size_t encoded_len, size_t line_count,
1103
+ size_t footer_len, size_t *needed_out) {
1104
+ const size_t parts[] = {header_len, 1, encoded_len, line_count, footer_len, 1};
1105
+ size_t needed = 0;
1106
+
1107
+ for (size_t i = 0; i < sizeof(parts) / sizeof(parts[0]); ++i) {
1108
+ if (pq_size_add(needed, parts[i], &needed) != PQ_SUCCESS)
1109
+ return PQ_ERROR_BUFFER;
1110
+ }
1111
+ *needed_out = needed;
1112
+ return PQ_SUCCESS;
1113
+ }
1114
+
1115
+ static size_t pq_write_pem_body(char *output, const char *header, size_t header_len,
1116
+ const unsigned char *encoded, size_t encoded_len,
1117
+ const char *footer, size_t footer_len) {
1118
+ char *cursor = output;
1119
+
1120
+ memcpy(cursor, header, header_len);
1121
+ cursor += header_len;
1122
+ *cursor++ = '\n';
1123
+ for (size_t offset = 0; offset < encoded_len; offset += 64) {
1124
+ size_t line_len = encoded_len - offset;
1125
+ if (line_len > 64)
1126
+ line_len = 64;
1127
+ memcpy(cursor, encoded + offset, line_len);
1128
+ cursor += line_len;
1129
+ *cursor++ = '\n';
1130
+ }
1131
+ memcpy(cursor, footer, footer_len);
1132
+ cursor += footer_len;
1133
+ *cursor = '\0';
1134
+ return (size_t)(cursor - output);
1135
+ }
1136
+
953
1137
  static int pq_der_to_pem(const char *label, const uint8_t *der, size_t der_len, char **output,
954
1138
  size_t *output_len) {
955
1139
  char header[64];
@@ -960,7 +1144,7 @@ static int pq_der_to_pem(const char *label, const uint8_t *der, size_t der_len,
960
1144
  size_t encoded_len;
961
1145
  size_t line_count;
962
1146
  size_t needed;
963
- char *cur;
1147
+ int ret;
964
1148
 
965
1149
  if (!label || !der || !output || !output_len)
966
1150
  return PQ_ERROR_BUFFER;
@@ -971,32 +1155,18 @@ static int pq_der_to_pem(const char *label, const uint8_t *der, size_t der_len,
971
1155
  footer_len = snprintf(footer, sizeof(footer), "-----END %s-----", label);
972
1156
  if (header_len <= 0 || footer_len <= 0)
973
1157
  return PQ_ERROR_BUFFER;
974
- if (der_len > (size_t)INT_MAX)
975
- return PQ_ERROR_BUFFER;
976
-
977
- encoded_len = 4 * ((der_len + 2) / 3);
978
- if (encoded_len > (size_t)INT_MAX)
979
- return PQ_ERROR_BUFFER;
980
-
981
- encoded = malloc(encoded_len + 1);
982
- if (!encoded)
983
- return PQ_ERROR_NOMEM;
984
-
985
- if (EVP_EncodeBlock(encoded, der, (int)der_len) != (int)encoded_len) {
986
- pq_secure_wipe(encoded, encoded_len + 1);
987
- free(encoded);
988
- return PQ_ERROR_OPENSSL;
989
- }
1158
+ ret = pq_base64_encode_der(der, der_len, &encoded, &encoded_len);
1159
+ if (ret != PQ_SUCCESS)
1160
+ return ret;
990
1161
 
991
1162
  line_count = encoded_len == 0 ? 0 : ((encoded_len + 63) / 64);
992
- if (SIZE_MAX - (size_t)header_len < 1 || SIZE_MAX - ((size_t)header_len + 1) < encoded_len ||
993
- SIZE_MAX - ((size_t)header_len + 1 + encoded_len) < line_count ||
994
- SIZE_MAX - ((size_t)header_len + 1 + encoded_len + line_count) < (size_t)footer_len + 1) {
1163
+ ret = pq_pem_encoded_size((size_t)header_len, encoded_len, line_count, (size_t)footer_len,
1164
+ &needed);
1165
+ if (ret != PQ_SUCCESS) {
995
1166
  pq_secure_wipe(encoded, encoded_len + 1);
996
1167
  free(encoded);
997
- return PQ_ERROR_BUFFER;
1168
+ return ret;
998
1169
  }
999
- needed = (size_t)header_len + 1 + encoded_len + line_count + (size_t)footer_len + 1;
1000
1170
 
1001
1171
  pem = malloc(needed);
1002
1172
  if (!pem) {
@@ -1005,26 +1175,9 @@ static int pq_der_to_pem(const char *label, const uint8_t *der, size_t der_len,
1005
1175
  return PQ_ERROR_NOMEM;
1006
1176
  }
1007
1177
 
1008
- cur = pem;
1009
- memcpy(cur, header, (size_t)header_len);
1010
- cur += header_len;
1011
- *cur++ = '\n';
1012
-
1013
- for (size_t offset = 0; offset < encoded_len; offset += 64) {
1014
- size_t line_len = encoded_len - offset;
1015
- if (line_len > 64)
1016
- line_len = 64;
1017
- memcpy(cur, encoded + offset, line_len);
1018
- cur += line_len;
1019
- *cur++ = '\n';
1020
- }
1021
-
1022
- memcpy(cur, footer, (size_t)footer_len);
1023
- cur += footer_len;
1024
- *cur = '\0';
1025
-
1026
1178
  *output = pem;
1027
- *output_len = (size_t)(cur - pem);
1179
+ *output_len = pq_write_pem_body(pem, header, (size_t)header_len, encoded, encoded_len, footer,
1180
+ (size_t)footer_len);
1028
1181
  pq_secure_wipe(encoded, encoded_len + 1);
1029
1182
  free(encoded);
1030
1183
  return PQ_SUCCESS;
@@ -1032,10 +1185,7 @@ static int pq_der_to_pem(const char *label, const uint8_t *der, size_t der_len,
1032
1185
 
1033
1186
  static int pq_pem_to_der(const char *label, const char *input, size_t input_len, uint8_t **der_out,
1034
1187
  size_t *der_len_out) {
1035
- char header[64], footer[64];
1036
- int header_len, footer_len;
1037
- const char *body_start, *footer_pos;
1038
- const char *tail;
1188
+ const char *body_start;
1039
1189
  uint8_t *der = NULL;
1040
1190
  unsigned char *compact = NULL;
1041
1191
  size_t body_len = 0;
@@ -1043,79 +1193,21 @@ static int pq_pem_to_der(const char *label, const char *input, size_t input_len,
1043
1193
  size_t der_cap = 0;
1044
1194
  int decoded_len = 0;
1045
1195
  int padding = 0;
1046
- int saw_padding = 0;
1196
+ int ret;
1047
1197
 
1048
1198
  if (!label || !input || !der_out || !der_len_out)
1049
1199
  return PQ_ERROR_BUFFER;
1050
1200
  *der_out = NULL;
1051
1201
  *der_len_out = 0;
1052
1202
 
1053
- header_len = snprintf(header, sizeof(header), "-----BEGIN %s-----", label);
1054
- footer_len = snprintf(footer, sizeof(footer), "-----END %s-----", label);
1055
- if (header_len <= 0 || footer_len <= 0)
1056
- return PQ_ERROR_BUFFER;
1057
- if (input_len < (size_t)(header_len + footer_len + 2))
1058
- return PQ_ERROR_BUFFER;
1059
- if (strncmp(input, header, (size_t)header_len) != 0)
1060
- return PQ_ERROR_BUFFER;
1061
-
1062
- body_start = input + header_len;
1063
- while ((size_t)(body_start - input) < input_len && pq_is_pem_whitespace(*body_start))
1064
- body_start++;
1065
-
1066
- footer_pos = pq_find_pem_footer(body_start, input_len - (size_t)(body_start - input), footer,
1067
- (size_t)footer_len);
1068
- if (!footer_pos)
1069
- return PQ_ERROR_BUFFER;
1070
-
1071
- tail = footer_pos + footer_len;
1072
- while ((size_t)(tail - input) < input_len) {
1073
- if (!pq_is_pem_whitespace(*tail))
1074
- return PQ_ERROR_BUFFER;
1075
- tail++;
1076
- }
1077
-
1078
- body_len = (size_t)(footer_pos - body_start);
1079
- if (body_len > (size_t)INT_MAX)
1080
- return PQ_ERROR_BUFFER;
1081
-
1082
- compact = malloc(body_len ? body_len : 1);
1083
- if (!compact)
1084
- return PQ_ERROR_NOMEM;
1085
-
1086
- for (size_t i = 0; i < body_len; ++i) {
1087
- unsigned char c = (unsigned char)body_start[i];
1088
- int value;
1089
- if (pq_is_pem_whitespace((char)c))
1090
- continue;
1091
-
1092
- value = pq_base64_char_value(c);
1093
- if (value < 0) {
1094
- pq_secure_wipe(compact, body_len);
1095
- free(compact);
1096
- return PQ_ERROR_BUFFER;
1097
- }
1098
- if (c == '=') {
1099
- saw_padding = 1;
1100
- padding++;
1101
- if (padding > 2) {
1102
- pq_secure_wipe(compact, body_len);
1103
- free(compact);
1104
- return PQ_ERROR_BUFFER;
1105
- }
1106
- } else if (saw_padding) {
1107
- pq_secure_wipe(compact, body_len);
1108
- free(compact);
1109
- return PQ_ERROR_BUFFER;
1110
- }
1111
- compact[compact_len++] = c;
1112
- }
1113
-
1114
- if (compact_len == 0 || (compact_len % 4) != 0 || compact_len > (size_t)INT_MAX) {
1115
- pq_secure_wipe(compact, body_len);
1116
- free(compact);
1117
- return PQ_ERROR_BUFFER;
1118
- }
1203
+ ret = pq_pem_body_bounds(label, input, input_len, &body_start, &body_len);
1204
+ if (ret != PQ_SUCCESS)
1205
+ return ret;
1206
+ ret = pq_pem_compact_body(body_start, body_len, &compact, &compact_len);
1207
+ if (ret != PQ_SUCCESS)
1208
+ return ret;
1209
+ for (size_t i = compact_len; i > 0 && compact[i - 1] == '='; --i)
1210
+ padding++;
1119
1211
 
1120
1212
  der_cap = (compact_len / 4) * 3;
1121
1213
  der = malloc(der_cap ? der_cap : 1);
@@ -1408,11 +1500,224 @@ cleanup:
1408
1500
  return ret;
1409
1501
  }
1410
1502
 
1503
+ static int pq_der_tlv_size(size_t value_len, size_t *tlv_len_out) {
1504
+ size_t header_len;
1505
+
1506
+ if (pq_size_add(1, pq_der_length_octets(value_len), &header_len) != PQ_SUCCESS ||
1507
+ pq_size_add(header_len, value_len, tlv_len_out) != PQ_SUCCESS)
1508
+ return PQ_ERROR_BUFFER;
1509
+ return PQ_SUCCESS;
1510
+ }
1511
+
1512
+ static int pq_der_write_tlv_header(uint8_t tag, uint8_t **cursor, size_t value_len) {
1513
+ if (!cursor || !*cursor)
1514
+ return PQ_ERROR_BUFFER;
1515
+ *(*cursor)++ = tag;
1516
+ return pq_der_write_length(cursor, value_len);
1517
+ }
1518
+
1519
+ static int pq_der_write_tlv(uint8_t **cursor, uint8_t tag, const uint8_t *value, size_t value_len) {
1520
+ int ret = pq_der_write_tlv_header(tag, cursor, value_len);
1521
+
1522
+ if (ret != PQ_SUCCESS)
1523
+ return ret;
1524
+ if (value_len > 0) {
1525
+ if (!value)
1526
+ return PQ_ERROR_BUFFER;
1527
+ memcpy(*cursor, value, value_len);
1528
+ *cursor += value_len;
1529
+ }
1530
+ return PQ_SUCCESS;
1531
+ }
1532
+
1533
+ typedef struct {
1534
+ size_t inner_len;
1535
+ size_t total_len;
1536
+ } pq_pkcs8_size_t;
1537
+
1538
+ static int pq_pkcs8_private_key_info_size(size_t oid_len, size_t private_key_len,
1539
+ pq_pkcs8_size_t *size_out) {
1540
+ size_t algorithm_len, private_len, inner_len, total_len;
1541
+
1542
+ if (pq_der_tlv_size(oid_len, &algorithm_len) != PQ_SUCCESS ||
1543
+ pq_der_tlv_size(private_key_len, &private_len) != PQ_SUCCESS ||
1544
+ pq_size_add(3, algorithm_len, &inner_len) != PQ_SUCCESS ||
1545
+ pq_size_add(inner_len, private_len, &inner_len) != PQ_SUCCESS ||
1546
+ pq_der_tlv_size(inner_len, &total_len) != PQ_SUCCESS)
1547
+ return PQ_ERROR_BUFFER;
1548
+ size_out->inner_len = inner_len;
1549
+ size_out->total_len = total_len;
1550
+ return PQ_SUCCESS;
1551
+ }
1552
+
1553
+ typedef struct {
1554
+ size_t oid_offset;
1555
+ size_t oid_tlv_len;
1556
+ size_t private_key_offset;
1557
+ size_t private_key_len;
1558
+ size_t outer_end;
1559
+ size_t content_offset;
1560
+ } pq_pkcs8_parts_t;
1561
+
1562
+ static int pq_pkcs8_parse_outer(const uint8_t *input, size_t input_len, pq_pkcs8_parts_t *parts) {
1563
+ size_t offset = 0, outer_offset = 0, outer_len = 0;
1564
+ size_t version_offset = 0, version_len = 0;
1565
+ int ret;
1566
+
1567
+ ret = pq_der_expect_tlv(input, input_len, &offset, 0x30, &outer_offset, &outer_len);
1568
+ if (ret != PQ_SUCCESS)
1569
+ return ret;
1570
+ if (offset != input_len ||
1571
+ pq_size_add(outer_offset, outer_len, &parts->outer_end) != PQ_SUCCESS ||
1572
+ parts->outer_end != input_len)
1573
+ return PQ_ERROR_BUFFER;
1574
+ offset = outer_offset;
1575
+ ret = pq_der_expect_tlv(input, parts->outer_end, &offset, 0x02, &version_offset, &version_len);
1576
+ if (ret != PQ_SUCCESS)
1577
+ return ret;
1578
+ if (version_len != 1 || input[version_offset] != 0)
1579
+ return PQ_ERROR_BUFFER;
1580
+ parts->content_offset = offset;
1581
+ return PQ_SUCCESS;
1582
+ }
1583
+
1584
+ static int pq_pkcs8_parse_algorithm(const uint8_t *input, size_t outer_end, size_t *offset,
1585
+ pq_pkcs8_parts_t *parts) {
1586
+ size_t alg_offset = 0, alg_len = 0, alg_end;
1587
+ size_t alg_cursor, oid_offset = 0, oid_len = 0;
1588
+ int ret;
1589
+
1590
+ ret = pq_der_expect_tlv(input, outer_end, offset, 0x30, &alg_offset, &alg_len);
1591
+ if (ret != PQ_SUCCESS || pq_size_add(alg_offset, alg_len, &alg_end) != PQ_SUCCESS)
1592
+ return PQ_ERROR_BUFFER;
1593
+ alg_cursor = alg_offset;
1594
+ parts->oid_offset = alg_cursor;
1595
+ ret = pq_der_expect_tlv(input, alg_end, &alg_cursor, 0x06, &oid_offset, &oid_len);
1596
+ if (ret != PQ_SUCCESS || alg_cursor != alg_end)
1597
+ return PQ_ERROR_BUFFER;
1598
+ parts->oid_tlv_len = alg_cursor - parts->oid_offset;
1599
+ return PQ_SUCCESS;
1600
+ }
1601
+
1602
+ static int pq_pkcs8_parse_parts(const uint8_t *input, size_t input_len, pq_pkcs8_parts_t *parts) {
1603
+ size_t offset;
1604
+ int ret = pq_pkcs8_parse_outer(input, input_len, parts);
1605
+
1606
+ if (ret != PQ_SUCCESS)
1607
+ return ret;
1608
+ offset = parts->content_offset;
1609
+ ret = pq_pkcs8_parse_algorithm(input, parts->outer_end, &offset, parts);
1610
+ if (ret != PQ_SUCCESS)
1611
+ return ret;
1612
+ ret = pq_der_expect_tlv(input, parts->outer_end, &offset, 0x04, &parts->private_key_offset,
1613
+ &parts->private_key_len);
1614
+ if (ret != PQ_SUCCESS || offset != parts->outer_end)
1615
+ return PQ_ERROR_BUFFER;
1616
+ return PQ_SUCCESS;
1617
+ }
1618
+
1619
+ static int pq_x509_sig_to_der(X509_SIG *encrypted, unsigned char **der_out, size_t *der_len_out) {
1620
+ unsigned char *der;
1621
+ unsigned char *cursor;
1622
+ int der_len = i2d_X509_SIG(encrypted, NULL);
1623
+
1624
+ if (der_len <= 0)
1625
+ return PQ_ERROR_OPENSSL;
1626
+ der = malloc((size_t)der_len);
1627
+ if (!der)
1628
+ return PQ_ERROR_NOMEM;
1629
+ cursor = der;
1630
+ if (i2d_X509_SIG(encrypted, &cursor) != der_len || (size_t)(cursor - der) != (size_t)der_len) {
1631
+ pq_secure_wipe(der, (size_t)der_len);
1632
+ free(der);
1633
+ return PQ_ERROR_OPENSSL;
1634
+ }
1635
+ *der_out = der;
1636
+ *der_len_out = (size_t)der_len;
1637
+ return PQ_SUCCESS;
1638
+ }
1639
+
1640
+ static int pq_pkcs8_info_to_der(PKCS8_PRIV_KEY_INFO *p8, unsigned char **der_out,
1641
+ size_t *der_len_out) {
1642
+ unsigned char *der;
1643
+ unsigned char *cursor;
1644
+ int der_len = i2d_PKCS8_PRIV_KEY_INFO(p8, NULL);
1645
+
1646
+ if (der_len <= 0)
1647
+ return PQ_ERROR_OPENSSL;
1648
+ der = malloc((size_t)der_len);
1649
+ if (!der)
1650
+ return PQ_ERROR_NOMEM;
1651
+ cursor = der;
1652
+ if (i2d_PKCS8_PRIV_KEY_INFO(p8, &cursor) != der_len ||
1653
+ (size_t)(cursor - der) != (size_t)der_len) {
1654
+ pq_secure_wipe(der, (size_t)der_len);
1655
+ free(der);
1656
+ return PQ_ERROR_OPENSSL;
1657
+ }
1658
+ *der_out = der;
1659
+ *der_len_out = (size_t)der_len;
1660
+ return PQ_SUCCESS;
1661
+ }
1662
+
1663
+ static int pq_pkcs8_encrypt(const uint8_t *plain_der, size_t plain_der_len, const char *passphrase,
1664
+ size_t passphrase_len, int iterations, X509_SIG **encrypted_out) {
1665
+ const unsigned char *cursor = plain_der;
1666
+ PKCS8_PRIV_KEY_INFO *p8 = NULL;
1667
+ X509_SIG *encrypted = NULL;
1668
+ unsigned char salt[16];
1669
+ int ret = PQ_ERROR_OPENSSL;
1670
+
1671
+ p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &cursor, (long)plain_der_len);
1672
+ if (!p8 || cursor != plain_der + plain_der_len || RAND_bytes(salt, sizeof(salt)) != 1)
1673
+ goto cleanup;
1674
+ encrypted = PKCS8_encrypt(-1, EVP_aes_256_cbc(), passphrase, (int)passphrase_len, salt,
1675
+ (int)sizeof(salt), iterations, p8);
1676
+ if (!encrypted)
1677
+ goto cleanup;
1678
+ *encrypted_out = encrypted;
1679
+ encrypted = NULL;
1680
+ ret = PQ_SUCCESS;
1681
+
1682
+ cleanup:
1683
+ pq_secure_wipe(salt, sizeof(salt));
1684
+ if (encrypted)
1685
+ X509_SIG_free(encrypted);
1686
+ if (p8)
1687
+ PKCS8_PRIV_KEY_INFO_free(p8);
1688
+ return ret;
1689
+ }
1690
+
1691
+ static int pq_pkcs8_decrypt(const uint8_t *encrypted_der, size_t encrypted_der_len,
1692
+ const char *passphrase, size_t passphrase_len,
1693
+ PKCS8_PRIV_KEY_INFO **p8_out) {
1694
+ const unsigned char *cursor = encrypted_der;
1695
+ X509_SIG *encrypted = d2i_X509_SIG(NULL, &cursor, (long)encrypted_der_len);
1696
+ PKCS8_PRIV_KEY_INFO *p8 = NULL;
1697
+ int ret = PQ_ERROR_OPENSSL;
1698
+
1699
+ if (!encrypted || cursor != encrypted_der + encrypted_der_len)
1700
+ goto cleanup;
1701
+ p8 = PKCS8_decrypt(encrypted, passphrase, (int)passphrase_len);
1702
+ if (!p8)
1703
+ goto cleanup;
1704
+ *p8_out = p8;
1705
+ p8 = NULL;
1706
+ ret = PQ_SUCCESS;
1707
+
1708
+ cleanup:
1709
+ if (p8)
1710
+ PKCS8_PRIV_KEY_INFO_free(p8);
1711
+ if (encrypted)
1712
+ X509_SIG_free(encrypted);
1713
+ return ret;
1714
+ }
1715
+
1411
1716
  int pq_pkcs8_private_key_info_to_der(uint8_t **output, size_t *output_len, const char *oid_text,
1412
1717
  const uint8_t *private_key, size_t private_key_len) {
1413
1718
  uint8_t *oid_der = NULL;
1414
1719
  size_t oid_der_len = 0;
1415
- size_t alg_body_len, alg_len, priv_len, inner_len, total_len;
1720
+ pq_pkcs8_size_t der_size = {0};
1416
1721
  uint8_t *buf = NULL;
1417
1722
  uint8_t *cur;
1418
1723
  int ret;
@@ -1426,58 +1731,42 @@ int pq_pkcs8_private_key_info_to_der(uint8_t **output, size_t *output_len, const
1426
1731
  if (ret != PQ_SUCCESS)
1427
1732
  return ret;
1428
1733
 
1429
- alg_body_len = oid_der_len;
1430
- alg_len = 1 + pq_der_length_octets(alg_body_len) + alg_body_len;
1431
- priv_len = 1 + pq_der_length_octets(private_key_len) + private_key_len;
1432
- if (pq_size_add(3, alg_len, &inner_len) != PQ_SUCCESS ||
1433
- pq_size_add(inner_len, priv_len, &inner_len) != PQ_SUCCESS) {
1434
- ret = PQ_ERROR_BUFFER;
1435
- goto cleanup;
1436
- }
1437
- if (pq_size_add(1 + pq_der_length_octets(inner_len), inner_len, &total_len) != PQ_SUCCESS) {
1438
- ret = PQ_ERROR_BUFFER;
1734
+ ret = pq_pkcs8_private_key_info_size(oid_der_len, private_key_len, &der_size);
1735
+ if (ret != PQ_SUCCESS)
1439
1736
  goto cleanup;
1440
- }
1441
1737
 
1442
- buf = malloc(total_len);
1738
+ buf = malloc(der_size.total_len);
1443
1739
  if (!buf) {
1444
1740
  ret = PQ_ERROR_NOMEM;
1445
1741
  goto cleanup;
1446
1742
  }
1447
1743
 
1448
1744
  cur = buf;
1449
- *cur++ = 0x30;
1450
- ret = pq_der_write_length(&cur, inner_len);
1745
+ ret = pq_der_write_tlv_header(0x30, &cur, der_size.inner_len);
1451
1746
  if (ret != PQ_SUCCESS)
1452
1747
  goto cleanup;
1453
1748
  *cur++ = 0x02;
1454
1749
  *cur++ = 0x01;
1455
1750
  *cur++ = 0x00;
1456
- *cur++ = 0x30;
1457
- ret = pq_der_write_length(&cur, alg_body_len);
1751
+ ret = pq_der_write_tlv(&cur, 0x30, oid_der, oid_der_len);
1458
1752
  if (ret != PQ_SUCCESS)
1459
1753
  goto cleanup;
1460
- memcpy(cur, oid_der, oid_der_len);
1461
- cur += oid_der_len;
1462
- *cur++ = 0x04;
1463
- ret = pq_der_write_length(&cur, private_key_len);
1754
+ ret = pq_der_write_tlv(&cur, 0x04, private_key, private_key_len);
1464
1755
  if (ret != PQ_SUCCESS)
1465
1756
  goto cleanup;
1466
- memcpy(cur, private_key, private_key_len);
1467
- cur += private_key_len;
1468
- if ((size_t)(cur - buf) != total_len) {
1757
+ if ((size_t)(cur - buf) != der_size.total_len) {
1469
1758
  ret = PQ_ERROR_BUFFER;
1470
1759
  goto cleanup;
1471
1760
  }
1472
1761
 
1473
1762
  *output = buf;
1474
- *output_len = total_len;
1763
+ *output_len = der_size.total_len;
1475
1764
  buf = NULL;
1476
1765
  ret = PQ_SUCCESS;
1477
1766
 
1478
1767
  cleanup:
1479
1768
  if (buf) {
1480
- pq_secure_wipe(buf, total_len);
1769
+ pq_secure_wipe(buf, der_size.total_len);
1481
1770
  free(buf);
1482
1771
  }
1483
1772
  if (oid_der) {
@@ -1490,11 +1779,7 @@ cleanup:
1490
1779
  int pq_pkcs8_private_key_info_from_der(char **oid_text_out, uint8_t **private_key_out,
1491
1780
  size_t *private_key_len_out, const uint8_t *input,
1492
1781
  size_t input_len) {
1493
- size_t offset = 0;
1494
- size_t outer_off = 0, outer_len = 0, outer_end;
1495
- size_t alg_off = 0, alg_len = 0, alg_end;
1496
- size_t oid_off = 0, oid_len = 0;
1497
- size_t priv_off = 0, priv_len = 0;
1782
+ pq_pkcs8_parts_t parts = {0};
1498
1783
  uint8_t *private_key = NULL;
1499
1784
  char *oid_text = NULL;
1500
1785
  int ret;
@@ -1505,58 +1790,23 @@ int pq_pkcs8_private_key_info_from_der(char **oid_text_out, uint8_t **private_ke
1505
1790
  *private_key_out = NULL;
1506
1791
  *private_key_len_out = 0;
1507
1792
 
1508
- ret = pq_der_expect_tlv(input, input_len, &offset, 0x30, &outer_off, &outer_len);
1793
+ ret = pq_pkcs8_parse_parts(input, input_len, &parts);
1509
1794
  if (ret != PQ_SUCCESS)
1510
1795
  return ret;
1511
- outer_end = outer_off + outer_len;
1512
- if (offset != input_len || outer_end != input_len)
1513
- return PQ_ERROR_BUFFER;
1514
-
1515
- offset = outer_off;
1516
- {
1517
- size_t version_off = 0, version_len = 0;
1518
- ret = pq_der_expect_tlv(input, outer_end, &offset, 0x02, &version_off, &version_len);
1519
- if (ret != PQ_SUCCESS)
1520
- return ret;
1521
- if (version_len != 1 || input[version_off] != 0x00)
1522
- return PQ_ERROR_BUFFER;
1523
- }
1524
-
1525
- ret = pq_der_expect_tlv(input, outer_end, &offset, 0x30, &alg_off, &alg_len);
1796
+ ret = pq_oid_der_to_text(input + parts.oid_offset, parts.oid_tlv_len, &oid_text);
1526
1797
  if (ret != PQ_SUCCESS)
1527
1798
  return ret;
1528
- alg_end = alg_off + alg_len;
1529
- {
1530
- size_t alg_cursor = alg_off;
1531
- size_t oid_tlv_start = alg_cursor;
1532
- ret = pq_der_expect_tlv(input, alg_end, &alg_cursor, 0x06, &oid_off, &oid_len);
1533
- if (ret != PQ_SUCCESS)
1534
- return ret;
1535
- if (alg_cursor != alg_end)
1536
- return PQ_ERROR_BUFFER;
1537
- ret = pq_oid_der_to_text(input + oid_tlv_start, alg_cursor - oid_tlv_start, &oid_text);
1538
- }
1539
- if (ret != PQ_SUCCESS)
1540
- return ret;
1541
-
1542
- ret = pq_der_expect_tlv(input, outer_end, &offset, 0x04, &priv_off, &priv_len);
1543
- if (ret != PQ_SUCCESS)
1544
- goto cleanup;
1545
- if (offset != outer_end) {
1546
- ret = PQ_ERROR_BUFFER;
1547
- goto cleanup;
1548
- }
1549
- private_key = malloc(priv_len ? priv_len : 1);
1799
+ private_key = malloc(parts.private_key_len ? parts.private_key_len : 1);
1550
1800
  if (!private_key) {
1551
1801
  ret = PQ_ERROR_NOMEM;
1552
1802
  goto cleanup;
1553
1803
  }
1554
- if (priv_len)
1555
- memcpy(private_key, input + priv_off, priv_len);
1804
+ if (parts.private_key_len)
1805
+ memcpy(private_key, input + parts.private_key_offset, parts.private_key_len);
1556
1806
 
1557
1807
  *oid_text_out = oid_text;
1558
1808
  *private_key_out = private_key;
1559
- *private_key_len_out = priv_len;
1809
+ *private_key_len_out = parts.private_key_len;
1560
1810
  oid_text = NULL;
1561
1811
  private_key = NULL;
1562
1812
  ret = PQ_SUCCESS;
@@ -1565,7 +1815,7 @@ cleanup:
1565
1815
  if (oid_text)
1566
1816
  free(oid_text);
1567
1817
  if (private_key) {
1568
- pq_secure_wipe(private_key, priv_len);
1818
+ pq_secure_wipe(private_key, parts.private_key_len);
1569
1819
  free(private_key);
1570
1820
  }
1571
1821
  return ret;
@@ -1575,14 +1825,10 @@ int pq_pkcs8_encrypt_private_key_info_der(uint8_t **output, size_t *output_len,
1575
1825
  const uint8_t *plain_der, size_t plain_der_len,
1576
1826
  const char *passphrase, size_t passphrase_len,
1577
1827
  int iterations) {
1578
- const unsigned char *cursor;
1579
- PKCS8_PRIV_KEY_INFO *p8 = NULL;
1580
1828
  X509_SIG *encrypted = NULL;
1581
- unsigned char salt[16];
1582
1829
  unsigned char *der = NULL;
1583
- unsigned char *der_cursor;
1584
- int der_len;
1585
- int ret = PQ_ERROR_OPENSSL;
1830
+ size_t der_len = 0;
1831
+ int ret;
1586
1832
 
1587
1833
  if (!output || !output_len || !plain_der || !passphrase || iterations <= 0 ||
1588
1834
  passphrase_len > (size_t)INT_MAX || plain_der_len > (size_t)LONG_MAX)
@@ -1590,61 +1836,36 @@ int pq_pkcs8_encrypt_private_key_info_der(uint8_t **output, size_t *output_len,
1590
1836
  *output = NULL;
1591
1837
  *output_len = 0;
1592
1838
 
1593
- cursor = plain_der;
1594
- p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &cursor, (long)plain_der_len);
1595
- if (!p8 || cursor != plain_der + plain_der_len)
1596
- goto cleanup;
1597
- if (RAND_bytes(salt, sizeof(salt)) != 1)
1598
- goto cleanup;
1599
-
1600
- encrypted = PKCS8_encrypt(-1, EVP_aes_256_cbc(), passphrase, (int)passphrase_len, salt,
1601
- (int)sizeof(salt), iterations, p8);
1602
- if (!encrypted)
1603
- goto cleanup;
1604
-
1605
- der_len = i2d_X509_SIG(encrypted, NULL);
1606
- if (der_len <= 0) {
1607
- ret = PQ_ERROR_OPENSSL;
1608
- goto cleanup;
1609
- }
1610
- der = malloc((size_t)der_len);
1611
- if (!der) {
1612
- ret = PQ_ERROR_NOMEM;
1839
+ ret = pq_pkcs8_encrypt(plain_der, plain_der_len, passphrase, passphrase_len, iterations,
1840
+ &encrypted);
1841
+ if (ret != PQ_SUCCESS)
1613
1842
  goto cleanup;
1614
- }
1615
- der_cursor = der;
1616
- if (i2d_X509_SIG(encrypted, &der_cursor) != der_len ||
1617
- (size_t)(der_cursor - der) != (size_t)der_len)
1843
+ ret = pq_x509_sig_to_der(encrypted, &der, &der_len);
1844
+ if (ret != PQ_SUCCESS)
1618
1845
  goto cleanup;
1619
1846
 
1620
1847
  *output = der;
1621
- *output_len = (size_t)der_len;
1848
+ *output_len = der_len;
1622
1849
  der = NULL;
1623
1850
  ret = PQ_SUCCESS;
1624
1851
 
1625
1852
  cleanup:
1626
- pq_secure_wipe(salt, sizeof(salt));
1627
1853
  if (der) {
1628
- pq_secure_wipe(der, (size_t)(der_len > 0 ? der_len : 0));
1854
+ pq_secure_wipe(der, der_len);
1629
1855
  free(der);
1630
1856
  }
1631
1857
  if (encrypted)
1632
1858
  X509_SIG_free(encrypted);
1633
- if (p8)
1634
- PKCS8_PRIV_KEY_INFO_free(p8);
1635
1859
  return ret;
1636
1860
  }
1637
1861
 
1638
1862
  int pq_pkcs8_decrypt_private_key_info_der(uint8_t **output, size_t *output_len,
1639
1863
  const uint8_t *encrypted_der, size_t encrypted_der_len,
1640
1864
  const char *passphrase, size_t passphrase_len) {
1641
- const unsigned char *cursor;
1642
- X509_SIG *encrypted = NULL;
1643
1865
  PKCS8_PRIV_KEY_INFO *p8 = NULL;
1644
1866
  unsigned char *der = NULL;
1645
- unsigned char *der_cursor;
1646
- int der_len;
1647
- int ret = PQ_ERROR_OPENSSL;
1867
+ size_t der_len = 0;
1868
+ int ret;
1648
1869
 
1649
1870
  if (!output || !output_len || !encrypted_der || !passphrase ||
1650
1871
  passphrase_len > (size_t)INT_MAX || encrypted_der_len > (size_t)LONG_MAX)
@@ -1652,41 +1873,25 @@ int pq_pkcs8_decrypt_private_key_info_der(uint8_t **output, size_t *output_len,
1652
1873
  *output = NULL;
1653
1874
  *output_len = 0;
1654
1875
 
1655
- cursor = encrypted_der;
1656
- encrypted = d2i_X509_SIG(NULL, &cursor, (long)encrypted_der_len);
1657
- if (!encrypted || cursor != encrypted_der + encrypted_der_len)
1658
- goto cleanup;
1659
- p8 = PKCS8_decrypt(encrypted, passphrase, (int)passphrase_len);
1660
- if (!p8)
1661
- goto cleanup;
1662
-
1663
- der_len = i2d_PKCS8_PRIV_KEY_INFO(p8, NULL);
1664
- if (der_len <= 0)
1665
- goto cleanup;
1666
- der = malloc((size_t)der_len);
1667
- if (!der) {
1668
- ret = PQ_ERROR_NOMEM;
1876
+ ret = pq_pkcs8_decrypt(encrypted_der, encrypted_der_len, passphrase, passphrase_len, &p8);
1877
+ if (ret != PQ_SUCCESS)
1669
1878
  goto cleanup;
1670
- }
1671
- der_cursor = der;
1672
- if (i2d_PKCS8_PRIV_KEY_INFO(p8, &der_cursor) != der_len ||
1673
- (size_t)(der_cursor - der) != (size_t)der_len)
1879
+ ret = pq_pkcs8_info_to_der(p8, &der, &der_len);
1880
+ if (ret != PQ_SUCCESS)
1674
1881
  goto cleanup;
1675
1882
 
1676
1883
  *output = der;
1677
- *output_len = (size_t)der_len;
1884
+ *output_len = der_len;
1678
1885
  der = NULL;
1679
1886
  ret = PQ_SUCCESS;
1680
1887
 
1681
1888
  cleanup:
1682
1889
  if (der) {
1683
- pq_secure_wipe(der, (size_t)(der_len > 0 ? der_len : 0));
1890
+ pq_secure_wipe(der, der_len);
1684
1891
  free(der);
1685
1892
  }
1686
1893
  if (p8)
1687
1894
  PKCS8_PRIV_KEY_INFO_free(p8);
1688
- if (encrypted)
1689
- X509_SIG_free(encrypted);
1690
1895
  return ret;
1691
1896
  }
1692
1897