Tor 0.4.9.0-alpha-dev
crypto_pwbox.c
Go to the documentation of this file.
1/* Copyright (c) 2014-2021, The Tor Project, Inc. */
2/* See LICENSE for licensing information */
3
4/**
5 * \file crypto_pwbox.c
6 *
7 * \brief Code for encrypting secrets in a password-protected form and saving
8 * them to disk.
9 */
10
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
38/**
39 * Make an authenticated passphrase-encrypted blob to encode the
40 * <b>input_len</b> bytes in <b>input</b> using the passphrase
41 * <b>secret</b> of <b>secret_len</b> bytes. Allocate a new chunk of memory
42 * to hold the encrypted data, and store a pointer to that memory in
43 * *<b>out</b>, and its size in <b>outlen_out</b>. Use <b>s2k_flags</b> as an
44 * argument to the passphrase-hashing function.
45 */
46int
47crypto_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),
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
143/**
144 * Try to decrypt the passphrase-encrypted blob of <b>input_len</b> bytes in
145 * <b>input</b> using the passphrase <b>secret</b> of <b>secret_len</b> bytes.
146 * On success, return 0 and allocate a new chunk of memory to hold the
147 * decrypted data, and store a pointer to that memory in *<b>out</b>, and its
148 * size in <b>outlen_out</b>. On failure, return UNPWBOX_BAD_SECRET if
149 * the passphrase might have been wrong, and UNPWBOX_CORRUPT if the object is
150 * definitely corrupt.
151 */
152int
153crypto_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}
Inline functions for reading and writing multibyte values from the middle of strings,...
static uint32_t tor_htonl(uint32_t a)
Definition: bytes.h:163
static uint32_t tor_ntohl(uint32_t a)
Definition: bytes.h:177
static void set_uint32(void *cp, uint32_t v)
Definition: bytes.h:87
void crypto_cipher_crypt_inplace(crypto_cipher_t *env, char *buf, size_t len)
crypto_cipher_t * crypto_cipher_new_with_iv(const char *key, const char *iv)
Definition: crypto_cipher.c:44
int crypto_cipher_decrypt(crypto_cipher_t *env, char *to, const char *from, size_t fromlen)
Headers for crypto_cipher.c.
#define CIPHER_KEY_LEN
Definition: crypto_cipher.h:22
Headers for crypto_digest.c.
void crypto_hmac_sha256(char *hmac_out, const char *key, size_t key_len, const char *msg, size_t msg_len)
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
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
Header for crypto_pwbox.c.
void crypto_rand(char *to, size_t n)
Definition: crypto_rand.c:479
Common functions for using (pseudo-)random number generators.
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:372
int secret_to_key_make_specifier(uint8_t *buf, size_t buf_len, unsigned flags)
Definition: crypto_s2k.c:407
Header for crypto_s2k.c.
#define S2K_MAXLEN
Definition: crypto_s2k.h:36
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:55
Common functions for cryptographic routines.
Headers for di_ops.c.
#define tor_memneq(a, b, sz)
Definition: di_ops.h:21
#define DIGEST256_LEN
Definition: digest_sizes.h:23
#define tor_free(p)
Definition: malloc.h:56
Header for muldiv.c.
Macros to manage assertions, fatal and non-fatal.
#define tor_assert(expr)
Definition: util_bug.h:103