tor  0.4.2.0-alpha-dev
crypto_ope.c
1 /* Copyright (c) 2018-2019, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
17 #include "orconfig.h"
18 
19 #define CRYPTO_OPE_PRIVATE
20 #include "lib/crypt_ops/crypto_ope.h"
23 #include "lib/log/util_bug.h"
24 #include "lib/malloc/malloc.h"
25 #include "lib/arch/bytes.h"
26 
27 #include <string.h>
28 
36 #define SAMPLE_INTERVAL 1024
37 
38 #define N_SAMPLES (OPE_INPUT_MAX / SAMPLE_INTERVAL)
39 
40 struct crypto_ope_t {
42  uint8_t key[OPE_KEY_LEN];
45  uint64_t samples[N_SAMPLES];
46 };
47 
49 typedef uint16_t ope_val_t;
50 
51 #ifdef WORDS_BIGENDIAN
52 
53 static inline ope_val_t
54 ope_val_from_le(ope_val_t x)
55 {
56  return
57  ((x) >> 8) |
58  (((x)&0xff) << 8);
59 }
60 #else /* !(defined(WORDS_BIGENDIAN)) */
61 #define ope_val_from_le(x) (x)
62 #endif /* defined(WORDS_BIGENDIAN) */
63 
71 STATIC crypto_cipher_t *
72 ope_get_cipher(const crypto_ope_t *ope, uint32_t initial_idx)
73 {
74  uint8_t iv[CIPHER_IV_LEN];
75  tor_assert((initial_idx & 0xf) == 0);
76  uint32_t n = tor_htonl(initial_idx >> 4);
77  memset(iv, 0, sizeof(iv));
78  memcpy(iv + CIPHER_IV_LEN - sizeof(n), &n, sizeof(n));
79 
81  iv,
82  OPE_KEY_LEN * 8);
83 }
84 
95 STATIC uint64_t
96 sum_values_from_cipher(crypto_cipher_t *c, size_t n)
97 {
98 #define BUFSZ 256
99  ope_val_t buf[BUFSZ];
100  uint64_t total = 0;
101  unsigned i;
102  while (n >= BUFSZ) {
103  memset(buf, 0, sizeof(buf));
104  crypto_cipher_crypt_inplace(c, (char*)buf, BUFSZ*sizeof(ope_val_t));
105 
106  for (i = 0; i < BUFSZ; ++i) {
107  total += ope_val_from_le(buf[i]);
108  total += 1;
109  }
110  n -= BUFSZ;
111  }
112 
113  memset(buf, 0, n*sizeof(ope_val_t));
114  crypto_cipher_crypt_inplace(c, (char*)buf, n*sizeof(ope_val_t));
115  for (i = 0; i < n; ++i) {
116  total += ope_val_from_le(buf[i]);
117  total += 1;
118  }
119 
120  memset(buf, 0, sizeof(buf));
121  return total;
122 }
123 
127 crypto_ope_t *
128 crypto_ope_new(const uint8_t *key)
129 {
130  crypto_ope_t *ope = tor_malloc_zero(sizeof(crypto_ope_t));
131  memcpy(ope->key, key, OPE_KEY_LEN);
132 
133  crypto_cipher_t *cipher = ope_get_cipher(ope, 0);
134 
135  uint64_t v = 0;
136  int i;
137  for (i = 0; i < N_SAMPLES; ++i) {
138  v += sum_values_from_cipher(cipher, SAMPLE_INTERVAL);
139  ope->samples[i] = v;
140  }
141 
142  crypto_cipher_free(cipher);
143  return ope;
144 }
145 
147 void
148 crypto_ope_free_(crypto_ope_t *ope)
149 {
150  if (!ope)
151  return;
152  memwipe(ope, 0, sizeof(*ope));
153  tor_free(ope);
154 }
155 
163 uint64_t
164 crypto_ope_encrypt(const crypto_ope_t *ope, int plaintext)
165 {
166  if (plaintext <= 0 || plaintext > OPE_INPUT_MAX)
167  return CRYPTO_OPE_ERROR;
168 
169  const int sample_idx = (plaintext / SAMPLE_INTERVAL);
170  const int starting_iv = sample_idx * SAMPLE_INTERVAL;
171  const int remaining_values = plaintext - starting_iv;
172  uint64_t v;
173  if (sample_idx == 0) {
174  v = 0;
175  } else {
176  v = ope->samples[sample_idx - 1];
177  }
178  crypto_cipher_t *cipher = ope_get_cipher(ope, starting_iv*sizeof(ope_val_t));
179 
180  v += sum_values_from_cipher(cipher, remaining_values);
181 
182  crypto_cipher_free(cipher);
183 
184  return v;
185 }
uint8_t key[OPE_KEY_LEN]
Definition: crypto_ope.c:42
void crypto_cipher_crypt_inplace(crypto_cipher_t *env, char *buf, size_t len)
Headers for crypto_cipher.c.
uint64_t samples[N_SAMPLES]
Definition: crypto_ope.c:45
#define tor_free(p)
Definition: malloc.h:52
Headers for util_malloc.c.
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:57
#define CIPHER_IV_LEN
Definition: crypto_cipher.h:24
Common functions for cryptographic routines.
tor_assert(buffer)
Inline functions for reading and writing multibyte values from the middle of strings,...
crypto_cipher_t * crypto_cipher_new_with_iv_and_bits(const uint8_t *key, const uint8_t *iv, int bits)
Definition: crypto_cipher.c:29
Macros to manage assertions, fatal and non-fatal.