PageRenderTime 42ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/auth/ecdhe.c

https://gitlab.com/axil/gnutls
C | 397 lines | 300 code | 63 blank | 34 comment | 31 complexity | 24762ccaa267021fa9bd4d056a3ae1c5 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. * Copyright (C) 2011-2012 Free Software Foundation, Inc.
  3. *
  4. * Author: Nikos Mavrogiannopoulos
  5. *
  6. * This file is part of GnuTLS.
  7. *
  8. * The GnuTLS is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public License
  10. * as published by the Free Software Foundation; either version 2.1 of
  11. * the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>
  20. *
  21. */
  22. /* This file contains common stuff in Ephemeral Diffie-Hellman (DHE)
  23. * and Anonymous DH key exchange(DHA). These are used in the handshake
  24. * procedure of the certificate and anoymous authentication.
  25. */
  26. #include <gnutls_int.h>
  27. #include "gnutls_auth.h"
  28. #include "gnutls_errors.h"
  29. #include "gnutls_dh.h"
  30. #include "gnutls_num.h"
  31. #include "gnutls_sig.h"
  32. #include <gnutls_state.h>
  33. #include <gnutls_datum.h>
  34. #include <gnutls_x509.h>
  35. #include <auth/ecdhe.h>
  36. #include <gnutls_ecc.h>
  37. #include <ext/ecc.h>
  38. #include <algorithms.h>
  39. #include <auth/psk.h>
  40. #include <auth/cert.h>
  41. #include <gnutls_pk.h>
  42. static int gen_ecdhe_server_kx(gnutls_session_t, gnutls_buffer_st *);
  43. static int
  44. proc_ecdhe_server_kx(gnutls_session_t session,
  45. uint8_t * data, size_t _data_size);
  46. static int
  47. proc_ecdhe_client_kx(gnutls_session_t session,
  48. uint8_t * data, size_t _data_size);
  49. #if defined(ENABLE_ECDHE)
  50. const mod_auth_st ecdhe_ecdsa_auth_struct = {
  51. "ECDHE_ECDSA",
  52. _gnutls_gen_cert_server_crt,
  53. _gnutls_gen_cert_client_crt,
  54. gen_ecdhe_server_kx,
  55. _gnutls_gen_ecdh_common_client_kx, /* This is the only difference */
  56. _gnutls_gen_cert_client_crt_vrfy,
  57. _gnutls_gen_cert_server_cert_req,
  58. _gnutls_proc_crt,
  59. _gnutls_proc_crt,
  60. proc_ecdhe_server_kx,
  61. proc_ecdhe_client_kx,
  62. _gnutls_proc_cert_client_crt_vrfy,
  63. _gnutls_proc_cert_cert_req
  64. };
  65. const mod_auth_st ecdhe_rsa_auth_struct = {
  66. "ECDHE_RSA",
  67. _gnutls_gen_cert_server_crt,
  68. _gnutls_gen_cert_client_crt,
  69. gen_ecdhe_server_kx,
  70. _gnutls_gen_ecdh_common_client_kx, /* This is the only difference */
  71. _gnutls_gen_cert_client_crt_vrfy,
  72. _gnutls_gen_cert_server_cert_req,
  73. _gnutls_proc_crt,
  74. _gnutls_proc_crt,
  75. proc_ecdhe_server_kx,
  76. proc_ecdhe_client_kx,
  77. _gnutls_proc_cert_client_crt_vrfy,
  78. _gnutls_proc_cert_cert_req
  79. };
  80. static int calc_ecdh_key(gnutls_session_t session,
  81. gnutls_datum_t * psk_key,
  82. gnutls_ecc_curve_t curve)
  83. {
  84. gnutls_pk_params_st pub;
  85. int ret;
  86. gnutls_pk_params_init(&pub);
  87. pub.params[ECC_X] = session->key.ecdh_x;
  88. pub.params[ECC_Y] = session->key.ecdh_y;
  89. pub.flags = curve;
  90. if (psk_key == NULL)
  91. ret =
  92. _gnutls_pk_derive(GNUTLS_PK_EC, &session->key.key,
  93. &session->key.ecdh_params, &pub);
  94. else {
  95. gnutls_datum_t tmp_dh_key;
  96. ret =
  97. _gnutls_pk_derive(GNUTLS_PK_EC, &tmp_dh_key,
  98. &session->key.ecdh_params, &pub);
  99. if (ret < 0) {
  100. ret = gnutls_assert_val(ret);
  101. goto cleanup;
  102. }
  103. ret =
  104. _gnutls_set_psk_session_key(session, psk_key,
  105. &tmp_dh_key);
  106. _gnutls_free_temp_key_datum(&tmp_dh_key);
  107. }
  108. if (ret < 0) {
  109. ret = gnutls_assert_val(ret);
  110. goto cleanup;
  111. }
  112. ret = 0;
  113. cleanup:
  114. /* no longer needed */
  115. _gnutls_mpi_release(&session->key.ecdh_x);
  116. _gnutls_mpi_release(&session->key.ecdh_y);
  117. gnutls_pk_params_release(&session->key.ecdh_params);
  118. return ret;
  119. }
  120. int _gnutls_proc_ecdh_common_client_kx(gnutls_session_t session,
  121. uint8_t * data, size_t _data_size,
  122. gnutls_ecc_curve_t curve,
  123. gnutls_datum_t * psk_key)
  124. {
  125. ssize_t data_size = _data_size;
  126. int ret, i = 0;
  127. int point_size;
  128. if (curve == GNUTLS_ECC_CURVE_INVALID)
  129. return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES);
  130. DECR_LEN(data_size, 1);
  131. point_size = data[i];
  132. i += 1;
  133. DECR_LEN(data_size, point_size);
  134. ret =
  135. _gnutls_ecc_ansi_x963_import(&data[i], point_size,
  136. &session->key.ecdh_x,
  137. &session->key.ecdh_y);
  138. if (ret < 0) {
  139. gnutls_assert();
  140. goto cleanup;
  141. }
  142. /* generate pre-shared key */
  143. ret = calc_ecdh_key(session, psk_key, curve);
  144. if (ret < 0) {
  145. gnutls_assert();
  146. goto cleanup;
  147. }
  148. cleanup:
  149. gnutls_pk_params_clear(&session->key.ecdh_params);
  150. return ret;
  151. }
  152. static int
  153. proc_ecdhe_client_kx(gnutls_session_t session,
  154. uint8_t * data, size_t _data_size)
  155. {
  156. gnutls_certificate_credentials_t cred;
  157. cred = (gnutls_certificate_credentials_t)
  158. _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE, NULL);
  159. if (cred == NULL) {
  160. gnutls_assert();
  161. return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
  162. }
  163. return _gnutls_proc_ecdh_common_client_kx(session, data,
  164. _data_size,
  165. _gnutls_session_ecc_curve_get
  166. (session), NULL);
  167. }
  168. int
  169. _gnutls_gen_ecdh_common_client_kx(gnutls_session_t session,
  170. gnutls_buffer_st * data)
  171. {
  172. return _gnutls_gen_ecdh_common_client_kx_int(session, data, NULL);
  173. }
  174. int
  175. _gnutls_gen_ecdh_common_client_kx_int(gnutls_session_t session,
  176. gnutls_buffer_st * data,
  177. gnutls_datum_t * psk_key)
  178. {
  179. int ret;
  180. gnutls_datum_t out;
  181. int curve = _gnutls_session_ecc_curve_get(session);
  182. /* generate temporal key */
  183. ret =
  184. _gnutls_pk_generate_keys(GNUTLS_PK_EC, curve,
  185. &session->key.ecdh_params);
  186. if (ret < 0)
  187. return gnutls_assert_val(ret);
  188. ret =
  189. _gnutls_ecc_ansi_x963_export(curve,
  190. session->key.ecdh_params.
  191. params[ECC_X] /* x */ ,
  192. session->key.ecdh_params.
  193. params[ECC_Y] /* y */ , &out);
  194. if (ret < 0) {
  195. gnutls_assert();
  196. goto cleanup;
  197. }
  198. ret =
  199. _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size);
  200. _gnutls_free_datum(&out);
  201. if (ret < 0) {
  202. gnutls_assert();
  203. goto cleanup;
  204. }
  205. /* generate pre-shared key */
  206. ret = calc_ecdh_key(session, psk_key, curve);
  207. if (ret < 0) {
  208. gnutls_assert();
  209. goto cleanup;
  210. }
  211. ret = data->length;
  212. cleanup:
  213. gnutls_pk_params_clear(&session->key.ecdh_params);
  214. return ret;
  215. }
  216. static int
  217. proc_ecdhe_server_kx(gnutls_session_t session,
  218. uint8_t * data, size_t _data_size)
  219. {
  220. int ret;
  221. gnutls_datum_t vparams;
  222. ret =
  223. _gnutls_proc_ecdh_common_server_kx(session, data, _data_size);
  224. if (ret < 0)
  225. return gnutls_assert_val(ret);
  226. vparams.data = data;
  227. vparams.size = ret;
  228. return _gnutls_proc_dhe_signature(session, data + ret,
  229. _data_size - ret, &vparams);
  230. }
  231. int
  232. _gnutls_proc_ecdh_common_server_kx(gnutls_session_t session,
  233. uint8_t * data, size_t _data_size)
  234. {
  235. int i, ret, point_size;
  236. gnutls_ecc_curve_t curve;
  237. ssize_t data_size = _data_size;
  238. i = 0;
  239. DECR_LEN(data_size, 1);
  240. if (data[i++] != 3)
  241. return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES);
  242. DECR_LEN(data_size, 2);
  243. curve = _gnutls_tls_id_to_ecc_curve(_gnutls_read_uint16(&data[i]));
  244. i += 2;
  245. ret = _gnutls_session_supports_ecc_curve(session, curve);
  246. if (ret < 0)
  247. return gnutls_assert_val(ret);
  248. _gnutls_session_ecc_curve_set(session, curve);
  249. DECR_LEN(data_size, 1);
  250. point_size = data[i];
  251. i++;
  252. DECR_LEN(data_size, point_size);
  253. ret =
  254. _gnutls_ecc_ansi_x963_import(&data[i], point_size,
  255. &session->key.ecdh_x,
  256. &session->key.ecdh_y);
  257. if (ret < 0)
  258. return gnutls_assert_val(ret);
  259. i += point_size;
  260. return i;
  261. }
  262. /* If the psk flag is set, then an empty psk_identity_hint will
  263. * be inserted */
  264. int _gnutls_ecdh_common_print_server_kx(gnutls_session_t session,
  265. gnutls_buffer_st * data,
  266. gnutls_ecc_curve_t curve)
  267. {
  268. uint8_t p;
  269. int ret;
  270. gnutls_datum_t out;
  271. if (curve == GNUTLS_ECC_CURVE_INVALID)
  272. return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES);
  273. /* curve type */
  274. p = 3;
  275. ret = _gnutls_buffer_append_data(data, &p, 1);
  276. if (ret < 0)
  277. return gnutls_assert_val(ret);
  278. ret =
  279. _gnutls_buffer_append_prefix(data, 16,
  280. _gnutls_ecc_curve_get_tls_id
  281. (curve));
  282. if (ret < 0)
  283. return gnutls_assert_val(ret);
  284. /* generate temporal key */
  285. ret =
  286. _gnutls_pk_generate_keys(GNUTLS_PK_EC, curve,
  287. &session->key.ecdh_params);
  288. if (ret < 0)
  289. return gnutls_assert_val(ret);
  290. ret =
  291. _gnutls_ecc_ansi_x963_export(curve,
  292. session->key.ecdh_params.
  293. params[ECC_X] /* x */ ,
  294. session->key.ecdh_params.
  295. params[ECC_Y] /* y */ , &out);
  296. if (ret < 0)
  297. return gnutls_assert_val(ret);
  298. ret =
  299. _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size);
  300. _gnutls_free_datum(&out);
  301. if (ret < 0)
  302. return gnutls_assert_val(ret);
  303. return data->length;
  304. }
  305. static int
  306. gen_ecdhe_server_kx(gnutls_session_t session, gnutls_buffer_st * data)
  307. {
  308. int ret = 0;
  309. gnutls_certificate_credentials_t cred;
  310. cred = (gnutls_certificate_credentials_t)
  311. _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE, NULL);
  312. if (cred == NULL) {
  313. gnutls_assert();
  314. return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
  315. }
  316. if ((ret = _gnutls_auth_info_set(session, GNUTLS_CRD_CERTIFICATE,
  317. sizeof(cert_auth_info_st),
  318. 0)) < 0) {
  319. gnutls_assert();
  320. return ret;
  321. }
  322. ret =
  323. _gnutls_ecdh_common_print_server_kx(session, data,
  324. _gnutls_session_ecc_curve_get
  325. (session));
  326. if (ret < 0) {
  327. gnutls_assert();
  328. return ret;
  329. }
  330. /* Generate the signature. */
  331. return _gnutls_gen_dhe_signature(session, data, data->data,
  332. data->length);
  333. }
  334. #endif