s2n_ecc_evp.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530
  1. /*
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License").
  5. * You may not use this file except in compliance with the License.
  6. * A copy of the License is located at
  7. *
  8. * http://aws.amazon.com/apache2.0
  9. *
  10. * or in the "license" file accompanying this file. This file is distributed
  11. * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  12. * express or implied. See the License for the specific language governing
  13. * permissions and limitations under the License.
  14. */
  15. #include "crypto/s2n_ecc_evp.h"
  16. #include <openssl/ecdh.h>
  17. #include <openssl/evp.h>
  18. #if defined(OPENSSL_IS_AWSLC)
  19. #error #include <openssl/mem.h>
  20. #endif
  21. #include <stdint.h>
  22. #include "tls/s2n_connection.h"
  23. #include "tls/s2n_ecc_preferences.h"
  24. #include "tls/s2n_tls_parameters.h"
  25. #include "utils/s2n_mem.h"
  26. #include "utils/s2n_safety.h"
  27. #define TLS_EC_CURVE_TYPE_NAMED 3
  28. DEFINE_POINTER_CLEANUP_FUNC(EVP_PKEY *, EVP_PKEY_free);
  29. DEFINE_POINTER_CLEANUP_FUNC(EVP_PKEY_CTX *, EVP_PKEY_CTX_free);
  30. DEFINE_POINTER_CLEANUP_FUNC(EC_KEY *, EC_KEY_free);
  31. #if !EVP_APIS_SUPPORTED
  32. DEFINE_POINTER_CLEANUP_FUNC(EC_POINT *, EC_POINT_free);
  33. #endif
  34. #if EVP_APIS_SUPPORTED
  35. static int s2n_ecc_evp_generate_key_x25519(const struct s2n_ecc_named_curve *named_curve, EVP_PKEY **evp_pkey);
  36. #else
  37. static int s2n_ecc_evp_write_point_data_snug(const EC_POINT *point, const EC_GROUP *group, struct s2n_blob *out);
  38. static int s2n_ecc_evp_calculate_point_length(const EC_POINT *point, const EC_GROUP *group, uint8_t *length);
  39. static EC_POINT *s2n_ecc_evp_blob_to_point(struct s2n_blob *blob, const EC_KEY *ec_key);
  40. #endif
  41. static int s2n_ecc_evp_generate_key_nist_curves(const struct s2n_ecc_named_curve *named_curve, EVP_PKEY **evp_pkey);
  42. static int s2n_ecc_evp_generate_own_key(const struct s2n_ecc_named_curve *named_curve, EVP_PKEY **evp_pkey);
  43. static int s2n_ecc_evp_compute_shared_secret(EVP_PKEY *own_key, EVP_PKEY *peer_public, uint16_t iana_id, struct s2n_blob *shared_secret);
  44. /* IANA values can be found here: https://tools.ietf.org/html/rfc8446#appendix-B.3.1.4 */
  45. const struct s2n_ecc_named_curve s2n_ecc_curve_secp256r1 = {
  46. .iana_id = TLS_EC_CURVE_SECP_256_R1,
  47. .libcrypto_nid = NID_X9_62_prime256v1,
  48. .name = "secp256r1",
  49. .share_size = SECP256R1_SHARE_SIZE,
  50. .generate_key = s2n_ecc_evp_generate_key_nist_curves,
  51. };
  52. const struct s2n_ecc_named_curve s2n_ecc_curve_secp384r1 = {
  53. .iana_id = TLS_EC_CURVE_SECP_384_R1,
  54. .libcrypto_nid = NID_secp384r1,
  55. .name = "secp384r1",
  56. .share_size = SECP384R1_SHARE_SIZE,
  57. .generate_key = s2n_ecc_evp_generate_key_nist_curves,
  58. };
  59. const struct s2n_ecc_named_curve s2n_ecc_curve_secp521r1 = {
  60. .iana_id = TLS_EC_CURVE_SECP_521_R1,
  61. .libcrypto_nid = NID_secp521r1,
  62. .name = "secp521r1",
  63. .share_size = SECP521R1_SHARE_SIZE,
  64. .generate_key = s2n_ecc_evp_generate_key_nist_curves,
  65. };
  66. #if EVP_APIS_SUPPORTED
  67. const struct s2n_ecc_named_curve s2n_ecc_curve_x25519 = {
  68. .iana_id = TLS_EC_CURVE_ECDH_X25519,
  69. .libcrypto_nid = NID_X25519,
  70. .name = "x25519",
  71. .share_size = X25519_SHARE_SIZE,
  72. .generate_key = s2n_ecc_evp_generate_key_x25519,
  73. };
  74. #else
  75. const struct s2n_ecc_named_curve s2n_ecc_curve_x25519 = { 0 };
  76. #endif
  77. /* A fake / unsupported curve for use in triggering retries
  78. * during testing.
  79. */
  80. const struct s2n_ecc_named_curve s2n_unsupported_curve = {
  81. .iana_id = 0,
  82. .name = "unsupported",
  83. .libcrypto_nid = NID_X9_62_prime256v1,
  84. .share_size = SECP256R1_SHARE_SIZE,
  85. .generate_key = s2n_ecc_evp_generate_key_nist_curves,
  86. };
  87. /* All curves that s2n supports. New curves MUST be added here.
  88. * This list is a super set of all the curves present in s2n_ecc_preferences list.
  89. */
  90. const struct s2n_ecc_named_curve *const s2n_all_supported_curves_list[] = {
  91. &s2n_ecc_curve_secp256r1,
  92. &s2n_ecc_curve_secp384r1,
  93. #if EVP_APIS_SUPPORTED
  94. &s2n_ecc_curve_x25519,
  95. #endif
  96. &s2n_ecc_curve_secp521r1,
  97. };
  98. const size_t s2n_all_supported_curves_list_len = s2n_array_len(s2n_all_supported_curves_list);
  99. int s2n_is_evp_apis_supported()
  100. {
  101. return EVP_APIS_SUPPORTED;
  102. }
  103. #if EVP_APIS_SUPPORTED
  104. static int s2n_ecc_evp_generate_key_x25519(const struct s2n_ecc_named_curve *named_curve, EVP_PKEY **evp_pkey)
  105. {
  106. DEFER_CLEANUP(EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(named_curve->libcrypto_nid, NULL),
  107. EVP_PKEY_CTX_free_pointer);
  108. S2N_ERROR_IF(pctx == NULL, S2N_ERR_ECDHE_GEN_KEY);
  109. POSIX_GUARD_OSSL(EVP_PKEY_keygen_init(pctx), S2N_ERR_ECDHE_GEN_KEY);
  110. POSIX_GUARD_OSSL(EVP_PKEY_keygen(pctx, evp_pkey), S2N_ERR_ECDHE_GEN_KEY);
  111. S2N_ERROR_IF(evp_pkey == NULL, S2N_ERR_ECDHE_GEN_KEY);
  112. return 0;
  113. }
  114. #endif
  115. static int s2n_ecc_evp_generate_key_nist_curves(const struct s2n_ecc_named_curve *named_curve, EVP_PKEY **evp_pkey)
  116. {
  117. DEFER_CLEANUP(EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL), EVP_PKEY_CTX_free_pointer);
  118. S2N_ERROR_IF(pctx == NULL, S2N_ERR_ECDHE_GEN_KEY);
  119. POSIX_GUARD_OSSL(EVP_PKEY_paramgen_init(pctx), S2N_ERR_ECDHE_GEN_KEY);
  120. POSIX_GUARD_OSSL(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, named_curve->libcrypto_nid), S2N_ERR_ECDHE_GEN_KEY);
  121. DEFER_CLEANUP(EVP_PKEY *params = NULL, EVP_PKEY_free_pointer);
  122. POSIX_GUARD_OSSL(EVP_PKEY_paramgen(pctx, &params), S2N_ERR_ECDHE_GEN_KEY);
  123. S2N_ERROR_IF(params == NULL, S2N_ERR_ECDHE_GEN_KEY);
  124. DEFER_CLEANUP(EVP_PKEY_CTX *kctx = EVP_PKEY_CTX_new(params, NULL), EVP_PKEY_CTX_free_pointer);
  125. S2N_ERROR_IF(kctx == NULL, S2N_ERR_ECDHE_GEN_KEY);
  126. POSIX_GUARD_OSSL(EVP_PKEY_keygen_init(kctx), S2N_ERR_ECDHE_GEN_KEY);
  127. POSIX_GUARD_OSSL(EVP_PKEY_keygen(kctx, evp_pkey), S2N_ERR_ECDHE_GEN_KEY);
  128. S2N_ERROR_IF(evp_pkey == NULL, S2N_ERR_ECDHE_GEN_KEY);
  129. return 0;
  130. }
  131. static int s2n_ecc_evp_generate_own_key(const struct s2n_ecc_named_curve *named_curve, EVP_PKEY **evp_pkey)
  132. {
  133. POSIX_ENSURE_REF(named_curve);
  134. S2N_ERROR_IF(named_curve->generate_key == NULL, S2N_ERR_ECDHE_GEN_KEY);
  135. return named_curve->generate_key(named_curve, evp_pkey);
  136. }
  137. static int s2n_ecc_evp_compute_shared_secret(EVP_PKEY *own_key, EVP_PKEY *peer_public, uint16_t iana_id, struct s2n_blob *shared_secret)
  138. {
  139. POSIX_ENSURE_REF(peer_public);
  140. POSIX_ENSURE_REF(own_key);
  141. /* From RFC 8446(TLS1.3) Section 4.2.8.2: For the curves secp256r1, secp384r1, and secp521r1, peers MUST validate
  142. * each other's public value Q by ensuring that the point is a valid point on the elliptic curve.
  143. * For the curve x25519 and x448 the peer public-key validation check doesn't apply.
  144. * From RFC 8422(TLS1.2) Section 5.11: With the NIST curves, each party MUST validate the public key sent by its peer
  145. * in the ClientKeyExchange and ServerKeyExchange messages. A receiving party MUST check that the x and y parameters from
  146. * the peer's public value satisfy the curve equation, y^2 = x^3 + ax + b mod p.
  147. * Note that the `EC_KEY_check_key` validation is a MUST for only NIST curves, if a non-NIST curve is added to s2n-tls
  148. * this is an additional validation step that increases security but decreases performance.
  149. */
  150. if (iana_id != TLS_EC_CURVE_ECDH_X25519 && iana_id != TLS_EC_CURVE_ECDH_X448) {
  151. DEFER_CLEANUP(EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(peer_public), EC_KEY_free_pointer);
  152. S2N_ERROR_IF(ec_key == NULL, S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
  153. POSIX_GUARD_OSSL(EC_KEY_check_key(ec_key), S2N_ERR_ECDHE_SHARED_SECRET);
  154. }
  155. size_t shared_secret_size;
  156. DEFER_CLEANUP(EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(own_key, NULL), EVP_PKEY_CTX_free_pointer);
  157. S2N_ERROR_IF(ctx == NULL, S2N_ERR_ECDHE_SHARED_SECRET);
  158. POSIX_GUARD_OSSL(EVP_PKEY_derive_init(ctx), S2N_ERR_ECDHE_SHARED_SECRET);
  159. POSIX_GUARD_OSSL(EVP_PKEY_derive_set_peer(ctx, peer_public), S2N_ERR_ECDHE_SHARED_SECRET);
  160. POSIX_GUARD_OSSL(EVP_PKEY_derive(ctx, NULL, &shared_secret_size), S2N_ERR_ECDHE_SHARED_SECRET);
  161. POSIX_GUARD(s2n_alloc(shared_secret, shared_secret_size));
  162. if (EVP_PKEY_derive(ctx, shared_secret->data, &shared_secret_size) != 1) {
  163. POSIX_GUARD(s2n_free(shared_secret));
  164. POSIX_BAIL(S2N_ERR_ECDHE_SHARED_SECRET);
  165. }
  166. return 0;
  167. }
  168. int s2n_ecc_evp_generate_ephemeral_key(struct s2n_ecc_evp_params *ecc_evp_params)
  169. {
  170. POSIX_ENSURE_REF(ecc_evp_params->negotiated_curve);
  171. S2N_ERROR_IF(ecc_evp_params->evp_pkey != NULL, S2N_ERR_ECDHE_GEN_KEY);
  172. S2N_ERROR_IF(s2n_ecc_evp_generate_own_key(ecc_evp_params->negotiated_curve, &ecc_evp_params->evp_pkey) != 0,
  173. S2N_ERR_ECDHE_GEN_KEY);
  174. S2N_ERROR_IF(ecc_evp_params->evp_pkey == NULL, S2N_ERR_ECDHE_GEN_KEY);
  175. return 0;
  176. }
  177. int s2n_ecc_evp_compute_shared_secret_from_params(struct s2n_ecc_evp_params *private_ecc_evp_params,
  178. struct s2n_ecc_evp_params *public_ecc_evp_params,
  179. struct s2n_blob *shared_key)
  180. {
  181. POSIX_ENSURE_REF(private_ecc_evp_params->negotiated_curve);
  182. POSIX_ENSURE_REF(private_ecc_evp_params->evp_pkey);
  183. POSIX_ENSURE_REF(public_ecc_evp_params->negotiated_curve);
  184. POSIX_ENSURE_REF(public_ecc_evp_params->evp_pkey);
  185. S2N_ERROR_IF(private_ecc_evp_params->negotiated_curve->iana_id != public_ecc_evp_params->negotiated_curve->iana_id,
  186. S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
  187. POSIX_GUARD(s2n_ecc_evp_compute_shared_secret(private_ecc_evp_params->evp_pkey, public_ecc_evp_params->evp_pkey,
  188. private_ecc_evp_params->negotiated_curve->iana_id, shared_key));
  189. return 0;
  190. }
  191. int s2n_ecc_evp_compute_shared_secret_as_server(struct s2n_ecc_evp_params *ecc_evp_params,
  192. struct s2n_stuffer *Yc_in, struct s2n_blob *shared_key)
  193. {
  194. POSIX_ENSURE_REF(ecc_evp_params->negotiated_curve);
  195. POSIX_ENSURE_REF(ecc_evp_params->evp_pkey);
  196. POSIX_ENSURE_REF(Yc_in);
  197. uint8_t client_public_len;
  198. struct s2n_blob client_public_blob = { 0 };
  199. DEFER_CLEANUP(EVP_PKEY *peer_key = EVP_PKEY_new(), EVP_PKEY_free_pointer);
  200. S2N_ERROR_IF(peer_key == NULL, S2N_ERR_BAD_MESSAGE);
  201. POSIX_GUARD(s2n_stuffer_read_uint8(Yc_in, &client_public_len));
  202. client_public_blob.size = client_public_len;
  203. client_public_blob.data = s2n_stuffer_raw_read(Yc_in, client_public_blob.size);
  204. POSIX_ENSURE_REF(client_public_blob.data);
  205. #if EVP_APIS_SUPPORTED
  206. if (ecc_evp_params->negotiated_curve->libcrypto_nid == NID_X25519) {
  207. POSIX_GUARD(EVP_PKEY_set_type(peer_key, ecc_evp_params->negotiated_curve->libcrypto_nid));
  208. } else {
  209. DEFER_CLEANUP(EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL), EVP_PKEY_CTX_free_pointer);
  210. S2N_ERROR_IF(pctx == NULL, S2N_ERR_ECDHE_SERIALIZING);
  211. POSIX_GUARD_OSSL(EVP_PKEY_paramgen_init(pctx), S2N_ERR_ECDHE_SERIALIZING);
  212. POSIX_GUARD_OSSL(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ecc_evp_params->negotiated_curve->libcrypto_nid), S2N_ERR_ECDHE_SERIALIZING);
  213. POSIX_GUARD_OSSL(EVP_PKEY_paramgen(pctx, &peer_key), S2N_ERR_ECDHE_SERIALIZING);
  214. }
  215. POSIX_GUARD_OSSL(EVP_PKEY_set1_tls_encodedpoint(peer_key, client_public_blob.data, client_public_blob.size),
  216. S2N_ERR_ECDHE_SERIALIZING);
  217. #else
  218. DEFER_CLEANUP(EC_KEY *ec_key = EC_KEY_new_by_curve_name(ecc_evp_params->negotiated_curve->libcrypto_nid),
  219. EC_KEY_free_pointer);
  220. S2N_ERROR_IF(ec_key == NULL, S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
  221. DEFER_CLEANUP(EC_POINT *point = s2n_ecc_evp_blob_to_point(&client_public_blob, ec_key), EC_POINT_free_pointer);
  222. S2N_ERROR_IF(point == NULL, S2N_ERR_BAD_MESSAGE);
  223. int success = EC_KEY_set_public_key(ec_key, point);
  224. POSIX_GUARD_OSSL(EVP_PKEY_set1_EC_KEY(peer_key, ec_key), S2N_ERR_ECDHE_SERIALIZING);
  225. S2N_ERROR_IF(success == 0, S2N_ERR_BAD_MESSAGE);
  226. #endif
  227. return s2n_ecc_evp_compute_shared_secret(ecc_evp_params->evp_pkey, peer_key,
  228. ecc_evp_params->negotiated_curve->iana_id, shared_key);
  229. }
  230. int s2n_ecc_evp_compute_shared_secret_as_client(struct s2n_ecc_evp_params *ecc_evp_params,
  231. struct s2n_stuffer *Yc_out, struct s2n_blob *shared_key)
  232. {
  233. DEFER_CLEANUP(struct s2n_ecc_evp_params client_params = { 0 }, s2n_ecc_evp_params_free);
  234. POSIX_ENSURE_REF(ecc_evp_params->negotiated_curve);
  235. client_params.negotiated_curve = ecc_evp_params->negotiated_curve;
  236. POSIX_GUARD(s2n_ecc_evp_generate_own_key(client_params.negotiated_curve, &client_params.evp_pkey));
  237. S2N_ERROR_IF(client_params.evp_pkey == NULL, S2N_ERR_ECDHE_GEN_KEY);
  238. if (s2n_ecc_evp_compute_shared_secret(client_params.evp_pkey, ecc_evp_params->evp_pkey, ecc_evp_params->negotiated_curve->iana_id, shared_key)
  239. != S2N_SUCCESS) {
  240. POSIX_BAIL(S2N_ERR_ECDHE_SHARED_SECRET);
  241. }
  242. POSIX_GUARD(s2n_stuffer_write_uint8(Yc_out, client_params.negotiated_curve->share_size));
  243. if (s2n_ecc_evp_write_params_point(&client_params, Yc_out) != 0) {
  244. POSIX_BAIL(S2N_ERR_ECDHE_SERIALIZING);
  245. }
  246. return 0;
  247. }
  248. #if (!EVP_APIS_SUPPORTED)
  249. static int s2n_ecc_evp_calculate_point_length(const EC_POINT *point, const EC_GROUP *group, uint8_t *length)
  250. {
  251. size_t ret = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
  252. S2N_ERROR_IF(ret == 0, S2N_ERR_ECDHE_SERIALIZING);
  253. S2N_ERROR_IF(ret > UINT8_MAX, S2N_ERR_ECDHE_SERIALIZING);
  254. *length = (uint8_t) ret;
  255. return 0;
  256. }
  257. static int s2n_ecc_evp_write_point_data_snug(const EC_POINT *point, const EC_GROUP *group, struct s2n_blob *out)
  258. {
  259. size_t ret = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, out->data, out->size, NULL);
  260. S2N_ERROR_IF(ret != out->size, S2N_ERR_ECDHE_SERIALIZING);
  261. return 0;
  262. }
  263. static EC_POINT *s2n_ecc_evp_blob_to_point(struct s2n_blob *blob, const EC_KEY *ec_key)
  264. {
  265. const EC_GROUP *group = EC_KEY_get0_group(ec_key);
  266. EC_POINT *point = EC_POINT_new(group);
  267. if (point == NULL) {
  268. PTR_BAIL(S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
  269. }
  270. if (EC_POINT_oct2point(group, point, blob->data, blob->size, NULL) != 1) {
  271. EC_POINT_free(point);
  272. PTR_BAIL(S2N_ERR_BAD_MESSAGE);
  273. }
  274. return point;
  275. }
  276. #endif
  277. int s2n_ecc_evp_read_params_point(struct s2n_stuffer *in, int point_size, struct s2n_blob *point_blob)
  278. {
  279. POSIX_ENSURE_REF(in);
  280. POSIX_ENSURE_REF(point_blob);
  281. POSIX_ENSURE_GTE(point_size, 0);
  282. /* Extract point from stuffer */
  283. point_blob->size = point_size;
  284. point_blob->data = s2n_stuffer_raw_read(in, point_size);
  285. POSIX_ENSURE_REF(point_blob->data);
  286. return 0;
  287. }
  288. int s2n_ecc_evp_read_params(struct s2n_stuffer *in, struct s2n_blob *data_to_verify,
  289. struct s2n_ecdhe_raw_server_params *raw_server_ecc_params)
  290. {
  291. POSIX_ENSURE_REF(in);
  292. uint8_t curve_type;
  293. uint8_t point_length;
  294. /* Remember where we started reading the data */
  295. data_to_verify->data = s2n_stuffer_raw_read(in, 0);
  296. POSIX_ENSURE_REF(data_to_verify->data);
  297. /* Read the curve */
  298. POSIX_GUARD(s2n_stuffer_read_uint8(in, &curve_type));
  299. S2N_ERROR_IF(curve_type != TLS_EC_CURVE_TYPE_NAMED, S2N_ERR_BAD_MESSAGE);
  300. raw_server_ecc_params->curve_blob.data = s2n_stuffer_raw_read(in, 2);
  301. POSIX_ENSURE_REF(raw_server_ecc_params->curve_blob.data);
  302. raw_server_ecc_params->curve_blob.size = 2;
  303. /* Read the point */
  304. POSIX_GUARD(s2n_stuffer_read_uint8(in, &point_length));
  305. POSIX_GUARD(s2n_ecc_evp_read_params_point(in, point_length, &raw_server_ecc_params->point_blob));
  306. /* curve type (1) + iana (2) + key share size (1) + key share */
  307. data_to_verify->size = point_length + 4;
  308. return 0;
  309. }
  310. int s2n_ecc_evp_write_params_point(struct s2n_ecc_evp_params *ecc_evp_params, struct s2n_stuffer *out)
  311. {
  312. POSIX_ENSURE_REF(ecc_evp_params);
  313. POSIX_ENSURE_REF(ecc_evp_params->negotiated_curve);
  314. POSIX_ENSURE_REF(ecc_evp_params->evp_pkey);
  315. POSIX_ENSURE_REF(out);
  316. #if EVP_APIS_SUPPORTED
  317. struct s2n_blob point_blob = { 0 };
  318. uint8_t *encoded_point = NULL;
  319. size_t size = EVP_PKEY_get1_tls_encodedpoint(ecc_evp_params->evp_pkey, &encoded_point);
  320. if (size != ecc_evp_params->negotiated_curve->share_size) {
  321. OPENSSL_free(encoded_point);
  322. POSIX_BAIL(S2N_ERR_ECDHE_SERIALIZING);
  323. } else {
  324. point_blob.data = s2n_stuffer_raw_write(out, ecc_evp_params->negotiated_curve->share_size);
  325. POSIX_ENSURE_REF(point_blob.data);
  326. POSIX_CHECKED_MEMCPY(point_blob.data, encoded_point, size);
  327. OPENSSL_free(encoded_point);
  328. }
  329. #else
  330. uint8_t point_len;
  331. struct s2n_blob point_blob = { 0 };
  332. DEFER_CLEANUP(EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(ecc_evp_params->evp_pkey), EC_KEY_free_pointer);
  333. S2N_ERROR_IF(ec_key == NULL, S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
  334. const EC_POINT *point = EC_KEY_get0_public_key(ec_key);
  335. const EC_GROUP *group = EC_KEY_get0_group(ec_key);
  336. S2N_ERROR_IF(point == NULL || group == NULL, S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
  337. POSIX_GUARD(s2n_ecc_evp_calculate_point_length(point, group, &point_len));
  338. S2N_ERROR_IF(point_len != ecc_evp_params->negotiated_curve->share_size, S2N_ERR_ECDHE_SERIALIZING);
  339. point_blob.data = s2n_stuffer_raw_write(out, point_len);
  340. POSIX_ENSURE_REF(point_blob.data);
  341. point_blob.size = point_len;
  342. POSIX_GUARD(s2n_ecc_evp_write_point_data_snug(point, group, &point_blob));
  343. #endif
  344. return 0;
  345. }
  346. int s2n_ecc_evp_write_params(struct s2n_ecc_evp_params *ecc_evp_params, struct s2n_stuffer *out,
  347. struct s2n_blob *written)
  348. {
  349. POSIX_ENSURE_REF(ecc_evp_params);
  350. POSIX_ENSURE_REF(ecc_evp_params->negotiated_curve);
  351. POSIX_ENSURE_REF(ecc_evp_params->evp_pkey);
  352. POSIX_ENSURE_REF(out);
  353. POSIX_ENSURE_REF(written);
  354. uint8_t key_share_size = ecc_evp_params->negotiated_curve->share_size;
  355. /* Remember where the written data starts */
  356. written->data = s2n_stuffer_raw_write(out, 0);
  357. POSIX_ENSURE_REF(written->data);
  358. POSIX_GUARD(s2n_stuffer_write_uint8(out, TLS_EC_CURVE_TYPE_NAMED));
  359. POSIX_GUARD(s2n_stuffer_write_uint16(out, ecc_evp_params->negotiated_curve->iana_id));
  360. POSIX_GUARD(s2n_stuffer_write_uint8(out, key_share_size));
  361. POSIX_GUARD(s2n_ecc_evp_write_params_point(ecc_evp_params, out));
  362. /* key share + key share size (1) + iana (2) + curve type (1) */
  363. written->size = key_share_size + 4;
  364. return written->size;
  365. }
  366. int s2n_ecc_evp_parse_params_point(struct s2n_blob *point_blob, struct s2n_ecc_evp_params *ecc_evp_params)
  367. {
  368. POSIX_ENSURE_REF(point_blob->data);
  369. POSIX_ENSURE_REF(ecc_evp_params->negotiated_curve);
  370. S2N_ERROR_IF(point_blob->size != ecc_evp_params->negotiated_curve->share_size, S2N_ERR_ECDHE_SERIALIZING);
  371. #if EVP_APIS_SUPPORTED
  372. if (ecc_evp_params->negotiated_curve->libcrypto_nid == NID_X25519) {
  373. if (ecc_evp_params->evp_pkey == NULL) {
  374. ecc_evp_params->evp_pkey = EVP_PKEY_new();
  375. }
  376. S2N_ERROR_IF(ecc_evp_params->evp_pkey == NULL, S2N_ERR_BAD_MESSAGE);
  377. POSIX_GUARD(EVP_PKEY_set_type(ecc_evp_params->evp_pkey, ecc_evp_params->negotiated_curve->libcrypto_nid));
  378. } else {
  379. DEFER_CLEANUP(EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL), EVP_PKEY_CTX_free_pointer);
  380. S2N_ERROR_IF(pctx == NULL, S2N_ERR_ECDHE_SERIALIZING);
  381. POSIX_GUARD_OSSL(EVP_PKEY_paramgen_init(pctx), S2N_ERR_ECDHE_SERIALIZING);
  382. POSIX_GUARD_OSSL(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, ecc_evp_params->negotiated_curve->libcrypto_nid), S2N_ERR_ECDHE_SERIALIZING);
  383. POSIX_GUARD_OSSL(EVP_PKEY_paramgen(pctx, &ecc_evp_params->evp_pkey), S2N_ERR_ECDHE_SERIALIZING);
  384. }
  385. POSIX_GUARD_OSSL(EVP_PKEY_set1_tls_encodedpoint(ecc_evp_params->evp_pkey, point_blob->data, point_blob->size),
  386. S2N_ERR_ECDHE_SERIALIZING);
  387. #else
  388. if (ecc_evp_params->evp_pkey == NULL) {
  389. ecc_evp_params->evp_pkey = EVP_PKEY_new();
  390. }
  391. S2N_ERROR_IF(ecc_evp_params->evp_pkey == NULL, S2N_ERR_BAD_MESSAGE);
  392. /* Create a key to store the point */
  393. DEFER_CLEANUP(EC_KEY *ec_key = EC_KEY_new_by_curve_name(ecc_evp_params->negotiated_curve->libcrypto_nid),
  394. EC_KEY_free_pointer);
  395. S2N_ERROR_IF(ec_key == NULL, S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
  396. /* Parse and store the server public point */
  397. DEFER_CLEANUP(EC_POINT *point = s2n_ecc_evp_blob_to_point(point_blob, ec_key), EC_POINT_free_pointer);
  398. S2N_ERROR_IF(point == NULL, S2N_ERR_BAD_MESSAGE);
  399. /* Set the point as the public key */
  400. int success = EC_KEY_set_public_key(ec_key, point);
  401. POSIX_GUARD_OSSL(EVP_PKEY_set1_EC_KEY(ecc_evp_params->evp_pkey, ec_key), S2N_ERR_ECDHE_SERIALIZING);
  402. /* EC_KEY_set_public_key returns 1 on success, 0 on failure */
  403. S2N_ERROR_IF(success == 0, S2N_ERR_BAD_MESSAGE);
  404. #endif
  405. return 0;
  406. }
  407. int s2n_ecc_evp_parse_params(struct s2n_connection *conn, struct s2n_ecdhe_raw_server_params *raw_server_ecc_params,
  408. struct s2n_ecc_evp_params *ecc_evp_params)
  409. {
  410. POSIX_ENSURE(s2n_ecc_evp_find_supported_curve(conn, &raw_server_ecc_params->curve_blob, &ecc_evp_params->negotiated_curve) == 0,
  411. S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
  412. return s2n_ecc_evp_parse_params_point(&raw_server_ecc_params->point_blob, ecc_evp_params);
  413. }
  414. int s2n_ecc_evp_find_supported_curve(struct s2n_connection *conn, struct s2n_blob *iana_ids, const struct s2n_ecc_named_curve **found)
  415. {
  416. const struct s2n_ecc_preferences *ecc_prefs = NULL;
  417. POSIX_GUARD(s2n_connection_get_ecc_preferences(conn, &ecc_prefs));
  418. POSIX_ENSURE_REF(ecc_prefs);
  419. struct s2n_stuffer iana_ids_in = { 0 };
  420. POSIX_GUARD(s2n_stuffer_init(&iana_ids_in, iana_ids));
  421. POSIX_GUARD(s2n_stuffer_write(&iana_ids_in, iana_ids));
  422. for (size_t i = 0; i < ecc_prefs->count; i++) {
  423. const struct s2n_ecc_named_curve *supported_curve = ecc_prefs->ecc_curves[i];
  424. for (uint32_t j = 0; j < iana_ids->size / 2; j++) {
  425. uint16_t iana_id;
  426. POSIX_GUARD(s2n_stuffer_read_uint16(&iana_ids_in, &iana_id));
  427. if (supported_curve->iana_id == iana_id) {
  428. *found = supported_curve;
  429. return 0;
  430. }
  431. }
  432. POSIX_GUARD(s2n_stuffer_reread(&iana_ids_in));
  433. }
  434. POSIX_BAIL(S2N_ERR_ECDHE_UNSUPPORTED_CURVE);
  435. }
  436. int s2n_ecc_evp_params_free(struct s2n_ecc_evp_params *ecc_evp_params)
  437. {
  438. if (ecc_evp_params->evp_pkey != NULL) {
  439. EVP_PKEY_free(ecc_evp_params->evp_pkey);
  440. ecc_evp_params->evp_pkey = NULL;
  441. }
  442. return 0;
  443. }