ecdh.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /*
  2. * Elliptic curve Diffie-Hellman
  3. *
  4. * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
  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. * This file is part of mbed TLS (https://tls.mbed.org)
  20. */
  21. /*
  22. * References:
  23. *
  24. * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
  25. * RFC 4492
  26. */
  27. #if !defined(MBEDTLS_CONFIG_FILE)
  28. #include "mbedtls/config.h"
  29. #else
  30. #include MBEDTLS_CONFIG_FILE
  31. #endif
  32. #if defined(MBEDTLS_ECDH_C)
  33. #include "mbedtls/ecdh.h"
  34. #include <string.h>
  35. #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
  36. /*
  37. * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair
  38. */
  39. int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
  40. int (*f_rng)(void *, unsigned char *, size_t),
  41. void *p_rng )
  42. {
  43. return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng );
  44. }
  45. #endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */
  46. #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
  47. /*
  48. * Compute shared secret (SEC1 3.3.1)
  49. */
  50. int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
  51. const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
  52. int (*f_rng)(void *, unsigned char *, size_t),
  53. void *p_rng )
  54. {
  55. int ret;
  56. mbedtls_ecp_point P;
  57. mbedtls_ecp_point_init( &P );
  58. /*
  59. * Make sure Q is a valid pubkey before using it
  60. */
  61. MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
  62. MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) );
  63. if( mbedtls_ecp_is_zero( &P ) )
  64. {
  65. ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
  66. goto cleanup;
  67. }
  68. MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) );
  69. cleanup:
  70. mbedtls_ecp_point_free( &P );
  71. return( ret );
  72. }
  73. #endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
  74. /*
  75. * Initialize context
  76. */
  77. void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
  78. {
  79. memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
  80. }
  81. /*
  82. * Free context
  83. */
  84. void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
  85. {
  86. if( ctx == NULL )
  87. return;
  88. mbedtls_ecp_group_free( &ctx->grp );
  89. mbedtls_ecp_point_free( &ctx->Q );
  90. mbedtls_ecp_point_free( &ctx->Qp );
  91. mbedtls_ecp_point_free( &ctx->Vi );
  92. mbedtls_ecp_point_free( &ctx->Vf );
  93. mbedtls_mpi_free( &ctx->d );
  94. mbedtls_mpi_free( &ctx->z );
  95. mbedtls_mpi_free( &ctx->_d );
  96. }
  97. /*
  98. * Setup and write the ServerKeyExhange parameters (RFC 4492)
  99. * struct {
  100. * ECParameters curve_params;
  101. * ECPoint public;
  102. * } ServerECDHParams;
  103. */
  104. int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen,
  105. unsigned char *buf, size_t blen,
  106. int (*f_rng)(void *, unsigned char *, size_t),
  107. void *p_rng )
  108. {
  109. int ret;
  110. size_t grp_len, pt_len;
  111. if( ctx == NULL || ctx->grp.pbits == 0 )
  112. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  113. if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
  114. != 0 )
  115. return( ret );
  116. if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) )
  117. != 0 )
  118. return( ret );
  119. buf += grp_len;
  120. blen -= grp_len;
  121. if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
  122. &pt_len, buf, blen ) ) != 0 )
  123. return( ret );
  124. *olen = grp_len + pt_len;
  125. return( 0 );
  126. }
  127. /*
  128. * Read the ServerKeyExhange parameters (RFC 4492)
  129. * struct {
  130. * ECParameters curve_params;
  131. * ECPoint public;
  132. * } ServerECDHParams;
  133. */
  134. int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
  135. const unsigned char **buf, const unsigned char *end )
  136. {
  137. int ret;
  138. if( ( ret = mbedtls_ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 )
  139. return( ret );
  140. if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, end - *buf ) )
  141. != 0 )
  142. return( ret );
  143. return( 0 );
  144. }
  145. /*
  146. * Get parameters from a keypair
  147. */
  148. int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key,
  149. mbedtls_ecdh_side side )
  150. {
  151. int ret;
  152. if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 )
  153. return( ret );
  154. /* If it's not our key, just import the public part as Qp */
  155. if( side == MBEDTLS_ECDH_THEIRS )
  156. return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) );
  157. /* Our key: import public (as Q) and private parts */
  158. if( side != MBEDTLS_ECDH_OURS )
  159. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  160. if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ||
  161. ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 )
  162. return( ret );
  163. return( 0 );
  164. }
  165. /*
  166. * Setup and export the client public value
  167. */
  168. int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen,
  169. unsigned char *buf, size_t blen,
  170. int (*f_rng)(void *, unsigned char *, size_t),
  171. void *p_rng )
  172. {
  173. int ret;
  174. if( ctx == NULL || ctx->grp.pbits == 0 )
  175. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  176. if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
  177. != 0 )
  178. return( ret );
  179. return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
  180. olen, buf, blen );
  181. }
  182. /*
  183. * Parse and import the client's public value
  184. */
  185. int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
  186. const unsigned char *buf, size_t blen )
  187. {
  188. int ret;
  189. const unsigned char *p = buf;
  190. if( ctx == NULL )
  191. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  192. if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, blen ) ) != 0 )
  193. return( ret );
  194. if( (size_t)( p - buf ) != blen )
  195. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  196. return( 0 );
  197. }
  198. /*
  199. * Derive and export the shared secret
  200. */
  201. int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen,
  202. unsigned char *buf, size_t blen,
  203. int (*f_rng)(void *, unsigned char *, size_t),
  204. void *p_rng )
  205. {
  206. int ret;
  207. if( ctx == NULL )
  208. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  209. if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d,
  210. f_rng, p_rng ) ) != 0 )
  211. {
  212. return( ret );
  213. }
  214. if( mbedtls_mpi_size( &ctx->z ) > blen )
  215. return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
  216. *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 );
  217. return mbedtls_mpi_write_binary( &ctx->z, buf, *olen );
  218. }
  219. #endif /* MBEDTLS_ECDH_C */