ecdh.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. /*
  2. * Elliptic curve Diffie-Hellman
  3. *
  4. * Copyright The Mbed TLS Contributors
  5. * SPDX-License-Identifier: Apache-2.0
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License"); you may
  8. * not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  15. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. */
  19. /*
  20. * References:
  21. *
  22. * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
  23. * RFC 4492
  24. */
  25. #include "common.h"
  26. #if defined(MBEDTLS_ECDH_C)
  27. #include "mbedtls/ecdh.h"
  28. #include "mbedtls/platform_util.h"
  29. #include "mbedtls/error.h"
  30. #include <string.h>
  31. /* Parameter validation macros based on platform_util.h */
  32. #define ECDH_VALIDATE_RET( cond ) \
  33. MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
  34. #define ECDH_VALIDATE( cond ) \
  35. MBEDTLS_INTERNAL_VALIDATE( cond )
  36. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  37. typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
  38. #endif
  39. static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
  40. const mbedtls_ecdh_context *ctx )
  41. {
  42. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  43. return( ctx->grp.id );
  44. #else
  45. return( ctx->grp_id );
  46. #endif
  47. }
  48. int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid )
  49. {
  50. /* At this time, all groups support ECDH. */
  51. (void) gid;
  52. return( 1 );
  53. }
  54. #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
  55. /*
  56. * Generate public key (restartable version)
  57. *
  58. * Note: this internal function relies on its caller preserving the value of
  59. * the output parameter 'd' across continuation calls. This would not be
  60. * acceptable for a public function but is OK here as we control call sites.
  61. */
  62. static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
  63. mbedtls_mpi *d, mbedtls_ecp_point *Q,
  64. int (*f_rng)(void *, unsigned char *, size_t),
  65. void *p_rng,
  66. mbedtls_ecp_restart_ctx *rs_ctx )
  67. {
  68. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  69. /* If multiplication is in progress, we already generated a privkey */
  70. #if defined(MBEDTLS_ECP_RESTARTABLE)
  71. if( rs_ctx == NULL || rs_ctx->rsm == NULL )
  72. #endif
  73. MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
  74. MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,
  75. f_rng, p_rng, rs_ctx ) );
  76. cleanup:
  77. return( ret );
  78. }
  79. /*
  80. * Generate public key
  81. */
  82. int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
  83. int (*f_rng)(void *, unsigned char *, size_t),
  84. void *p_rng )
  85. {
  86. ECDH_VALIDATE_RET( grp != NULL );
  87. ECDH_VALIDATE_RET( d != NULL );
  88. ECDH_VALIDATE_RET( Q != NULL );
  89. ECDH_VALIDATE_RET( f_rng != NULL );
  90. return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) );
  91. }
  92. #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
  93. #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
  94. /*
  95. * Compute shared secret (SEC1 3.3.1)
  96. */
  97. static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp,
  98. mbedtls_mpi *z,
  99. const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
  100. int (*f_rng)(void *, unsigned char *, size_t),
  101. void *p_rng,
  102. mbedtls_ecp_restart_ctx *rs_ctx )
  103. {
  104. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  105. mbedtls_ecp_point P;
  106. mbedtls_ecp_point_init( &P );
  107. MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q,
  108. f_rng, p_rng, rs_ctx ) );
  109. if( mbedtls_ecp_is_zero( &P ) )
  110. {
  111. ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  112. goto cleanup;
  113. }
  114. MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) );
  115. cleanup:
  116. mbedtls_ecp_point_free( &P );
  117. return( ret );
  118. }
  119. /*
  120. * Compute shared secret (SEC1 3.3.1)
  121. */
  122. int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
  123. const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
  124. int (*f_rng)(void *, unsigned char *, size_t),
  125. void *p_rng )
  126. {
  127. ECDH_VALIDATE_RET( grp != NULL );
  128. ECDH_VALIDATE_RET( Q != NULL );
  129. ECDH_VALIDATE_RET( d != NULL );
  130. ECDH_VALIDATE_RET( z != NULL );
  131. return( ecdh_compute_shared_restartable( grp, z, Q, d,
  132. f_rng, p_rng, NULL ) );
  133. }
  134. #endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
  135. static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx )
  136. {
  137. mbedtls_ecp_group_init( &ctx->grp );
  138. mbedtls_mpi_init( &ctx->d );
  139. mbedtls_ecp_point_init( &ctx->Q );
  140. mbedtls_ecp_point_init( &ctx->Qp );
  141. mbedtls_mpi_init( &ctx->z );
  142. #if defined(MBEDTLS_ECP_RESTARTABLE)
  143. mbedtls_ecp_restart_init( &ctx->rs );
  144. #endif
  145. }
  146. /*
  147. * Initialize context
  148. */
  149. void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
  150. {
  151. ECDH_VALIDATE( ctx != NULL );
  152. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  153. ecdh_init_internal( ctx );
  154. mbedtls_ecp_point_init( &ctx->Vi );
  155. mbedtls_ecp_point_init( &ctx->Vf );
  156. mbedtls_mpi_init( &ctx->_d );
  157. #else
  158. memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
  159. ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
  160. #endif
  161. ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
  162. #if defined(MBEDTLS_ECP_RESTARTABLE)
  163. ctx->restart_enabled = 0;
  164. #endif
  165. }
  166. static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx,
  167. mbedtls_ecp_group_id grp_id )
  168. {
  169. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  170. ret = mbedtls_ecp_group_load( &ctx->grp, grp_id );
  171. if( ret != 0 )
  172. {
  173. return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
  174. }
  175. return( 0 );
  176. }
  177. /*
  178. * Setup context
  179. */
  180. int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id )
  181. {
  182. ECDH_VALIDATE_RET( ctx != NULL );
  183. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  184. return( ecdh_setup_internal( ctx, grp_id ) );
  185. #else
  186. switch( grp_id )
  187. {
  188. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  189. case MBEDTLS_ECP_DP_CURVE25519:
  190. ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
  191. ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
  192. ctx->grp_id = grp_id;
  193. return( mbedtls_everest_setup( &ctx->ctx.everest_ecdh, grp_id ) );
  194. #endif
  195. default:
  196. ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
  197. ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
  198. ctx->grp_id = grp_id;
  199. ecdh_init_internal( &ctx->ctx.mbed_ecdh );
  200. return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) );
  201. }
  202. #endif
  203. }
  204. static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx )
  205. {
  206. mbedtls_ecp_group_free( &ctx->grp );
  207. mbedtls_mpi_free( &ctx->d );
  208. mbedtls_ecp_point_free( &ctx->Q );
  209. mbedtls_ecp_point_free( &ctx->Qp );
  210. mbedtls_mpi_free( &ctx->z );
  211. #if defined(MBEDTLS_ECP_RESTARTABLE)
  212. mbedtls_ecp_restart_free( &ctx->rs );
  213. #endif
  214. }
  215. #if defined(MBEDTLS_ECP_RESTARTABLE)
  216. /*
  217. * Enable restartable operations for context
  218. */
  219. void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx )
  220. {
  221. ECDH_VALIDATE( ctx != NULL );
  222. ctx->restart_enabled = 1;
  223. }
  224. #endif
  225. /*
  226. * Free context
  227. */
  228. void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
  229. {
  230. if( ctx == NULL )
  231. return;
  232. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  233. mbedtls_ecp_point_free( &ctx->Vi );
  234. mbedtls_ecp_point_free( &ctx->Vf );
  235. mbedtls_mpi_free( &ctx->_d );
  236. ecdh_free_internal( ctx );
  237. #else
  238. switch( ctx->var )
  239. {
  240. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  241. case MBEDTLS_ECDH_VARIANT_EVEREST:
  242. mbedtls_everest_free( &ctx->ctx.everest_ecdh );
  243. break;
  244. #endif
  245. case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
  246. ecdh_free_internal( &ctx->ctx.mbed_ecdh );
  247. break;
  248. default:
  249. break;
  250. }
  251. ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
  252. ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
  253. ctx->grp_id = MBEDTLS_ECP_DP_NONE;
  254. #endif
  255. }
  256. static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
  257. size_t *olen, int point_format,
  258. unsigned char *buf, size_t blen,
  259. int (*f_rng)(void *,
  260. unsigned char *,
  261. size_t),
  262. void *p_rng,
  263. int restart_enabled )
  264. {
  265. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  266. size_t grp_len, pt_len;
  267. #if defined(MBEDTLS_ECP_RESTARTABLE)
  268. mbedtls_ecp_restart_ctx *rs_ctx = NULL;
  269. #endif
  270. if( ctx->grp.pbits == 0 )
  271. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  272. #if defined(MBEDTLS_ECP_RESTARTABLE)
  273. if( restart_enabled )
  274. rs_ctx = &ctx->rs;
  275. #else
  276. (void) restart_enabled;
  277. #endif
  278. #if defined(MBEDTLS_ECP_RESTARTABLE)
  279. if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
  280. f_rng, p_rng, rs_ctx ) ) != 0 )
  281. return( ret );
  282. #else
  283. if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
  284. f_rng, p_rng ) ) != 0 )
  285. return( ret );
  286. #endif /* MBEDTLS_ECP_RESTARTABLE */
  287. if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf,
  288. blen ) ) != 0 )
  289. return( ret );
  290. buf += grp_len;
  291. blen -= grp_len;
  292. if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format,
  293. &pt_len, buf, blen ) ) != 0 )
  294. return( ret );
  295. *olen = grp_len + pt_len;
  296. return( 0 );
  297. }
  298. /*
  299. * Setup and write the ServerKeyExchange parameters (RFC 4492)
  300. * struct {
  301. * ECParameters curve_params;
  302. * ECPoint public;
  303. * } ServerECDHParams;
  304. */
  305. int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
  306. unsigned char *buf, size_t blen,
  307. int (*f_rng)(void *, unsigned char *, size_t),
  308. void *p_rng )
  309. {
  310. int restart_enabled = 0;
  311. ECDH_VALIDATE_RET( ctx != NULL );
  312. ECDH_VALIDATE_RET( olen != NULL );
  313. ECDH_VALIDATE_RET( buf != NULL );
  314. ECDH_VALIDATE_RET( f_rng != NULL );
  315. #if defined(MBEDTLS_ECP_RESTARTABLE)
  316. restart_enabled = ctx->restart_enabled;
  317. #else
  318. (void) restart_enabled;
  319. #endif
  320. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  321. return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen,
  322. f_rng, p_rng, restart_enabled ) );
  323. #else
  324. switch( ctx->var )
  325. {
  326. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  327. case MBEDTLS_ECDH_VARIANT_EVEREST:
  328. return( mbedtls_everest_make_params( &ctx->ctx.everest_ecdh, olen,
  329. buf, blen, f_rng, p_rng ) );
  330. #endif
  331. case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
  332. return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen,
  333. ctx->point_format, buf, blen,
  334. f_rng, p_rng,
  335. restart_enabled ) );
  336. default:
  337. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  338. }
  339. #endif
  340. }
  341. static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx,
  342. const unsigned char **buf,
  343. const unsigned char *end )
  344. {
  345. return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf,
  346. end - *buf ) );
  347. }
  348. /*
  349. * Read the ServerKeyExhange parameters (RFC 4492)
  350. * struct {
  351. * ECParameters curve_params;
  352. * ECPoint public;
  353. * } ServerECDHParams;
  354. */
  355. int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
  356. const unsigned char **buf,
  357. const unsigned char *end )
  358. {
  359. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  360. mbedtls_ecp_group_id grp_id;
  361. ECDH_VALIDATE_RET( ctx != NULL );
  362. ECDH_VALIDATE_RET( buf != NULL );
  363. ECDH_VALIDATE_RET( *buf != NULL );
  364. ECDH_VALIDATE_RET( end != NULL );
  365. if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) )
  366. != 0 )
  367. return( ret );
  368. if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 )
  369. return( ret );
  370. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  371. return( ecdh_read_params_internal( ctx, buf, end ) );
  372. #else
  373. switch( ctx->var )
  374. {
  375. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  376. case MBEDTLS_ECDH_VARIANT_EVEREST:
  377. return( mbedtls_everest_read_params( &ctx->ctx.everest_ecdh,
  378. buf, end) );
  379. #endif
  380. case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
  381. return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh,
  382. buf, end ) );
  383. default:
  384. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  385. }
  386. #endif
  387. }
  388. static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx,
  389. const mbedtls_ecp_keypair *key,
  390. mbedtls_ecdh_side side )
  391. {
  392. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  393. /* If it's not our key, just import the public part as Qp */
  394. if( side == MBEDTLS_ECDH_THEIRS )
  395. return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) );
  396. /* Our key: import public (as Q) and private parts */
  397. if( side != MBEDTLS_ECDH_OURS )
  398. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  399. if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ||
  400. ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 )
  401. return( ret );
  402. return( 0 );
  403. }
  404. /*
  405. * Get parameters from a keypair
  406. */
  407. int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx,
  408. const mbedtls_ecp_keypair *key,
  409. mbedtls_ecdh_side side )
  410. {
  411. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  412. ECDH_VALIDATE_RET( ctx != NULL );
  413. ECDH_VALIDATE_RET( key != NULL );
  414. ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS ||
  415. side == MBEDTLS_ECDH_THEIRS );
  416. if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE )
  417. {
  418. /* This is the first call to get_params(). Set up the context
  419. * for use with the group. */
  420. if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 )
  421. return( ret );
  422. }
  423. else
  424. {
  425. /* This is not the first call to get_params(). Check that the
  426. * current key's group is the same as the context's, which was set
  427. * from the first key's group. */
  428. if( mbedtls_ecdh_grp_id( ctx ) != key->grp.id )
  429. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  430. }
  431. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  432. return( ecdh_get_params_internal( ctx, key, side ) );
  433. #else
  434. switch( ctx->var )
  435. {
  436. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  437. case MBEDTLS_ECDH_VARIANT_EVEREST:
  438. {
  439. mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
  440. MBEDTLS_EVEREST_ECDH_OURS :
  441. MBEDTLS_EVEREST_ECDH_THEIRS;
  442. return( mbedtls_everest_get_params( &ctx->ctx.everest_ecdh,
  443. key, s) );
  444. }
  445. #endif
  446. case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
  447. return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh,
  448. key, side ) );
  449. default:
  450. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  451. }
  452. #endif
  453. }
  454. static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx,
  455. size_t *olen, int point_format,
  456. unsigned char *buf, size_t blen,
  457. int (*f_rng)(void *,
  458. unsigned char *,
  459. size_t),
  460. void *p_rng,
  461. int restart_enabled )
  462. {
  463. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  464. #if defined(MBEDTLS_ECP_RESTARTABLE)
  465. mbedtls_ecp_restart_ctx *rs_ctx = NULL;
  466. #endif
  467. if( ctx->grp.pbits == 0 )
  468. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  469. #if defined(MBEDTLS_ECP_RESTARTABLE)
  470. if( restart_enabled )
  471. rs_ctx = &ctx->rs;
  472. #else
  473. (void) restart_enabled;
  474. #endif
  475. #if defined(MBEDTLS_ECP_RESTARTABLE)
  476. if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
  477. f_rng, p_rng, rs_ctx ) ) != 0 )
  478. return( ret );
  479. #else
  480. if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
  481. f_rng, p_rng ) ) != 0 )
  482. return( ret );
  483. #endif /* MBEDTLS_ECP_RESTARTABLE */
  484. return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen,
  485. buf, blen );
  486. }
  487. /*
  488. * Setup and export the client public value
  489. */
  490. int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
  491. unsigned char *buf, size_t blen,
  492. int (*f_rng)(void *, unsigned char *, size_t),
  493. void *p_rng )
  494. {
  495. int restart_enabled = 0;
  496. ECDH_VALIDATE_RET( ctx != NULL );
  497. ECDH_VALIDATE_RET( olen != NULL );
  498. ECDH_VALIDATE_RET( buf != NULL );
  499. ECDH_VALIDATE_RET( f_rng != NULL );
  500. #if defined(MBEDTLS_ECP_RESTARTABLE)
  501. restart_enabled = ctx->restart_enabled;
  502. #endif
  503. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  504. return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen,
  505. f_rng, p_rng, restart_enabled ) );
  506. #else
  507. switch( ctx->var )
  508. {
  509. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  510. case MBEDTLS_ECDH_VARIANT_EVEREST:
  511. return( mbedtls_everest_make_public( &ctx->ctx.everest_ecdh, olen,
  512. buf, blen, f_rng, p_rng ) );
  513. #endif
  514. case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
  515. return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen,
  516. ctx->point_format, buf, blen,
  517. f_rng, p_rng,
  518. restart_enabled ) );
  519. default:
  520. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  521. }
  522. #endif
  523. }
  524. static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
  525. const unsigned char *buf, size_t blen )
  526. {
  527. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  528. const unsigned char *p = buf;
  529. if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p,
  530. blen ) ) != 0 )
  531. return( ret );
  532. if( (size_t)( p - buf ) != blen )
  533. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  534. return( 0 );
  535. }
  536. /*
  537. * Parse and import the client's public value
  538. */
  539. int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
  540. const unsigned char *buf, size_t blen )
  541. {
  542. ECDH_VALIDATE_RET( ctx != NULL );
  543. ECDH_VALIDATE_RET( buf != NULL );
  544. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  545. return( ecdh_read_public_internal( ctx, buf, blen ) );
  546. #else
  547. switch( ctx->var )
  548. {
  549. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  550. case MBEDTLS_ECDH_VARIANT_EVEREST:
  551. return( mbedtls_everest_read_public( &ctx->ctx.everest_ecdh,
  552. buf, blen ) );
  553. #endif
  554. case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
  555. return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh,
  556. buf, blen ) );
  557. default:
  558. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  559. }
  560. #endif
  561. }
  562. static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx,
  563. size_t *olen, unsigned char *buf,
  564. size_t blen,
  565. int (*f_rng)(void *,
  566. unsigned char *,
  567. size_t),
  568. void *p_rng,
  569. int restart_enabled )
  570. {
  571. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  572. #if defined(MBEDTLS_ECP_RESTARTABLE)
  573. mbedtls_ecp_restart_ctx *rs_ctx = NULL;
  574. #endif
  575. if( ctx == NULL || ctx->grp.pbits == 0 )
  576. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  577. #if defined(MBEDTLS_ECP_RESTARTABLE)
  578. if( restart_enabled )
  579. rs_ctx = &ctx->rs;
  580. #else
  581. (void) restart_enabled;
  582. #endif
  583. #if defined(MBEDTLS_ECP_RESTARTABLE)
  584. if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp,
  585. &ctx->d, f_rng, p_rng,
  586. rs_ctx ) ) != 0 )
  587. {
  588. return( ret );
  589. }
  590. #else
  591. if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp,
  592. &ctx->d, f_rng, p_rng ) ) != 0 )
  593. {
  594. return( ret );
  595. }
  596. #endif /* MBEDTLS_ECP_RESTARTABLE */
  597. if( mbedtls_mpi_size( &ctx->z ) > blen )
  598. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  599. *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 );
  600. if( mbedtls_ecp_get_type( &ctx->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
  601. return mbedtls_mpi_write_binary_le( &ctx->z, buf, *olen );
  602. return mbedtls_mpi_write_binary( &ctx->z, buf, *olen );
  603. }
  604. /*
  605. * Derive and export the shared secret
  606. */
  607. int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
  608. unsigned char *buf, size_t blen,
  609. int (*f_rng)(void *, unsigned char *, size_t),
  610. void *p_rng )
  611. {
  612. int restart_enabled = 0;
  613. ECDH_VALIDATE_RET( ctx != NULL );
  614. ECDH_VALIDATE_RET( olen != NULL );
  615. ECDH_VALIDATE_RET( buf != NULL );
  616. #if defined(MBEDTLS_ECP_RESTARTABLE)
  617. restart_enabled = ctx->restart_enabled;
  618. #endif
  619. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  620. return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng,
  621. restart_enabled ) );
  622. #else
  623. switch( ctx->var )
  624. {
  625. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  626. case MBEDTLS_ECDH_VARIANT_EVEREST:
  627. return( mbedtls_everest_calc_secret( &ctx->ctx.everest_ecdh, olen,
  628. buf, blen, f_rng, p_rng ) );
  629. #endif
  630. case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
  631. return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf,
  632. blen, f_rng, p_rng,
  633. restart_enabled ) );
  634. default:
  635. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  636. }
  637. #endif
  638. }
  639. #endif /* MBEDTLS_ECDH_C */