tor  0.4.0.1-alpha
crypto_pwbox.c
Go to the documentation of this file.
1 /* Copyright (c) 2014-2019, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
11 #include <string.h>
12 
13 #include "lib/arch/bytes.h"
20 #include "lib/ctime/di_ops.h"
21 #include "lib/intmath/muldiv.h"
22 #include "trunnel/pwbox.h"
23 #include "lib/log/util_bug.h"
24 
25 /* 8 bytes "TORBOX00"
26  1 byte: header len (H)
27  H bytes: header, denoting secret key algorithm.
28  16 bytes: IV
29  Round up to multiple of 128 bytes, then encrypt:
30  4 bytes: data len
31  data
32  zeros
33  32 bytes: HMAC-SHA256 of all previous bytes.
34 */
35 
36 #define MAX_OVERHEAD (S2K_MAXLEN + 8 + 1 + 32 + CIPHER_IV_LEN)
37 
46 int
47 crypto_pwbox(uint8_t **out, size_t *outlen_out,
48  const uint8_t *input, size_t input_len,
49  const char *secret, size_t secret_len,
50  unsigned s2k_flags)
51 {
52  uint8_t *result = NULL, *encrypted_portion;
53  size_t encrypted_len = 128 * CEIL_DIV(input_len+4, 128);
54  ssize_t result_len;
55  int spec_len;
56  uint8_t keys[CIPHER_KEY_LEN + DIGEST256_LEN];
57  pwbox_encoded_t *enc = NULL;
58  ssize_t enc_len;
59 
60  crypto_cipher_t *cipher;
61  int rv;
62 
63  enc = pwbox_encoded_new();
64  tor_assert(enc);
65 
66  pwbox_encoded_setlen_skey_header(enc, S2K_MAXLEN);
67 
69  pwbox_encoded_getarray_skey_header(enc),
70  S2K_MAXLEN,
71  s2k_flags);
72  if (BUG(spec_len < 0 || spec_len > S2K_MAXLEN))
73  goto err;
74  pwbox_encoded_setlen_skey_header(enc, spec_len);
75  enc->header_len = spec_len;
76 
77  crypto_rand((char*)enc->iv, sizeof(enc->iv));
78 
79  pwbox_encoded_setlen_data(enc, encrypted_len);
80  encrypted_portion = pwbox_encoded_getarray_data(enc);
81 
82  set_uint32(encrypted_portion, tor_htonl((uint32_t)input_len));
83  memcpy(encrypted_portion+4, input, input_len);
84 
85  /* Now that all the data is in position, derive some keys, encrypt, and
86  * digest */
87  const int s2k_rv = secret_to_key_derivekey(keys, sizeof(keys),
88  pwbox_encoded_getarray_skey_header(enc),
89  spec_len,
90  secret, secret_len);
91  if (BUG(s2k_rv < 0))
92  goto err;
93 
94  cipher = crypto_cipher_new_with_iv((char*)keys, (char*)enc->iv);
95  crypto_cipher_crypt_inplace(cipher, (char*)encrypted_portion, encrypted_len);
96  crypto_cipher_free(cipher);
97 
98  result_len = pwbox_encoded_encoded_len(enc);
99  if (BUG(result_len < 0))
100  goto err;
101  result = tor_malloc(result_len);
102  enc_len = pwbox_encoded_encode(result, result_len, enc);
103  if (BUG(enc_len < 0))
104  goto err;
105  tor_assert(enc_len == result_len);
106 
107  crypto_hmac_sha256((char*) result + result_len - 32,
108  (const char*)keys + CIPHER_KEY_LEN,
110  (const char*)result,
111  result_len - 32);
112 
113  *out = result;
114  *outlen_out = result_len;
115  rv = 0;
116  goto out;
117 
118  /* LCOV_EXCL_START
119 
120  This error case is often unreachable if we're correctly coded, unless
121  somebody adds a new error case somewhere, or unless you're building
122  without scrypto support.
123 
124  - make_specifier can't fail, unless S2K_MAX_LEN is too short.
125  - secret_to_key_derivekey can't really fail unless we're missing
126  scrypt, or the underlying function fails, or we pass it a bogus
127  algorithm or parameters.
128  - pwbox_encoded_encoded_len can't fail unless we're using trunnel
129  incorrectly.
130  - pwbox_encoded_encode can't fail unless we're using trunnel wrong,
131  or it's buggy.
132  */
133  err:
134  tor_free(result);
135  rv = -1;
136  /* LCOV_EXCL_STOP */
137  out:
138  pwbox_encoded_free(enc);
139  memwipe(keys, 0, sizeof(keys));
140  return rv;
141 }
142 
152 int
153 crypto_unpwbox(uint8_t **out, size_t *outlen_out,
154  const uint8_t *inp, size_t input_len,
155  const char *secret, size_t secret_len)
156 {
157  uint8_t *result = NULL;
158  const uint8_t *encrypted;
159  uint8_t keys[CIPHER_KEY_LEN + DIGEST256_LEN];
160  uint8_t hmac[DIGEST256_LEN];
161  uint32_t result_len;
162  size_t encrypted_len;
163  crypto_cipher_t *cipher = NULL;
164  int rv = UNPWBOX_CORRUPTED;
165  ssize_t got_len;
166 
167  pwbox_encoded_t *enc = NULL;
168 
169  got_len = pwbox_encoded_parse(&enc, inp, input_len);
170  if (got_len < 0 || (size_t)got_len != input_len)
171  goto err;
172 
173  /* Now derive the keys and check the hmac. */
174  if (secret_to_key_derivekey(keys, sizeof(keys),
175  pwbox_encoded_getarray_skey_header(enc),
176  pwbox_encoded_getlen_skey_header(enc),
177  secret, secret_len) < 0)
178  goto err;
179 
180  crypto_hmac_sha256((char *)hmac,
181  (const char*)keys + CIPHER_KEY_LEN, DIGEST256_LEN,
182  (const char*)inp, input_len - DIGEST256_LEN);
183 
184  if (tor_memneq(hmac, enc->hmac, DIGEST256_LEN)) {
185  rv = UNPWBOX_BAD_SECRET;
186  goto err;
187  }
188 
189  /* How long is the plaintext? */
190  encrypted = pwbox_encoded_getarray_data(enc);
191  encrypted_len = pwbox_encoded_getlen_data(enc);
192  if (encrypted_len < 4)
193  goto err;
194 
195  cipher = crypto_cipher_new_with_iv((char*)keys, (char*)enc->iv);
196  crypto_cipher_decrypt(cipher, (char*)&result_len, (char*)encrypted, 4);
197  result_len = tor_ntohl(result_len);
198  if (encrypted_len < result_len + 4)
199  goto err;
200 
201  /* Allocate a buffer and decrypt */
202  result = tor_malloc_zero(result_len);
203  crypto_cipher_decrypt(cipher, (char*)result, (char*)encrypted+4, result_len);
204 
205  *out = result;
206  *outlen_out = result_len;
207 
208  rv = UNPWBOX_OKAY;
209  goto out;
210 
211  err:
212  tor_free(result);
213 
214  out:
215  crypto_cipher_free(cipher);
216  pwbox_encoded_free(enc);
217  memwipe(keys, 0, sizeof(keys));
218  return rv;
219 }
void crypto_cipher_crypt_inplace(crypto_cipher_t *env, char *buf, size_t len)
Common functions for using (pseudo-)random number generators.
Headers for di_ops.c.
Header for crypto_pwbox.c.
Headers for crypto_cipher.c.
#define tor_free(p)
Definition: malloc.h:52
#define CIPHER_KEY_LEN
Definition: crypto_cipher.h:22
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:57
void crypto_hmac_sha256(char *hmac_out, const char *key, size_t key_len, const char *msg, size_t msg_len)
static void set_uint32(void *cp, uint32_t v)
Definition: bytes.h:82
#define DIGEST256_LEN
Definition: digest_sizes.h:23
Common functions for cryptographic routines.
tor_assert(buffer)
Header for crypto_s2k.c.
int crypto_cipher_decrypt(crypto_cipher_t *env, char *to, const char *from, size_t fromlen)
int crypto_unpwbox(uint8_t **out, size_t *outlen_out, const uint8_t *inp, size_t input_len, const char *secret, size_t secret_len)
Definition: crypto_pwbox.c:153
Headers for crypto_digest.c.
Header for muldiv.c.
crypto_cipher_t * crypto_cipher_new_with_iv(const char *key, const char *iv)
Definition: crypto_cipher.c:44
Inline functions for reading and writing multibyte values from the middle of strings, and for manipulating byte order.
int secret_to_key_derivekey(uint8_t *key_out, size_t key_out_len, const uint8_t *spec, size_t spec_len, const char *secret, size_t secret_len)
Definition: crypto_s2k.c:370
int secret_to_key_make_specifier(uint8_t *buf, size_t buf_len, unsigned flags)
Definition: crypto_s2k.c:405
Macros to manage assertions, fatal and non-fatal.
#define S2K_MAXLEN
Definition: crypto_s2k.h:36
int crypto_pwbox(uint8_t **out, size_t *outlen_out, const uint8_t *input, size_t input_len, const char *secret, size_t secret_len, unsigned s2k_flags)
Definition: crypto_pwbox.c:47