crypto_curve25519.c 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /* Copyright (c) 2012, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /* Wrapper code for a curve25519 implementation. */
  4. #define CRYPTO_CURVE25519_PRIVATE
  5. #include "orconfig.h"
  6. #include "crypto.h"
  7. #include "crypto_curve25519.h"
  8. #include "util.h"
  9. /* ==============================
  10. Part 1: wrap a suitable curve25519 implementation as curve25519_impl
  11. ============================== */
  12. #ifdef USE_CURVE25519_DONNA
  13. int curve25519_donna(uint8_t *mypublic,
  14. const uint8_t *secret, const uint8_t *basepoint);
  15. #endif
  16. #ifdef USE_CURVE25519_NACL
  17. #include <crypto_scalarmult_curve25519.h>
  18. #endif
  19. int
  20. curve25519_impl(uint8_t *output, const uint8_t *secret,
  21. const uint8_t *basepoint)
  22. {
  23. #ifdef USE_CURVE25519_DONNA
  24. return curve25519_donna(output, secret, basepoint);
  25. #elif defined(USE_CURVE25519_NACL)
  26. return crypto_scalarmult_curve25519(output, secret, basepoint);
  27. #else
  28. #error "No implementation of curve25519 is available."
  29. #endif
  30. }
  31. /* ==============================
  32. Part 2: Wrap curve25519_impl with some convenience types and functions.
  33. ============================== */
  34. /**
  35. * Return true iff a curve25519_public_key_t seems valid. (It's not necessary
  36. * to see if the point is on the curve, since the twist is also secure, but we
  37. * do need to make sure that it isn't the point at infinity.) */
  38. int
  39. curve25519_public_key_is_ok(const curve25519_public_key_t *key)
  40. {
  41. static const uint8_t zero[] =
  42. "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  43. "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
  44. return tor_memneq(key->public_key, zero, CURVE25519_PUBKEY_LEN);
  45. }
  46. /** Generate a new keypair and return the secret key. If <b>extra_strong</b>
  47. * is true, this key is possibly going to get used more than once, so
  48. * use a better-than-usual RNG. */
  49. void
  50. curve25519_secret_key_generate(curve25519_secret_key_t *key_out,
  51. int extra_strong)
  52. {
  53. uint8_t k_tmp[CURVE25519_SECKEY_LEN];
  54. crypto_rand((char*)key_out->secret_key, CURVE25519_SECKEY_LEN);
  55. if (extra_strong && !crypto_strongest_rand(k_tmp, CURVE25519_SECKEY_LEN)) {
  56. /* If they asked for extra-strong entropy and we have some, use it as an
  57. * HMAC key to improve not-so-good entopy rather than using it directly,
  58. * just in case the extra-strong entropy is less amazing than we hoped. */
  59. crypto_hmac_sha256((char *)key_out->secret_key,
  60. (const char *)k_tmp, sizeof(k_tmp),
  61. (const char *)key_out->secret_key, CURVE25519_SECKEY_LEN);
  62. }
  63. memwipe(k_tmp, 0, sizeof(k_tmp));
  64. key_out->secret_key[0] &= 248;
  65. key_out->secret_key[31] &= 127;
  66. key_out->secret_key[31] |= 64;
  67. }
  68. void
  69. curve25519_public_key_generate(curve25519_public_key_t *key_out,
  70. const curve25519_secret_key_t *seckey)
  71. {
  72. static const uint8_t basepoint[32] = {9};
  73. curve25519_impl(key_out->public_key, seckey->secret_key, basepoint);
  74. }
  75. /** Perform the curve25519 ECDH handshake with <b>skey</b> and <b>pkey</b>,
  76. * writing CURVE25519_OUTPUT_LEN bytes of output into <b>output</b>. */
  77. void
  78. curve25519_handshake(uint8_t *output,
  79. const curve25519_secret_key_t *skey,
  80. const curve25519_public_key_t *pkey)
  81. {
  82. curve25519_impl(output, skey->secret_key, pkey->public_key);
  83. }