ecdh.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*
  2. * Elliptic curve Diffie-Hellman
  3. *
  4. * Copyright (C) 2006-2014, Brainspark B.V.
  5. *
  6. * This file is part of PolarSSL (http://www.polarssl.org)
  7. * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
  8. *
  9. * All rights reserved.
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License along
  22. * with this program; if not, write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  24. */
  25. /*
  26. * References:
  27. *
  28. * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
  29. * RFC 4492
  30. */
  31. #if !defined(POLARSSL_CONFIG_FILE)
  32. #include "polarssl/config.h"
  33. #else
  34. #include POLARSSL_CONFIG_FILE
  35. #endif
  36. #if defined(POLARSSL_ECDH_C)
  37. #include "polarssl/ecdh.h"
  38. /*
  39. * Generate public key: simple wrapper around ecp_gen_keypair
  40. */
  41. int ecdh_gen_public( ecp_group *grp, mpi *d, ecp_point *Q,
  42. int (*f_rng)(void *, unsigned char *, size_t),
  43. void *p_rng )
  44. {
  45. return ecp_gen_keypair( grp, d, Q, f_rng, p_rng );
  46. }
  47. /*
  48. * Compute shared secret (SEC1 3.3.1)
  49. */
  50. int ecdh_compute_shared( ecp_group *grp, mpi *z,
  51. const ecp_point *Q, const mpi *d,
  52. int (*f_rng)(void *, unsigned char *, size_t),
  53. void *p_rng )
  54. {
  55. int ret;
  56. ecp_point P;
  57. ecp_point_init( &P );
  58. /*
  59. * Make sure Q is a valid pubkey before using it
  60. */
  61. MPI_CHK( ecp_check_pubkey( grp, Q ) );
  62. MPI_CHK( ecp_mul( grp, &P, d, Q, f_rng, p_rng ) );
  63. if( ecp_is_zero( &P ) )
  64. {
  65. ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA;
  66. goto cleanup;
  67. }
  68. MPI_CHK( mpi_copy( z, &P.X ) );
  69. cleanup:
  70. ecp_point_free( &P );
  71. return( ret );
  72. }
  73. /*
  74. * Initialize context
  75. */
  76. void ecdh_init( ecdh_context *ctx )
  77. {
  78. memset( ctx, 0, sizeof( ecdh_context ) );
  79. }
  80. /*
  81. * Free context
  82. */
  83. void ecdh_free( ecdh_context *ctx )
  84. {
  85. if( ctx == NULL )
  86. return;
  87. ecp_group_free( &ctx->grp );
  88. ecp_point_free( &ctx->Q );
  89. ecp_point_free( &ctx->Qp );
  90. ecp_point_free( &ctx->Vi );
  91. ecp_point_free( &ctx->Vf );
  92. mpi_free( &ctx->d );
  93. mpi_free( &ctx->z );
  94. mpi_free( &ctx->_d );
  95. }
  96. /*
  97. * Setup and write the ServerKeyExhange parameters (RFC 4492)
  98. * struct {
  99. * ECParameters curve_params;
  100. * ECPoint public;
  101. * } ServerECDHParams;
  102. */
  103. int ecdh_make_params( ecdh_context *ctx, size_t *olen,
  104. unsigned char *buf, size_t blen,
  105. int (*f_rng)(void *, unsigned char *, size_t),
  106. void *p_rng )
  107. {
  108. int ret;
  109. size_t grp_len, pt_len;
  110. if( ctx == NULL || ctx->grp.pbits == 0 )
  111. return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
  112. if( ( ret = ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
  113. != 0 )
  114. return( ret );
  115. if( ( ret = ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) )
  116. != 0 )
  117. return( ret );
  118. buf += grp_len;
  119. blen -= grp_len;
  120. if( ( ret = ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
  121. &pt_len, buf, blen ) ) != 0 )
  122. return( ret );
  123. *olen = grp_len + pt_len;
  124. return( 0 );
  125. }
  126. /*
  127. * Read the ServerKeyExhange parameters (RFC 4492)
  128. * struct {
  129. * ECParameters curve_params;
  130. * ECPoint public;
  131. * } ServerECDHParams;
  132. */
  133. int ecdh_read_params( ecdh_context *ctx,
  134. const unsigned char **buf, const unsigned char *end )
  135. {
  136. int ret;
  137. if( ( ret = ecp_tls_read_group( &ctx->grp, buf, end - *buf ) ) != 0 )
  138. return( ret );
  139. if( ( ret = ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, end - *buf ) )
  140. != 0 )
  141. return( ret );
  142. return( 0 );
  143. }
  144. /*
  145. * Get parameters from a keypair
  146. */
  147. int ecdh_get_params( ecdh_context *ctx, const ecp_keypair *key,
  148. ecdh_side side )
  149. {
  150. int ret;
  151. if( ( ret = ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 )
  152. return( ret );
  153. /* If it's not our key, just import the public part as Qp */
  154. if( side == POLARSSL_ECDH_THEIRS )
  155. return( ecp_copy( &ctx->Qp, &key->Q ) );
  156. /* Our key: import public (as Q) and private parts */
  157. if( side != POLARSSL_ECDH_OURS )
  158. return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
  159. if( ( ret = ecp_copy( &ctx->Q, &key->Q ) ) != 0 ||
  160. ( ret = mpi_copy( &ctx->d, &key->d ) ) != 0 )
  161. return( ret );
  162. return( 0 );
  163. }
  164. /*
  165. * Setup and export the client public value
  166. */
  167. int ecdh_make_public( ecdh_context *ctx, size_t *olen,
  168. unsigned char *buf, size_t blen,
  169. int (*f_rng)(void *, unsigned char *, size_t),
  170. void *p_rng )
  171. {
  172. int ret;
  173. if( ctx == NULL || ctx->grp.pbits == 0 )
  174. return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
  175. if( ( ret = ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) )
  176. != 0 )
  177. return( ret );
  178. return ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format,
  179. olen, buf, blen );
  180. }
  181. /*
  182. * Parse and import the client's public value
  183. */
  184. int ecdh_read_public( ecdh_context *ctx,
  185. const unsigned char *buf, size_t blen )
  186. {
  187. int ret;
  188. const unsigned char *p = buf;
  189. if( ctx == NULL )
  190. return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
  191. if( ( ret = ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, blen ) ) != 0 )
  192. return( ret );
  193. if( (size_t)( p - buf ) != blen )
  194. return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
  195. return( 0 );
  196. }
  197. /*
  198. * Derive and export the shared secret
  199. */
  200. int ecdh_calc_secret( ecdh_context *ctx, size_t *olen,
  201. unsigned char *buf, size_t blen,
  202. int (*f_rng)(void *, unsigned char *, size_t),
  203. void *p_rng )
  204. {
  205. int ret;
  206. if( ctx == NULL )
  207. return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
  208. if( ( ret = ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d,
  209. f_rng, p_rng ) ) != 0 )
  210. {
  211. return( ret );
  212. }
  213. if( mpi_size( &ctx->z ) > blen )
  214. return( POLARSSL_ERR_ECP_BAD_INPUT_DATA );
  215. *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 );
  216. return mpi_write_binary( &ctx->z, buf, *olen );
  217. }
  218. #if defined(POLARSSL_SELF_TEST)
  219. /*
  220. * Checkup routine
  221. */
  222. int ecdh_self_test( int verbose )
  223. {
  224. ((void) verbose );
  225. return( 0 );
  226. }
  227. #endif /* POLARSSL_SELF_TEST */
  228. #endif /* POLARSSL_ECDH_C */