opensslcrypto_ecc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  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 <openssl/bn.h>
  9. #include <openssl/ec.h>
  10. #include <openssl/ecdsa.h>
  11. #include <openssl/obj_mac.h>
  12. struct libcrypto_ecc_key {
  13. struct aws_ecc_key_pair key_pair;
  14. EC_KEY *ec_key;
  15. };
  16. static int s_curve_name_to_nid(enum aws_ecc_curve_name curve_name) {
  17. switch (curve_name) {
  18. case AWS_CAL_ECDSA_P256:
  19. return NID_X9_62_prime256v1;
  20. case AWS_CAL_ECDSA_P384:
  21. return NID_secp384r1;
  22. }
  23. AWS_FATAL_ASSERT(!"Unsupported elliptic curve name");
  24. return -1;
  25. }
  26. static void s_key_pair_destroy(struct aws_ecc_key_pair *key_pair) {
  27. if (key_pair) {
  28. aws_byte_buf_clean_up(&key_pair->pub_x);
  29. aws_byte_buf_clean_up(&key_pair->pub_y);
  30. aws_byte_buf_clean_up_secure(&key_pair->priv_d);
  31. struct libcrypto_ecc_key *key_impl = key_pair->impl;
  32. if (key_impl->ec_key) {
  33. EC_KEY_free(key_impl->ec_key);
  34. }
  35. aws_mem_release(key_pair->allocator, key_pair);
  36. }
  37. }
  38. static int s_sign_payload(
  39. const struct aws_ecc_key_pair *key_pair,
  40. const struct aws_byte_cursor *hash,
  41. struct aws_byte_buf *signature_output) {
  42. struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl;
  43. unsigned int signature_size = signature_output->capacity - signature_output->len;
  44. int ret_val = ECDSA_sign(
  45. 0,
  46. hash->ptr,
  47. hash->len,
  48. signature_output->buffer + signature_output->len,
  49. &signature_size,
  50. libcrypto_key_pair->ec_key);
  51. signature_output->len += signature_size;
  52. return ret_val == 1 ? AWS_OP_SUCCESS : aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  53. }
  54. static int s_verify_payload(
  55. const struct aws_ecc_key_pair *key_pair,
  56. const struct aws_byte_cursor *hash,
  57. const struct aws_byte_cursor *signature) {
  58. struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl;
  59. return ECDSA_verify(0, hash->ptr, hash->len, signature->ptr, signature->len, libcrypto_key_pair->ec_key) == 1
  60. ? AWS_OP_SUCCESS
  61. : aws_raise_error(AWS_ERROR_CAL_SIGNATURE_VALIDATION_FAILED);
  62. }
  63. static size_t s_signature_length(const struct aws_ecc_key_pair *key_pair) {
  64. struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl;
  65. return ECDSA_size(libcrypto_key_pair->ec_key);
  66. }
  67. static int s_fill_in_public_key_info(
  68. struct libcrypto_ecc_key *libcrypto_key_pair,
  69. const EC_GROUP *group,
  70. const EC_POINT *pub_key_point) {
  71. BIGNUM *big_num_x = BN_new();
  72. BIGNUM *big_num_y = BN_new();
  73. int ret_val = AWS_OP_ERR;
  74. if (EC_POINT_get_affine_coordinates_GFp(group, pub_key_point, big_num_x, big_num_y, NULL) != 1) {
  75. aws_raise_error(AWS_ERROR_INVALID_STATE);
  76. goto clean_up;
  77. }
  78. size_t x_coor_size = BN_num_bytes(big_num_x);
  79. size_t y_coor_size = BN_num_bytes(big_num_y);
  80. if (aws_byte_buf_init(&libcrypto_key_pair->key_pair.pub_x, libcrypto_key_pair->key_pair.allocator, x_coor_size)) {
  81. goto clean_up;
  82. }
  83. if (aws_byte_buf_init(&libcrypto_key_pair->key_pair.pub_y, libcrypto_key_pair->key_pair.allocator, y_coor_size)) {
  84. goto clean_up;
  85. }
  86. BN_bn2bin(big_num_x, libcrypto_key_pair->key_pair.pub_x.buffer);
  87. BN_bn2bin(big_num_y, libcrypto_key_pair->key_pair.pub_y.buffer);
  88. libcrypto_key_pair->key_pair.pub_x.len = x_coor_size;
  89. libcrypto_key_pair->key_pair.pub_y.len = y_coor_size;
  90. ret_val = AWS_OP_SUCCESS;
  91. clean_up:
  92. BN_free(big_num_x);
  93. BN_free(big_num_y);
  94. return ret_val;
  95. }
  96. static int s_derive_public_key(struct aws_ecc_key_pair *key_pair) {
  97. struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl;
  98. if (!libcrypto_key_pair->key_pair.priv_d.buffer) {
  99. return aws_raise_error(AWS_ERROR_INVALID_STATE);
  100. }
  101. /* we already have a public key. */
  102. if (libcrypto_key_pair->key_pair.pub_x.len) {
  103. return AWS_OP_SUCCESS;
  104. }
  105. BIGNUM *priv_key_num =
  106. BN_bin2bn(libcrypto_key_pair->key_pair.priv_d.buffer, libcrypto_key_pair->key_pair.priv_d.len, NULL);
  107. const EC_GROUP *group = EC_KEY_get0_group(libcrypto_key_pair->ec_key);
  108. EC_POINT *point = EC_POINT_new(group);
  109. EC_POINT_mul(group, point, priv_key_num, NULL, NULL, NULL);
  110. BN_free(priv_key_num);
  111. EC_KEY_set_public_key(libcrypto_key_pair->ec_key, point);
  112. int ret_val = s_fill_in_public_key_info(libcrypto_key_pair, group, point);
  113. EC_POINT_free(point);
  114. return ret_val;
  115. }
  116. static struct aws_ecc_key_pair_vtable vtable = {
  117. .sign_message = s_sign_payload,
  118. .verify_signature = s_verify_payload,
  119. .derive_pub_key = s_derive_public_key,
  120. .signature_length = s_signature_length,
  121. .destroy = s_key_pair_destroy,
  122. };
  123. struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_private_key_impl(
  124. struct aws_allocator *allocator,
  125. enum aws_ecc_curve_name curve_name,
  126. const struct aws_byte_cursor *priv_key) {
  127. size_t key_length = aws_ecc_key_coordinate_byte_size_from_curve_name(curve_name);
  128. if (priv_key->len != key_length) {
  129. AWS_LOGF_ERROR(AWS_LS_CAL_ECC, "Private key length does not match curve's expected length");
  130. aws_raise_error(AWS_ERROR_CAL_INVALID_KEY_LENGTH_FOR_ALGORITHM);
  131. return NULL;
  132. }
  133. struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key));
  134. key_impl->ec_key = EC_KEY_new_by_curve_name(s_curve_name_to_nid(curve_name));
  135. key_impl->key_pair.curve_name = curve_name;
  136. key_impl->key_pair.allocator = allocator;
  137. key_impl->key_pair.vtable = &vtable;
  138. key_impl->key_pair.impl = key_impl;
  139. aws_atomic_init_int(&key_impl->key_pair.ref_count, 1);
  140. aws_byte_buf_init_copy_from_cursor(&key_impl->key_pair.priv_d, allocator, *priv_key);
  141. BIGNUM *priv_key_num = BN_bin2bn(key_impl->key_pair.priv_d.buffer, key_impl->key_pair.priv_d.len, NULL);
  142. if (!EC_KEY_set_private_key(key_impl->ec_key, priv_key_num)) {
  143. AWS_LOGF_ERROR(AWS_LS_CAL_ECC, "Failed to set openssl private key");
  144. aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
  145. BN_free(priv_key_num);
  146. s_key_pair_destroy(&key_impl->key_pair);
  147. return NULL;
  148. }
  149. BN_free(priv_key_num);
  150. return &key_impl->key_pair;
  151. }
  152. struct aws_ecc_key_pair *aws_ecc_key_pair_new_generate_random(
  153. struct aws_allocator *allocator,
  154. enum aws_ecc_curve_name curve_name) {
  155. struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key));
  156. key_impl->ec_key = EC_KEY_new_by_curve_name(s_curve_name_to_nid(curve_name));
  157. key_impl->key_pair.curve_name = curve_name;
  158. key_impl->key_pair.allocator = allocator;
  159. key_impl->key_pair.vtable = &vtable;
  160. key_impl->key_pair.impl = key_impl;
  161. aws_atomic_init_int(&key_impl->key_pair.ref_count, 1);
  162. if (EC_KEY_generate_key(key_impl->ec_key) != 1) {
  163. goto error;
  164. }
  165. const EC_POINT *pub_key_point = EC_KEY_get0_public_key(key_impl->ec_key);
  166. const EC_GROUP *group = EC_KEY_get0_group(key_impl->ec_key);
  167. const BIGNUM *private_key_num = EC_KEY_get0_private_key(key_impl->ec_key);
  168. size_t priv_key_size = BN_num_bytes(private_key_num);
  169. if (aws_byte_buf_init(&key_impl->key_pair.priv_d, allocator, priv_key_size)) {
  170. goto error;
  171. }
  172. BN_bn2bin(private_key_num, key_impl->key_pair.priv_d.buffer);
  173. key_impl->key_pair.priv_d.len = priv_key_size;
  174. if (!s_fill_in_public_key_info(key_impl, group, pub_key_point)) {
  175. return &key_impl->key_pair;
  176. }
  177. error:
  178. s_key_pair_destroy(&key_impl->key_pair);
  179. return NULL;
  180. }
  181. struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_public_key_impl(
  182. struct aws_allocator *allocator,
  183. enum aws_ecc_curve_name curve_name,
  184. const struct aws_byte_cursor *public_key_x,
  185. const struct aws_byte_cursor *public_key_y) {
  186. struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key));
  187. BIGNUM *pub_x_num = NULL;
  188. BIGNUM *pub_y_num = NULL;
  189. EC_POINT *point = NULL;
  190. if (!key_impl) {
  191. return NULL;
  192. }
  193. key_impl->ec_key = EC_KEY_new_by_curve_name(s_curve_name_to_nid(curve_name));
  194. key_impl->key_pair.curve_name = curve_name;
  195. key_impl->key_pair.allocator = allocator;
  196. key_impl->key_pair.vtable = &vtable;
  197. key_impl->key_pair.impl = key_impl;
  198. aws_atomic_init_int(&key_impl->key_pair.ref_count, 1);
  199. if (aws_byte_buf_init_copy_from_cursor(&key_impl->key_pair.pub_x, allocator, *public_key_x)) {
  200. s_key_pair_destroy(&key_impl->key_pair);
  201. return NULL;
  202. }
  203. if (aws_byte_buf_init_copy_from_cursor(&key_impl->key_pair.pub_y, allocator, *public_key_y)) {
  204. s_key_pair_destroy(&key_impl->key_pair);
  205. return NULL;
  206. }
  207. pub_x_num = BN_bin2bn(public_key_x->ptr, public_key_x->len, NULL);
  208. pub_y_num = BN_bin2bn(public_key_y->ptr, public_key_y->len, NULL);
  209. const EC_GROUP *group = EC_KEY_get0_group(key_impl->ec_key);
  210. point = EC_POINT_new(group);
  211. if (EC_POINT_set_affine_coordinates_GFp(group, point, pub_x_num, pub_y_num, NULL) != 1) {
  212. goto error;
  213. }
  214. if (EC_KEY_set_public_key(key_impl->ec_key, point) != 1) {
  215. goto error;
  216. }
  217. EC_POINT_free(point);
  218. BN_free(pub_x_num);
  219. BN_free(pub_y_num);
  220. return &key_impl->key_pair;
  221. error:
  222. if (point) {
  223. EC_POINT_free(point);
  224. }
  225. if (pub_x_num) {
  226. BN_free(pub_x_num);
  227. }
  228. if (pub_y_num) {
  229. BN_free(pub_y_num);
  230. }
  231. s_key_pair_destroy(&key_impl->key_pair);
  232. return NULL;
  233. }
  234. struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_asn1(
  235. struct aws_allocator *allocator,
  236. const struct aws_byte_cursor *encoded_keys) {
  237. struct aws_ecc_key_pair *key = NULL;
  238. struct aws_der_decoder *decoder = aws_der_decoder_new(allocator, *encoded_keys);
  239. if (!decoder) {
  240. return NULL;
  241. }
  242. struct aws_byte_cursor pub_x;
  243. struct aws_byte_cursor pub_y;
  244. struct aws_byte_cursor priv_d;
  245. enum aws_ecc_curve_name curve_name;
  246. if (aws_der_decoder_load_ecc_key_pair(decoder, &pub_x, &pub_y, &priv_d, &curve_name)) {
  247. goto error;
  248. }
  249. if (priv_d.ptr) {
  250. struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key));
  251. key_impl->key_pair.curve_name = curve_name;
  252. /* as awkward as it seems, there's not a great way to manually set the public key, so let openssl just parse
  253. * the der document manually now that we know what parts are what. */
  254. if (!d2i_ECPrivateKey(&key_impl->ec_key, (const unsigned char **)&encoded_keys->ptr, encoded_keys->len)) {
  255. aws_mem_release(allocator, key_impl);
  256. aws_raise_error(AWS_ERROR_CAL_MISSING_REQUIRED_KEY_COMPONENT);
  257. goto error;
  258. }
  259. key_impl->key_pair.allocator = allocator;
  260. key_impl->key_pair.vtable = &vtable;
  261. key_impl->key_pair.impl = key_impl;
  262. aws_atomic_init_int(&key_impl->key_pair.ref_count, 1);
  263. key = &key_impl->key_pair;
  264. struct aws_byte_buf temp_buf;
  265. AWS_ZERO_STRUCT(temp_buf);
  266. if (pub_x.ptr) {
  267. temp_buf = aws_byte_buf_from_array(pub_x.ptr, pub_x.len);
  268. if (aws_byte_buf_init_copy(&key->pub_x, allocator, &temp_buf)) {
  269. goto error;
  270. }
  271. }
  272. if (pub_y.ptr) {
  273. temp_buf = aws_byte_buf_from_array(pub_y.ptr, pub_y.len);
  274. if (aws_byte_buf_init_copy(&key->pub_y, allocator, &temp_buf)) {
  275. goto error;
  276. }
  277. }
  278. if (priv_d.ptr) {
  279. temp_buf = aws_byte_buf_from_array(priv_d.ptr, priv_d.len);
  280. if (aws_byte_buf_init_copy(&key->priv_d, allocator, &temp_buf)) {
  281. goto error;
  282. }
  283. }
  284. } else {
  285. key = aws_ecc_key_pair_new_from_public_key(allocator, curve_name, &pub_x, &pub_y);
  286. if (!key) {
  287. goto error;
  288. }
  289. }
  290. aws_der_decoder_destroy(decoder);
  291. return key;
  292. error:
  293. aws_der_decoder_destroy(decoder);
  294. s_key_pair_destroy(key);
  295. return NULL;
  296. }