ecdh.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /*
  2. *
  3. * Embedded Linux library
  4. *
  5. * Copyright (C) 2018 Intel Corporation. All rights reserved.
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. */
  22. #ifdef HAVE_CONFIG_H
  23. #include <config.h>
  24. #endif
  25. #include <stdint.h>
  26. #include "private.h"
  27. #include "ecc-private.h"
  28. #include "ecc.h"
  29. #include "ecdh.h"
  30. #include "random.h"
  31. /*
  32. * Some sane maximum for calculating the public key.
  33. */
  34. #define ECDH_MAX_ITERATIONS 20
  35. /*
  36. * IETF draft-jivsov-ecc-compact-00 Section 4.2.1
  37. *
  38. * The following algorithm calculates a key pair {k, Q=k*G=(x,y)}, where k is
  39. * the private key and Q=(x,y) is the public key.
  40. *
  41. * Black box generation:
  42. * 1. Generate a key pair {k, Q=k*G=(x,y)} with KG
  43. * 2. if( y != min(y,p-y) ) goto step 1
  44. * 3. output {k, Q=(x,y)} as a key pair
  45. */
  46. LIB_EXPORT bool l_ecdh_generate_key_pair(const struct l_ecc_curve *curve,
  47. struct l_ecc_scalar **out_private,
  48. struct l_ecc_point **out_public)
  49. {
  50. bool compliant = false;
  51. int iter = 0;
  52. uint64_t p2[L_ECC_MAX_DIGITS];
  53. _ecc_calculate_p2(curve, p2);
  54. *out_public = l_ecc_point_new(curve);
  55. while (!compliant && iter++ < ECDH_MAX_ITERATIONS) {
  56. *out_private = l_ecc_scalar_new_random(curve);
  57. _ecc_point_mult(*out_public, &curve->g, (*out_private)->c,
  58. NULL, curve->p);
  59. /* ensure public key is compliant */
  60. if (_vli_cmp((*out_public)->y, p2, curve->ndigits) >= 0) {
  61. compliant = true;
  62. break;
  63. }
  64. l_ecc_scalar_free(*out_private);
  65. }
  66. if (!compliant) {
  67. l_ecc_point_free(*out_public);
  68. return false;
  69. }
  70. return true;
  71. }
  72. LIB_EXPORT bool l_ecdh_generate_shared_secret(
  73. const struct l_ecc_scalar *private_key,
  74. const struct l_ecc_point *other_public,
  75. struct l_ecc_scalar **secret)
  76. {
  77. const struct l_ecc_curve *curve = private_key->curve;
  78. struct l_ecc_scalar *z;
  79. struct l_ecc_point *product;
  80. z = l_ecc_scalar_new_random(curve);
  81. product = l_ecc_point_new(curve);
  82. _ecc_point_mult(product, other_public, private_key->c, z->c, curve->p);
  83. *secret = _ecc_constant_new(curve, product->x, curve->ndigits * 8);
  84. l_ecc_point_free(product);
  85. l_ecc_scalar_free(z);
  86. return true;
  87. }