crypto_ope.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /* Copyright (c) 2018, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * A rudimentary order-preserving encryption scheme.
  5. *
  6. * To compute the encryption of N, this scheme uses an AES-CTR stream to
  7. * generate M-byte values, and adds the first N of them together. (+1 each to
  8. * insure that the ciphertexts are strictly decreasing.)
  9. *
  10. * We use this for generating onion service revision counters based on the
  11. * current time, without leaking the amount of skew in our view of the current
  12. * time. MUCH more analysis would be needed before using it for anything
  13. * else!
  14. */
  15. #include "orconfig.h"
  16. #include "crypto.h"
  17. #define CRYPTO_OPE_PRIVATE
  18. #include "crypto_ope.h"
  19. /**
  20. * How infrequent should the precomputed values be for this encryption?
  21. * The choice of this value creates a space/time tradeoff.
  22. *
  23. * Note that this value must be a multiple of 16; see
  24. * ope_get_cipher()
  25. */
  26. #define SAMPLE_INTERVAL 1024
  27. /** Number of precomputed samples to make for each OPE key. */
  28. #define N_SAMPLES (OPE_INPUT_MAX / SAMPLE_INTERVAL)
  29. struct crypto_ope_c {
  30. /** An AES key for use with this object. */
  31. uint8_t key[OPE_KEY_LEN];
  32. /** Cached intermediate encryption values at SAMPLE_INTERVAL,
  33. * SAMPLE_INTERVAL*2,...SAMPLE_INTERVAL*N_SAMPLES */
  34. uint64_t samples[N_SAMPLES];
  35. };
  36. /** The type to add up in order to produce our OPE ciphertexts */
  37. typedef uint16_t ope_val_t;
  38. #ifdef WORDS_BIG_ENDIAN
  39. /** Convert an OPE value to little-endian */
  40. static inline ope_val_t
  41. ope_val_to_le(ope_val_t x)
  42. {
  43. return
  44. ((x) >> 8) |
  45. (((x)&0xff) << 8);
  46. }
  47. #else
  48. #define ope_val_to_le(x) (x)
  49. #endif
  50. /**
  51. * Return a new AES256-CTR stream cipher object for <b>ope</b>, ready to yield
  52. * bytes from the stream at position <b>initial_idx</b>.
  53. *
  54. * Note that because the index is converted directly to an IV, it must be a
  55. * multiple of the AES block size (16).
  56. */
  57. STATIC crypto_cipher_t *
  58. ope_get_cipher(const crypto_ope_t *ope, uint32_t initial_idx)
  59. {
  60. uint8_t iv[CIPHER_IV_LEN];
  61. tor_assert((initial_idx & 0xf) == 0);
  62. uint32_t n = htonl(initial_idx >> 4);
  63. memset(iv, 0, sizeof(iv));
  64. memcpy(iv + CIPHER_IV_LEN - sizeof(n), &n, sizeof(n));
  65. return crypto_cipher_new_with_iv_and_bits(ope->key,
  66. iv,
  67. OPE_KEY_LEN * 8);
  68. }
  69. /**
  70. * Retrieve and add the next <b>n</b> values from the stream cipher <b>c</b>,
  71. * and return their sum.
  72. *
  73. * Note that values are taken in little-endian order (for performance on
  74. * prevalent hardware), and are mapped from range 0..2^n-1 to range 1..2^n (so
  75. * that each input encrypts to a different output).
  76. *
  77. * NOTE: this function is not constant-time.
  78. */
  79. STATIC uint64_t
  80. sum_values_from_cipher(crypto_cipher_t *c, size_t n)
  81. {
  82. #define BUFSZ 256
  83. ope_val_t buf[BUFSZ];
  84. uint64_t total = 0;
  85. unsigned i;
  86. while (n >= BUFSZ) {
  87. memset(buf, 0, sizeof(buf));
  88. crypto_cipher_crypt_inplace(c, (char*)buf, BUFSZ*sizeof(ope_val_t));
  89. for (i = 0; i < BUFSZ; ++i) {
  90. total += ope_val_to_le(buf[i]);
  91. total += 1;
  92. }
  93. n -= BUFSZ;
  94. }
  95. memset(buf, 0, n*sizeof(ope_val_t));
  96. crypto_cipher_crypt_inplace(c, (char*)buf, n*sizeof(ope_val_t));
  97. for (i = 0; i < n; ++i) {
  98. total += ope_val_to_le(buf[i]);
  99. total += 1;
  100. }
  101. memset(buf, 0, sizeof(buf));
  102. return total;
  103. }
  104. /**
  105. * Return a new crypto_ope_t object, using the provided 256-bit key.
  106. */
  107. crypto_ope_t *
  108. crypto_ope_new(const uint8_t *key)
  109. {
  110. crypto_ope_t *ope = tor_malloc_zero(sizeof(crypto_ope_t));
  111. memcpy(ope->key, key, OPE_KEY_LEN);
  112. crypto_cipher_t *cipher = ope_get_cipher(ope, 0);
  113. uint64_t v = 0;
  114. int i;
  115. for (i = 0; i < N_SAMPLES; ++i) {
  116. v += sum_values_from_cipher(cipher, SAMPLE_INTERVAL);
  117. ope->samples[i] = v;
  118. }
  119. crypto_cipher_free(cipher);
  120. return ope;
  121. }
  122. /** Free all storage held in <>ope</b>. */
  123. void
  124. crypto_ope_free_(crypto_ope_t *ope)
  125. {
  126. if (!ope)
  127. return;
  128. memwipe(ope, 0, sizeof(*ope));
  129. tor_free(ope);
  130. }
  131. /**
  132. * Return the encrypted value corresponding to <b>input</b>. The input value
  133. * must be in range 1..OPE_INPUT_MAX. Returns UINT64_MAX on an invalid input.
  134. *
  135. * NOTE: this function is not constant-time.
  136. */
  137. uint64_t
  138. crypto_ope_encrypt(const crypto_ope_t *ope, int plaintext)
  139. {
  140. if (plaintext <= 0 || plaintext > OPE_INPUT_MAX)
  141. return UINT64_MAX;
  142. const int sample_idx = (plaintext / SAMPLE_INTERVAL);
  143. const int starting_iv = sample_idx * SAMPLE_INTERVAL;
  144. const int remaining_values = plaintext - starting_iv;
  145. uint64_t v;
  146. if (sample_idx == 0) {
  147. v = 0;
  148. } else {
  149. v = ope->samples[sample_idx - 1];
  150. }
  151. crypto_cipher_t *cipher = ope_get_cipher(ope, starting_iv*sizeof(ope_val_t));
  152. v += sum_values_from_cipher(cipher, remaining_values);
  153. crypto_cipher_free(cipher);
  154. return v;
  155. }