ecdh.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865
  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 "ecdh_misc.h"
  31. #include <string.h>
  32. /* Parameter validation macros based on platform_util.h */
  33. #define ECDH_VALIDATE_RET( cond ) \
  34. MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
  35. #define ECDH_VALIDATE( cond ) \
  36. MBEDTLS_INTERNAL_VALIDATE( cond )
  37. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  38. typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
  39. #endif
  40. static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
  41. const mbedtls_ecdh_context *ctx )
  42. {
  43. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  44. return( ctx->grp.id );
  45. #else
  46. return( ctx->grp_id );
  47. #endif
  48. }
  49. int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid )
  50. {
  51. /* At this time, all groups support ECDH. */
  52. (void) gid;
  53. return( 1 );
  54. }
  55. #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
  56. /*
  57. * Generate public key (restartable version)
  58. *
  59. * Note: this internal function relies on its caller preserving the value of
  60. * the output parameter 'd' across continuation calls. This would not be
  61. * acceptable for a public function but is OK here as we control call sites.
  62. */
  63. static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp,
  64. mbedtls_mpi *d, mbedtls_ecp_point *Q,
  65. int (*f_rng)(void *, unsigned char *, size_t),
  66. void *p_rng,
  67. mbedtls_ecp_restart_ctx *rs_ctx )
  68. {
  69. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  70. /* If multiplication is in progress, we already generated a privkey */
  71. #if defined(MBEDTLS_ECP_RESTARTABLE)
  72. if( rs_ctx == NULL || rs_ctx->rsm == NULL )
  73. #endif
  74. MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
  75. MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,
  76. f_rng, p_rng, rs_ctx ) );
  77. cleanup:
  78. return( ret );
  79. }
  80. /*
  81. * Generate public key
  82. */
  83. int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
  84. int (*f_rng)(void *, unsigned char *, size_t),
  85. void *p_rng )
  86. {
  87. ECDH_VALIDATE_RET( grp != NULL );
  88. ECDH_VALIDATE_RET( d != NULL );
  89. ECDH_VALIDATE_RET( Q != NULL );
  90. ECDH_VALIDATE_RET( f_rng != NULL );
  91. return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) );
  92. }
  93. #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
  94. #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
  95. /*
  96. * Compute shared secret (SEC1 3.3.1)
  97. */
  98. static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp,
  99. mbedtls_mpi *z,
  100. const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
  101. int (*f_rng)(void *, unsigned char *, size_t),
  102. void *p_rng,
  103. mbedtls_ecp_restart_ctx *rs_ctx )
  104. {
  105. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  106. mbedtls_ecp_point P;
  107. mbedtls_ecp_point_init( &P );
  108. MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q,
  109. f_rng, p_rng, rs_ctx ) );
  110. if( mbedtls_ecp_is_zero( &P ) )
  111. {
  112. ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  113. goto cleanup;
  114. }
  115. MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) );
  116. cleanup:
  117. mbedtls_ecp_point_free( &P );
  118. return( ret );
  119. }
  120. /*
  121. * Compute shared secret (SEC1 3.3.1)
  122. */
  123. int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
  124. const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
  125. int (*f_rng)(void *, unsigned char *, size_t),
  126. void *p_rng )
  127. {
  128. ECDH_VALIDATE_RET( grp != NULL );
  129. ECDH_VALIDATE_RET( Q != NULL );
  130. ECDH_VALIDATE_RET( d != NULL );
  131. ECDH_VALIDATE_RET( z != NULL );
  132. return( ecdh_compute_shared_restartable( grp, z, Q, d,
  133. f_rng, p_rng, NULL ) );
  134. }
  135. #endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
  136. static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx )
  137. {
  138. mbedtls_ecp_group_init( &ctx->grp );
  139. mbedtls_mpi_init( &ctx->d );
  140. mbedtls_ecp_point_init( &ctx->Q );
  141. mbedtls_ecp_point_init( &ctx->Qp );
  142. mbedtls_mpi_init( &ctx->z );
  143. #if defined(MBEDTLS_ECP_RESTARTABLE)
  144. mbedtls_ecp_restart_init( &ctx->rs );
  145. #endif
  146. }
  147. /*
  148. * Initialize context
  149. */
  150. void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
  151. {
  152. ECDH_VALIDATE( ctx != NULL );
  153. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  154. ecdh_init_internal( ctx );
  155. mbedtls_ecp_point_init( &ctx->Vi );
  156. mbedtls_ecp_point_init( &ctx->Vf );
  157. mbedtls_mpi_init( &ctx->_d );
  158. #else
  159. memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
  160. ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
  161. #endif
  162. ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
  163. #if defined(MBEDTLS_ECP_RESTARTABLE)
  164. ctx->restart_enabled = 0;
  165. #endif
  166. }
  167. static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx,
  168. mbedtls_ecp_group_id grp_id )
  169. {
  170. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  171. ret = mbedtls_ecp_group_load( &ctx->grp, grp_id );
  172. if( ret != 0 )
  173. {
  174. return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
  175. }
  176. return( 0 );
  177. }
  178. /*
  179. * Setup context
  180. */
  181. int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id )
  182. {
  183. ECDH_VALIDATE_RET( ctx != NULL );
  184. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  185. return( ecdh_setup_internal( ctx, grp_id ) );
  186. #else
  187. switch( grp_id )
  188. {
  189. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  190. case MBEDTLS_ECP_DP_CURVE25519:
  191. ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
  192. ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
  193. ctx->grp_id = grp_id;
  194. return( mbedtls_everest_setup( &ctx->ctx.everest_ecdh, grp_id ) );
  195. #endif
  196. default:
  197. ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
  198. ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
  199. ctx->grp_id = grp_id;
  200. ecdh_init_internal( &ctx->ctx.mbed_ecdh );
  201. return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) );
  202. }
  203. #endif
  204. }
  205. static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx )
  206. {
  207. mbedtls_ecp_group_free( &ctx->grp );
  208. mbedtls_mpi_free( &ctx->d );
  209. mbedtls_ecp_point_free( &ctx->Q );
  210. mbedtls_ecp_point_free( &ctx->Qp );
  211. mbedtls_mpi_free( &ctx->z );
  212. #if defined(MBEDTLS_ECP_RESTARTABLE)
  213. mbedtls_ecp_restart_free( &ctx->rs );
  214. #endif
  215. }
  216. #if defined(MBEDTLS_ECP_RESTARTABLE)
  217. /*
  218. * Enable restartable operations for context
  219. */
  220. void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx )
  221. {
  222. ECDH_VALIDATE( ctx != NULL );
  223. ctx->restart_enabled = 1;
  224. }
  225. #endif
  226. /*
  227. * Free context
  228. */
  229. void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
  230. {
  231. if( ctx == NULL )
  232. return;
  233. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  234. mbedtls_ecp_point_free( &ctx->Vi );
  235. mbedtls_ecp_point_free( &ctx->Vf );
  236. mbedtls_mpi_free( &ctx->_d );
  237. ecdh_free_internal( ctx );
  238. #else
  239. switch( ctx->var )
  240. {
  241. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  242. case MBEDTLS_ECDH_VARIANT_EVEREST:
  243. mbedtls_everest_free( &ctx->ctx.everest_ecdh );
  244. break;
  245. #endif
  246. case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
  247. ecdh_free_internal( &ctx->ctx.mbed_ecdh );
  248. break;
  249. default:
  250. break;
  251. }
  252. ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
  253. ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
  254. ctx->grp_id = MBEDTLS_ECP_DP_NONE;
  255. #endif
  256. }
  257. static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
  258. size_t *olen, int point_format,
  259. unsigned char *buf, size_t blen,
  260. int (*f_rng)(void *,
  261. unsigned char *,
  262. size_t),
  263. void *p_rng,
  264. int restart_enabled )
  265. {
  266. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  267. size_t grp_len, pt_len;
  268. #if defined(MBEDTLS_ECP_RESTARTABLE)
  269. mbedtls_ecp_restart_ctx *rs_ctx = NULL;
  270. #endif
  271. if( ctx->grp.pbits == 0 )
  272. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  273. #if defined(MBEDTLS_ECP_RESTARTABLE)
  274. if( restart_enabled )
  275. rs_ctx = &ctx->rs;
  276. #else
  277. (void) restart_enabled;
  278. #endif
  279. #if defined(MBEDTLS_ECP_RESTARTABLE)
  280. if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
  281. f_rng, p_rng, rs_ctx ) ) != 0 )
  282. return( ret );
  283. #else
  284. if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
  285. f_rng, p_rng ) ) != 0 )
  286. return( ret );
  287. #endif /* MBEDTLS_ECP_RESTARTABLE */
  288. if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf,
  289. blen ) ) != 0 )
  290. return( ret );
  291. buf += grp_len;
  292. blen -= grp_len;
  293. if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format,
  294. &pt_len, buf, blen ) ) != 0 )
  295. return( ret );
  296. *olen = grp_len + pt_len;
  297. return( 0 );
  298. }
  299. /*
  300. * Setup and write the ServerKeyExchange parameters (RFC 4492)
  301. * struct {
  302. * ECParameters curve_params;
  303. * ECPoint public;
  304. * } ServerECDHParams;
  305. */
  306. int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
  307. unsigned char *buf, size_t blen,
  308. int (*f_rng)(void *, unsigned char *, size_t),
  309. void *p_rng )
  310. {
  311. int restart_enabled = 0;
  312. ECDH_VALIDATE_RET( ctx != NULL );
  313. ECDH_VALIDATE_RET( olen != NULL );
  314. ECDH_VALIDATE_RET( buf != NULL );
  315. ECDH_VALIDATE_RET( f_rng != NULL );
  316. #if defined(MBEDTLS_ECP_RESTARTABLE)
  317. restart_enabled = ctx->restart_enabled;
  318. #else
  319. (void) restart_enabled;
  320. #endif
  321. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  322. return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen,
  323. f_rng, p_rng, restart_enabled ) );
  324. #else
  325. switch( ctx->var )
  326. {
  327. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  328. case MBEDTLS_ECDH_VARIANT_EVEREST:
  329. return( mbedtls_everest_make_params( &ctx->ctx.everest_ecdh, olen,
  330. buf, blen, f_rng, p_rng ) );
  331. #endif
  332. case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
  333. return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen,
  334. ctx->point_format, buf, blen,
  335. f_rng, p_rng,
  336. restart_enabled ) );
  337. default:
  338. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  339. }
  340. #endif
  341. }
  342. static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx,
  343. const unsigned char **buf,
  344. const unsigned char *end )
  345. {
  346. return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf,
  347. end - *buf ) );
  348. }
  349. /*
  350. * Read the ServerKeyExhange parameters (RFC 4492)
  351. * struct {
  352. * ECParameters curve_params;
  353. * ECPoint public;
  354. * } ServerECDHParams;
  355. */
  356. int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
  357. const unsigned char **buf,
  358. const unsigned char *end )
  359. {
  360. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  361. mbedtls_ecp_group_id grp_id;
  362. ECDH_VALIDATE_RET( ctx != NULL );
  363. ECDH_VALIDATE_RET( buf != NULL );
  364. ECDH_VALIDATE_RET( *buf != NULL );
  365. ECDH_VALIDATE_RET( end != NULL );
  366. if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) )
  367. != 0 )
  368. return( ret );
  369. if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 )
  370. return( ret );
  371. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  372. return( ecdh_read_params_internal( ctx, buf, end ) );
  373. #else
  374. switch( ctx->var )
  375. {
  376. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  377. case MBEDTLS_ECDH_VARIANT_EVEREST:
  378. return( mbedtls_everest_read_params( &ctx->ctx.everest_ecdh,
  379. buf, end) );
  380. #endif
  381. case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
  382. return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh,
  383. buf, end ) );
  384. default:
  385. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  386. }
  387. #endif
  388. }
  389. static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx,
  390. const mbedtls_ecp_keypair *key,
  391. mbedtls_ecdh_side side )
  392. {
  393. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  394. /* If it's not our key, just import the public part as Qp */
  395. if( side == MBEDTLS_ECDH_THEIRS )
  396. return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) );
  397. /* Our key: import public (as Q) and private parts */
  398. if( side != MBEDTLS_ECDH_OURS )
  399. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  400. if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ||
  401. ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 )
  402. return( ret );
  403. return( 0 );
  404. }
  405. /*
  406. * Get parameters from a keypair
  407. */
  408. int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx,
  409. const mbedtls_ecp_keypair *key,
  410. mbedtls_ecdh_side side )
  411. {
  412. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  413. ECDH_VALIDATE_RET( ctx != NULL );
  414. ECDH_VALIDATE_RET( key != NULL );
  415. ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS ||
  416. side == MBEDTLS_ECDH_THEIRS );
  417. if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE )
  418. {
  419. /* This is the first call to get_params(). Set up the context
  420. * for use with the group. */
  421. if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 )
  422. return( ret );
  423. }
  424. else
  425. {
  426. /* This is not the first call to get_params(). Check that the
  427. * current key's group is the same as the context's, which was set
  428. * from the first key's group. */
  429. if( mbedtls_ecdh_grp_id( ctx ) != key->grp.id )
  430. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  431. }
  432. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  433. return( ecdh_get_params_internal( ctx, key, side ) );
  434. #else
  435. switch( ctx->var )
  436. {
  437. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  438. case MBEDTLS_ECDH_VARIANT_EVEREST:
  439. {
  440. mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
  441. MBEDTLS_EVEREST_ECDH_OURS :
  442. MBEDTLS_EVEREST_ECDH_THEIRS;
  443. return( mbedtls_everest_get_params( &ctx->ctx.everest_ecdh,
  444. key, s) );
  445. }
  446. #endif
  447. case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
  448. return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh,
  449. key, side ) );
  450. default:
  451. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  452. }
  453. #endif
  454. }
  455. static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx,
  456. size_t *olen, int point_format,
  457. unsigned char *buf, size_t blen,
  458. int (*f_rng)(void *,
  459. unsigned char *,
  460. size_t),
  461. void *p_rng,
  462. int restart_enabled )
  463. {
  464. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  465. #if defined(MBEDTLS_ECP_RESTARTABLE)
  466. mbedtls_ecp_restart_ctx *rs_ctx = NULL;
  467. #endif
  468. if( ctx->grp.pbits == 0 )
  469. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  470. #if defined(MBEDTLS_ECP_RESTARTABLE)
  471. if( restart_enabled )
  472. rs_ctx = &ctx->rs;
  473. #else
  474. (void) restart_enabled;
  475. #endif
  476. #if defined(MBEDTLS_ECP_RESTARTABLE)
  477. if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q,
  478. f_rng, p_rng, rs_ctx ) ) != 0 )
  479. return( ret );
  480. #else
  481. if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
  482. f_rng, p_rng ) ) != 0 )
  483. return( ret );
  484. #endif /* MBEDTLS_ECP_RESTARTABLE */
  485. return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen,
  486. buf, blen );
  487. }
  488. /*
  489. * Setup and export the client public value
  490. */
  491. int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
  492. unsigned char *buf, size_t blen,
  493. int (*f_rng)(void *, unsigned char *, size_t),
  494. void *p_rng )
  495. {
  496. int restart_enabled = 0;
  497. ECDH_VALIDATE_RET( ctx != NULL );
  498. ECDH_VALIDATE_RET( olen != NULL );
  499. ECDH_VALIDATE_RET( buf != NULL );
  500. ECDH_VALIDATE_RET( f_rng != NULL );
  501. #if defined(MBEDTLS_ECP_RESTARTABLE)
  502. restart_enabled = ctx->restart_enabled;
  503. #endif
  504. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  505. return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen,
  506. f_rng, p_rng, restart_enabled ) );
  507. #else
  508. switch( ctx->var )
  509. {
  510. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  511. case MBEDTLS_ECDH_VARIANT_EVEREST:
  512. return( mbedtls_everest_make_public( &ctx->ctx.everest_ecdh, olen,
  513. buf, blen, f_rng, p_rng ) );
  514. #endif
  515. case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
  516. return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen,
  517. ctx->point_format, buf, blen,
  518. f_rng, p_rng,
  519. restart_enabled ) );
  520. default:
  521. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  522. }
  523. #endif
  524. }
  525. static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
  526. const unsigned char *buf, size_t blen )
  527. {
  528. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  529. const unsigned char *p = buf;
  530. if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p,
  531. blen ) ) != 0 )
  532. return( ret );
  533. if( (size_t)( p - buf ) != blen )
  534. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  535. return( 0 );
  536. }
  537. /*
  538. * Parse and import the client's public value
  539. */
  540. int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
  541. const unsigned char *buf, size_t blen )
  542. {
  543. ECDH_VALIDATE_RET( ctx != NULL );
  544. ECDH_VALIDATE_RET( buf != NULL );
  545. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  546. return( ecdh_read_public_internal( ctx, buf, blen ) );
  547. #else
  548. switch( ctx->var )
  549. {
  550. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  551. case MBEDTLS_ECDH_VARIANT_EVEREST:
  552. return( mbedtls_everest_read_public( &ctx->ctx.everest_ecdh,
  553. buf, blen ) );
  554. #endif
  555. case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
  556. return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh,
  557. buf, blen ) );
  558. default:
  559. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  560. }
  561. #endif
  562. }
  563. static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx,
  564. size_t *olen, unsigned char *buf,
  565. size_t blen,
  566. int (*f_rng)(void *,
  567. unsigned char *,
  568. size_t),
  569. void *p_rng,
  570. int restart_enabled )
  571. {
  572. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  573. #if defined(MBEDTLS_ECP_RESTARTABLE)
  574. mbedtls_ecp_restart_ctx *rs_ctx = NULL;
  575. #endif
  576. if( ctx == NULL || ctx->grp.pbits == 0 )
  577. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  578. #if defined(MBEDTLS_ECP_RESTARTABLE)
  579. if( restart_enabled )
  580. rs_ctx = &ctx->rs;
  581. #else
  582. (void) restart_enabled;
  583. #endif
  584. #if defined(MBEDTLS_ECP_RESTARTABLE)
  585. if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp,
  586. &ctx->d, f_rng, p_rng,
  587. rs_ctx ) ) != 0 )
  588. {
  589. return( ret );
  590. }
  591. #else
  592. if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp,
  593. &ctx->d, f_rng, p_rng ) ) != 0 )
  594. {
  595. return( ret );
  596. }
  597. #endif /* MBEDTLS_ECP_RESTARTABLE */
  598. if( mbedtls_mpi_size( &ctx->z ) > blen )
  599. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  600. *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 );
  601. if( mbedtls_ecp_get_type( &ctx->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
  602. return mbedtls_mpi_write_binary_le( &ctx->z, buf, *olen );
  603. return mbedtls_mpi_write_binary( &ctx->z, buf, *olen );
  604. }
  605. /*
  606. * Derive and export the shared secret
  607. */
  608. int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
  609. unsigned char *buf, size_t blen,
  610. int (*f_rng)(void *, unsigned char *, size_t),
  611. void *p_rng )
  612. {
  613. int restart_enabled = 0;
  614. ECDH_VALIDATE_RET( ctx != NULL );
  615. ECDH_VALIDATE_RET( olen != NULL );
  616. ECDH_VALIDATE_RET( buf != NULL );
  617. #if defined(MBEDTLS_ECP_RESTARTABLE)
  618. restart_enabled = ctx->restart_enabled;
  619. #endif
  620. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  621. return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng,
  622. restart_enabled ) );
  623. #else
  624. switch( ctx->var )
  625. {
  626. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  627. case MBEDTLS_ECDH_VARIANT_EVEREST:
  628. return( mbedtls_everest_calc_secret( &ctx->ctx.everest_ecdh, olen,
  629. buf, blen, f_rng, p_rng ) );
  630. #endif
  631. case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
  632. return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf,
  633. blen, f_rng, p_rng,
  634. restart_enabled ) );
  635. default:
  636. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  637. }
  638. #endif
  639. }
  640. #if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL)
  641. static int ecdh_tls13_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
  642. size_t *olen, int point_format, unsigned char *buf, size_t blen,
  643. int ( *f_rng )( void *, unsigned char *, size_t), void *p_rng )
  644. {
  645. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  646. if( ctx->grp.pbits == 0 )
  647. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  648. if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
  649. f_rng, p_rng ) ) != 0 )
  650. return( ret );
  651. ret = mbedtls_ecp_point_write_binary( &ctx->grp, &ctx->Q, point_format,
  652. olen, buf, blen );
  653. if( ret != 0 )
  654. return( ret );
  655. return( 0 );
  656. }
  657. int mbedtls_ecdh_tls13_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
  658. unsigned char *buf, size_t blen,
  659. int ( *f_rng )( void *, unsigned char *, size_t ),
  660. void *p_rng )
  661. {
  662. ECDH_VALIDATE_RET( ctx != NULL );
  663. ECDH_VALIDATE_RET( olen != NULL );
  664. ECDH_VALIDATE_RET( buf != NULL );
  665. ECDH_VALIDATE_RET( f_rng != NULL );
  666. #if defined(MBEDTLS_ECP_RESTARTABLE)
  667. if( ctx-> restart_enabled )
  668. return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
  669. #endif
  670. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  671. return( ecdh_tls13_make_params_internal( ctx, olen, ctx->point_format,
  672. buf, blen, f_rng, p_rng ) );
  673. #else
  674. switch( ctx->var )
  675. {
  676. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  677. case MBEDTLS_ECDH_VARIANT_EVEREST:
  678. return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
  679. #endif
  680. case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
  681. return( ecdh_tls13_make_params_internal( &ctx->ctx.mbed_ecdh, olen,
  682. ctx->point_format, buf, blen,
  683. f_rng, p_rng ) );
  684. default:
  685. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  686. }
  687. #endif
  688. }
  689. /*
  690. * Setup context without Everest
  691. */
  692. int mbedtls_ecdh_setup_no_everest( mbedtls_ecdh_context *ctx,
  693. mbedtls_ecp_group_id grp_id )
  694. {
  695. ECDH_VALIDATE_RET( ctx != NULL );
  696. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  697. return( ecdh_setup_internal( ctx, grp_id ) );
  698. #else
  699. ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
  700. ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
  701. ctx->grp_id = grp_id;
  702. ecdh_init_internal( &ctx->ctx.mbed_ecdh );
  703. return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) );
  704. #endif
  705. }
  706. static int ecdh_tls13_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
  707. const unsigned char *buf,
  708. size_t buf_len )
  709. {
  710. int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
  711. const unsigned char *p = buf;
  712. size_t data_len;
  713. if( buf_len < 3 )
  714. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  715. data_len = MBEDTLS_GET_UINT16_BE( p, 0 );
  716. p += 2;
  717. if( data_len < 1 || data_len != ( buf_len - 2 ) )
  718. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  719. if( ( ret = mbedtls_ecp_point_read_binary( &ctx->grp,
  720. &ctx->Qp, p, data_len ) ) != 0)
  721. {
  722. return( ret );
  723. }
  724. return( 0 );
  725. }
  726. /*
  727. * Parse and import the client's TLS 1.3 public value
  728. */
  729. int mbedtls_ecdh_tls13_read_public( mbedtls_ecdh_context *ctx,
  730. const unsigned char *buf,
  731. size_t buf_len )
  732. {
  733. ECDH_VALIDATE_RET( ctx != NULL );
  734. ECDH_VALIDATE_RET( buf != NULL );
  735. #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
  736. return( ecdh_tls13_read_public_internal( ctx, buf, buf_len ) );
  737. #else
  738. switch( ctx->var )
  739. {
  740. #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
  741. case MBEDTLS_ECDH_VARIANT_EVEREST:
  742. return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
  743. #endif
  744. case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
  745. return( ecdh_tls13_read_public_internal( &ctx->ctx.mbed_ecdh,
  746. buf, buf_len ) );
  747. default:
  748. return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  749. }
  750. #endif
  751. }
  752. #endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
  753. #endif /* MBEDTLS_ECDH_C */