ecc.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /**
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. * SPDX-License-Identifier: Apache-2.0.
  4. */
  5. #include <aws/cal/private/ecc.h>
  6. #include <aws/cal/cal.h>
  7. #include <aws/cal/private/der.h>
  8. #include <aws/common/encoding.h>
  9. #define STATIC_INIT_BYTE_CURSOR(a, name) \
  10. static struct aws_byte_cursor s_##name = { \
  11. .ptr = (a), \
  12. .len = sizeof(a), \
  13. };
  14. static uint8_t s_p256_oid[] = {
  15. 0x2A,
  16. 0x86,
  17. 0x48,
  18. 0xCE,
  19. 0x3D,
  20. 0x03,
  21. 0x01,
  22. 0x07,
  23. };
  24. STATIC_INIT_BYTE_CURSOR(s_p256_oid, ecc_p256_oid)
  25. static uint8_t s_p384_oid[] = {
  26. 0x2B,
  27. 0x81,
  28. 0x04,
  29. 0x00,
  30. 0x22,
  31. };
  32. STATIC_INIT_BYTE_CURSOR(s_p384_oid, ecc_p384_oid)
  33. static struct aws_byte_cursor *s_ecc_curve_oids[] = {
  34. [AWS_CAL_ECDSA_P256] = &s_ecc_p256_oid,
  35. [AWS_CAL_ECDSA_P384] = &s_ecc_p384_oid,
  36. };
  37. int aws_ecc_curve_name_from_oid(struct aws_byte_cursor *oid, enum aws_ecc_curve_name *curve_name) {
  38. if (aws_byte_cursor_eq(oid, &s_ecc_p256_oid)) {
  39. *curve_name = AWS_CAL_ECDSA_P256;
  40. return AWS_OP_SUCCESS;
  41. }
  42. if (aws_byte_cursor_eq(oid, &s_ecc_p384_oid)) {
  43. *curve_name = AWS_CAL_ECDSA_P384;
  44. return AWS_OP_SUCCESS;
  45. }
  46. return aws_raise_error(AWS_ERROR_CAL_UNKNOWN_OBJECT_IDENTIFIER);
  47. }
  48. int aws_ecc_oid_from_curve_name(enum aws_ecc_curve_name curve_name, struct aws_byte_cursor *oid) {
  49. if (curve_name < AWS_CAL_ECDSA_P256 || curve_name > AWS_CAL_ECDSA_P384) {
  50. return aws_raise_error(AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM);
  51. }
  52. *oid = *s_ecc_curve_oids[curve_name];
  53. return AWS_OP_SUCCESS;
  54. }
  55. typedef struct aws_ecc_key_pair *(aws_ecc_key_pair_new_from_public_key_fn)(
  56. struct aws_allocator *allocator,
  57. enum aws_ecc_curve_name curve_name,
  58. const struct aws_byte_cursor *public_key_x,
  59. const struct aws_byte_cursor *public_key_y);
  60. typedef struct aws_ecc_key_pair *(aws_ecc_key_pair_new_from_private_key_fn)(
  61. struct aws_allocator *allocator,
  62. enum aws_ecc_curve_name curve_name,
  63. const struct aws_byte_cursor *priv_key);
  64. #ifndef BYO_CRYPTO
  65. extern struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_public_key_impl(
  66. struct aws_allocator *allocator,
  67. enum aws_ecc_curve_name curve_name,
  68. const struct aws_byte_cursor *public_key_x,
  69. const struct aws_byte_cursor *public_key_y);
  70. extern struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_private_key_impl(
  71. struct aws_allocator *allocator,
  72. enum aws_ecc_curve_name curve_name,
  73. const struct aws_byte_cursor *priv_key);
  74. #else /* BYO_CRYPTO */
  75. struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_public_key_impl(
  76. struct aws_allocator *allocator,
  77. enum aws_ecc_curve_name curve_name,
  78. const struct aws_byte_cursor *public_key_x,
  79. const struct aws_byte_cursor *public_key_y) {
  80. (void)allocator;
  81. (void)curve_name;
  82. (void)public_key_x;
  83. (void)public_key_y;
  84. abort();
  85. }
  86. struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_private_key_impl(
  87. struct aws_allocator *allocator,
  88. enum aws_ecc_curve_name curve_name,
  89. const struct aws_byte_cursor *priv_key) {
  90. (void)allocator;
  91. (void)curve_name;
  92. (void)priv_key;
  93. abort();
  94. }
  95. #endif /* BYO_CRYPTO */
  96. static aws_ecc_key_pair_new_from_public_key_fn *s_ecc_key_pair_new_from_public_key_fn =
  97. aws_ecc_key_pair_new_from_public_key_impl;
  98. static aws_ecc_key_pair_new_from_private_key_fn *s_ecc_key_pair_new_from_private_key_fn =
  99. aws_ecc_key_pair_new_from_private_key_impl;
  100. struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_public_key(
  101. struct aws_allocator *allocator,
  102. enum aws_ecc_curve_name curve_name,
  103. const struct aws_byte_cursor *public_key_x,
  104. const struct aws_byte_cursor *public_key_y) {
  105. return s_ecc_key_pair_new_from_public_key_fn(allocator, curve_name, public_key_x, public_key_y);
  106. }
  107. struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_private_key(
  108. struct aws_allocator *allocator,
  109. enum aws_ecc_curve_name curve_name,
  110. const struct aws_byte_cursor *priv_key) {
  111. return s_ecc_key_pair_new_from_private_key_fn(allocator, curve_name, priv_key);
  112. }
  113. static void s_aws_ecc_key_pair_destroy(struct aws_ecc_key_pair *key_pair) {
  114. if (key_pair) {
  115. AWS_FATAL_ASSERT(key_pair->vtable->destroy && "ECC KEY PAIR destroy function must be included on the vtable");
  116. key_pair->vtable->destroy(key_pair);
  117. }
  118. }
  119. int aws_ecc_key_pair_derive_public_key(struct aws_ecc_key_pair *key_pair) {
  120. AWS_FATAL_ASSERT(key_pair->vtable->derive_pub_key && "ECC KEY PAIR derive function must be included on the vtable");
  121. return key_pair->vtable->derive_pub_key(key_pair);
  122. }
  123. int aws_ecc_key_pair_sign_message(
  124. const struct aws_ecc_key_pair *key_pair,
  125. const struct aws_byte_cursor *message,
  126. struct aws_byte_buf *signature) {
  127. AWS_FATAL_ASSERT(key_pair->vtable->sign_message && "ECC KEY PAIR sign message must be included on the vtable");
  128. return key_pair->vtable->sign_message(key_pair, message, signature);
  129. }
  130. int aws_ecc_key_pair_verify_signature(
  131. const struct aws_ecc_key_pair *key_pair,
  132. const struct aws_byte_cursor *message,
  133. const struct aws_byte_cursor *signature) {
  134. AWS_FATAL_ASSERT(
  135. key_pair->vtable->verify_signature && "ECC KEY PAIR verify signature must be included on the vtable");
  136. return key_pair->vtable->verify_signature(key_pair, message, signature);
  137. }
  138. size_t aws_ecc_key_pair_signature_length(const struct aws_ecc_key_pair *key_pair) {
  139. AWS_FATAL_ASSERT(
  140. key_pair->vtable->signature_length && "ECC KEY PAIR signature length must be included on the vtable");
  141. return key_pair->vtable->signature_length(key_pair);
  142. }
  143. void aws_ecc_key_pair_get_public_key(
  144. const struct aws_ecc_key_pair *key_pair,
  145. struct aws_byte_cursor *pub_x,
  146. struct aws_byte_cursor *pub_y) {
  147. *pub_x = aws_byte_cursor_from_buf(&key_pair->pub_x);
  148. *pub_y = aws_byte_cursor_from_buf(&key_pair->pub_y);
  149. }
  150. void aws_ecc_key_pair_get_private_key(const struct aws_ecc_key_pair *key_pair, struct aws_byte_cursor *private_d) {
  151. *private_d = aws_byte_cursor_from_buf(&key_pair->priv_d);
  152. }
  153. size_t aws_ecc_key_coordinate_byte_size_from_curve_name(enum aws_ecc_curve_name curve_name) {
  154. switch (curve_name) {
  155. case AWS_CAL_ECDSA_P256:
  156. return 32;
  157. case AWS_CAL_ECDSA_P384:
  158. return 48;
  159. default:
  160. return 0;
  161. }
  162. }
  163. int aws_der_decoder_load_ecc_key_pair(
  164. struct aws_der_decoder *decoder,
  165. struct aws_byte_cursor *out_public_x_coor,
  166. struct aws_byte_cursor *out_public_y_coor,
  167. struct aws_byte_cursor *out_private_d,
  168. enum aws_ecc_curve_name *out_curve_name) {
  169. AWS_ZERO_STRUCT(*out_public_x_coor);
  170. AWS_ZERO_STRUCT(*out_public_y_coor);
  171. AWS_ZERO_STRUCT(*out_private_d);
  172. /* we could have private key or a public key, or a full pair. */
  173. struct aws_byte_cursor pair_part_1;
  174. AWS_ZERO_STRUCT(pair_part_1);
  175. struct aws_byte_cursor pair_part_2;
  176. AWS_ZERO_STRUCT(pair_part_2);
  177. bool curve_name_recognized = false;
  178. /* work with this pointer and move it to the next after using it. We need
  179. * to know which curve we're dealing with before we can figure out which is which. */
  180. struct aws_byte_cursor *current_part = &pair_part_1;
  181. while (aws_der_decoder_next(decoder)) {
  182. enum aws_der_type type = aws_der_decoder_tlv_type(decoder);
  183. if (type == AWS_DER_OBJECT_IDENTIFIER) {
  184. struct aws_byte_cursor oid;
  185. AWS_ZERO_STRUCT(oid);
  186. aws_der_decoder_tlv_blob(decoder, &oid);
  187. /* There can be other OID's so just look for one that is the curve. */
  188. if (!aws_ecc_curve_name_from_oid(&oid, out_curve_name)) {
  189. curve_name_recognized = true;
  190. }
  191. continue;
  192. }
  193. /* you'd think we'd get some type hints on which key this is, but it's not consistent
  194. * as far as I can tell. */
  195. if (type == AWS_DER_BIT_STRING || type == AWS_DER_OCTET_STRING) {
  196. aws_der_decoder_tlv_string(decoder, current_part);
  197. current_part = &pair_part_2;
  198. }
  199. }
  200. if (!curve_name_recognized) {
  201. return aws_raise_error(AWS_ERROR_CAL_UNKNOWN_OBJECT_IDENTIFIER);
  202. }
  203. size_t key_coordinate_size = aws_ecc_key_coordinate_byte_size_from_curve_name(*out_curve_name);
  204. struct aws_byte_cursor *private_key = NULL;
  205. struct aws_byte_cursor *public_key = NULL;
  206. size_t public_key_blob_size = key_coordinate_size * 2 + 1;
  207. if (pair_part_1.ptr && pair_part_1.len) {
  208. if (pair_part_1.len == key_coordinate_size) {
  209. private_key = &pair_part_1;
  210. } else if (pair_part_1.len == public_key_blob_size) {
  211. public_key = &pair_part_1;
  212. }
  213. }
  214. if (pair_part_2.ptr && pair_part_2.len) {
  215. if (pair_part_2.len == key_coordinate_size) {
  216. private_key = &pair_part_2;
  217. } else if (pair_part_2.len == public_key_blob_size) {
  218. public_key = &pair_part_2;
  219. }
  220. }
  221. if (!private_key && !public_key) {
  222. return aws_raise_error(AWS_ERROR_CAL_MISSING_REQUIRED_KEY_COMPONENT);
  223. }
  224. if (private_key) {
  225. *out_private_d = *private_key;
  226. }
  227. if (public_key) {
  228. aws_byte_cursor_advance(public_key, 1);
  229. *out_public_x_coor = *public_key;
  230. out_public_x_coor->len = key_coordinate_size;
  231. out_public_y_coor->ptr = public_key->ptr + key_coordinate_size;
  232. out_public_y_coor->len = key_coordinate_size;
  233. }
  234. return AWS_OP_SUCCESS;
  235. }
  236. void aws_ecc_key_pair_acquire(struct aws_ecc_key_pair *key_pair) {
  237. aws_atomic_fetch_add(&key_pair->ref_count, 1);
  238. }
  239. void aws_ecc_key_pair_release(struct aws_ecc_key_pair *key_pair) {
  240. if (key_pair == NULL) {
  241. return;
  242. }
  243. size_t old_value = aws_atomic_fetch_sub(&key_pair->ref_count, 1);
  244. if (old_value == 1) {
  245. s_aws_ecc_key_pair_destroy(key_pair);
  246. }
  247. }
  248. struct aws_ecc_key_pair *aws_ecc_key_new_from_hex_coordinates(
  249. struct aws_allocator *allocator,
  250. enum aws_ecc_curve_name curve_name,
  251. struct aws_byte_cursor pub_x_hex_cursor,
  252. struct aws_byte_cursor pub_y_hex_cursor) {
  253. struct aws_byte_buf pub_x_buffer;
  254. AWS_ZERO_STRUCT(pub_x_buffer);
  255. struct aws_byte_buf pub_y_buffer;
  256. AWS_ZERO_STRUCT(pub_y_buffer);
  257. struct aws_ecc_key_pair *key = NULL;
  258. size_t pub_x_length = 0;
  259. size_t pub_y_length = 0;
  260. if (aws_hex_compute_decoded_len(pub_x_hex_cursor.len, &pub_x_length) ||
  261. aws_hex_compute_decoded_len(pub_y_hex_cursor.len, &pub_y_length)) {
  262. goto done;
  263. }
  264. if (aws_byte_buf_init(&pub_x_buffer, allocator, pub_x_length) ||
  265. aws_byte_buf_init(&pub_y_buffer, allocator, pub_y_length)) {
  266. goto done;
  267. }
  268. if (aws_hex_decode(&pub_x_hex_cursor, &pub_x_buffer) || aws_hex_decode(&pub_y_hex_cursor, &pub_y_buffer)) {
  269. goto done;
  270. }
  271. struct aws_byte_cursor pub_x_cursor = aws_byte_cursor_from_buf(&pub_x_buffer);
  272. struct aws_byte_cursor pub_y_cursor = aws_byte_cursor_from_buf(&pub_y_buffer);
  273. key = aws_ecc_key_pair_new_from_public_key(allocator, curve_name, &pub_x_cursor, &pub_y_cursor);
  274. done:
  275. aws_byte_buf_clean_up(&pub_x_buffer);
  276. aws_byte_buf_clean_up(&pub_y_buffer);
  277. return key;
  278. }