1From eb8e399417b22099b5a52e5fb468979e44486e73 Mon Sep 17 00:00:00 2001
2From: Michael Forney <mforney@mforney.org>
3Date: Sun, 17 Nov 2019 01:27:04 -0800
4Subject: [PATCH] Use BearSSL for SHA1 and DH, add fallback RC4
5
6---
7 libtransmission/crypto-utils-bearssl.c | 234 ++++++++++++++++++++++++
8 libtransmission/crypto-utils-fallback.c | 77 ++++++++
9 2 files changed, 311 insertions(+)
10 create mode 100644 libtransmission/crypto-utils-bearssl.c
11
12diff --git a/libtransmission/crypto-utils-bearssl.c b/libtransmission/crypto-utils-bearssl.c
13new file mode 100644
14index 000000000..5672a48df
15--- /dev/null
16+++ b/libtransmission/crypto-utils-bearssl.c
17@@ -0,0 +1,234 @@
18+#include <assert.h>
19+#include <stdlib.h>
20+
21+#include <bearssl.h>
22+
23+#include "crypto-utils.h"
24+
25+#define TR_CRYPTO_DH_SECRET_FALLBACK
26+#define TR_CRYPTO_X509_FALLBACK
27+#define TR_CRYPTO_RC4_FALLBACK
28+#include "crypto-utils-fallback.c"
29+
30+/***
31+****
32+***/
33+
34+#define MY_NAME "tr_crypto_utils"
35+
36+tr_sha1_ctx_t tr_sha1_init(void)
37+{
38+ br_sha1_context * ctx;
39+
40+ ctx = tr_malloc(sizeof (*ctx));
41+ if (!ctx)
42+ {
43+ return NULL;
44+ }
45+
46+ br_sha1_init(ctx);
47+
48+ return ctx;
49+}
50+
51+bool tr_sha1_update(tr_sha1_ctx_t handle, void const* data, size_t data_length)
52+{
53+ TR_ASSERT(handle != NULL);
54+
55+ if (data_length == 0)
56+ {
57+ return true;
58+ }
59+
60+ TR_ASSERT(data != NULL);
61+
62+ br_sha1_update(handle, data, data_length);
63+
64+ return true;
65+}
66+
67+bool tr_sha1_final(tr_sha1_ctx_t handle, uint8_t* hash)
68+{
69+ if (hash != NULL)
70+ {
71+ TR_ASSERT(handle != NULL);
72+ br_sha1_out(handle, hash);
73+ }
74+
75+ tr_free(handle);
76+ return true;
77+}
78+
79+/***
80+****
81+***/
82+
83+typedef struct {
84+ uint8_t const* prime_num;
85+ size_t prime_num_length;
86+ uint8_t const* generator_num;
87+ size_t generator_num_length;
88+ uint8_t* private_key;
89+ size_t private_key_length;
90+} DH;
91+
92+tr_dh_ctx_t tr_dh_new(uint8_t const* prime_num, size_t prime_num_length, uint8_t const* generator_num,
93+ size_t generator_num_length)
94+{
95+ DH* handle;
96+
97+ TR_ASSERT(prime_num != NULL);
98+ TR_ASSERT(generator_num != NULL);
99+ TR_ASSERT(generator_num_length < prime_num_length);
100+
101+ if (generator_num_length > prime_num_length)
102+ {
103+ return NULL;
104+ }
105+
106+ handle = tr_malloc(sizeof(*handle));
107+ if (handle == NULL)
108+ {
109+ return NULL;
110+ }
111+
112+ handle->prime_num = prime_num;
113+ handle->prime_num_length = prime_num_length;
114+ handle->generator_num = generator_num;
115+ handle->generator_num_length = generator_num_length;
116+ handle->private_key = NULL;
117+
118+ return handle;
119+}
120+
121+void
122+tr_dh_free (tr_dh_ctx_t raw_handle)
123+{
124+ DH* handle = raw_handle;
125+
126+ if (handle == NULL)
127+ {
128+ return;
129+ }
130+
131+ tr_free(handle->private_key);
132+ tr_free(handle);
133+}
134+
135+bool tr_dh_make_key(tr_dh_ctx_t raw_handle, size_t private_key_length, uint8_t* public_key, size_t* public_key_length)
136+{
137+ TR_ASSERT(raw_handle != NULL);
138+ TR_ASSERT(public_key != NULL);
139+
140+ DH* handle = raw_handle;
141+ br_rsa_public modexp;
142+ br_rsa_public_key key;
143+ uint8_t* x;
144+ size_t xlen;
145+
146+ modexp = br_rsa_public_get_default();
147+
148+ handle->private_key = tr_malloc(private_key_length);
149+ handle->private_key_length = private_key_length;
150+
151+ if (!handle->private_key)
152+ {
153+ goto fail;
154+ }
155+
156+ if (!tr_rand_buffer(handle->private_key, handle->private_key_length))
157+ {
158+ goto fail;
159+ }
160+
161+ memset(public_key, 0, handle->prime_num_length - handle->generator_num_length);
162+ memcpy(public_key + handle->prime_num_length - handle->generator_num_length, handle->generator_num, handle->generator_num_length);
163+
164+ key.n = (unsigned char*)handle->prime_num;
165+ key.nlen = handle->prime_num_length;
166+ key.e = handle->private_key;
167+ key.elen = handle->private_key_length;
168+
169+ if (!modexp(public_key, handle->prime_num_length, &key))
170+ {
171+ goto fail;
172+ }
173+
174+ *public_key_length = handle->prime_num_length;
175+
176+ return true;
177+
178+fail:
179+ tr_free(handle->private_key);
180+ handle->private_key = NULL;
181+ return false;
182+}
183+
184+tr_dh_secret_t tr_dh_agree(tr_dh_ctx_t raw_handle, uint8_t const* other_public_key, size_t other_public_key_length)
185+{
186+ TR_ASSERT(raw_handle != NULL);
187+ TR_ASSERT(other_public_key != NULL);
188+
189+ DH* handle = raw_handle;
190+ struct tr_dh_secret* ret;
191+ br_rsa_public modexp;
192+ br_rsa_public_key key;
193+ uint8_t* x;
194+ size_t xlen;
195+
196+ if (other_public_key_length > handle->prime_num_length)
197+ {
198+ return NULL;
199+ }
200+
201+ ret = tr_dh_secret_new(handle->prime_num_length);
202+ if (!ret)
203+ {
204+ return NULL;
205+ }
206+
207+ memset(ret->key, 0, ret->key_length - other_public_key_length);
208+ memcpy(ret->key + ret->key_length - other_public_key_length, other_public_key, other_public_key_length);
209+
210+ modexp = br_rsa_public_get_default();
211+
212+ key.n = (unsigned char*)handle->prime_num;
213+ key.nlen = handle->prime_num_length;
214+ key.e = handle->private_key;
215+ key.elen = handle->private_key_length;
216+
217+ if (!modexp(ret->key, ret->key_length, &key))
218+ {
219+ tr_dh_secret_free (ret);
220+ ret = NULL;
221+ }
222+
223+ return ret;
224+}
225+
226+/***
227+****
228+***/
229+
230+bool tr_rand_buffer(void* buffer, size_t length)
231+{
232+ TR_ASSERT(buffer != NULL);
233+
234+ static br_hmac_drbg_context ctx;
235+ static bool init;
236+ br_prng_seeder seeder;
237+
238+ if (!init)
239+ {
240+ br_hmac_drbg_init(&ctx, &br_sha256_vtable, NULL, 0);
241+ seeder = br_prng_seeder_system(NULL);
242+ if (!seeder || !seeder(&ctx.vtable))
243+ {
244+ return false;
245+ }
246+ init = true;
247+ }
248+
249+ br_hmac_drbg_generate(&ctx, buffer, length);
250+ return true;
251+}
252diff --git a/libtransmission/crypto-utils-fallback.c b/libtransmission/crypto-utils-fallback.c
253index c17b54e25..a521956a3 100644
254--- a/libtransmission/crypto-utils-fallback.c
255+++ b/libtransmission/crypto-utils-fallback.c
256@@ -92,3 +92,80 @@ void tr_x509_cert_free(tr_x509_cert_t handle)
257 }
258
259 #endif /* TR_CRYPTO_X509_FALLBACK */
260+
261+#ifdef TR_CRYPTO_RC4_FALLBACK
262+
263+struct tr_rc4
264+{
265+ uint32_t i, j, S[256];
266+};
267+
268+tr_rc4_ctx_t
269+tr_rc4_new (void)
270+{
271+ return tr_malloc (sizeof (struct tr_rc4));
272+}
273+
274+void
275+tr_rc4_free (tr_rc4_ctx_t handle)
276+{
277+ tr_free (handle);
278+}
279+
280+void
281+tr_rc4_set_key (tr_rc4_ctx_t raw_handle,
282+ const uint8_t * key,
283+ size_t key_length)
284+{
285+ struct tr_rc4 * handle = raw_handle;
286+ uint32_t tmp, * S;
287+ size_t i, j;
288+
289+ assert (handle != NULL);
290+ assert (key != NULL);
291+
292+ S = handle->S;
293+ for (i = 0; i < 256; ++i)
294+ S[i] = i;
295+
296+ j = 0;
297+ for (i = 0; i < 256; ++i) {
298+ j = (j + S[i] + key[i % key_length]) & 0xff;
299+ tmp = S[i];
300+ S[i] = S[j];
301+ S[j] = tmp;
302+ }
303+ handle->i = 0;
304+ handle->j = 0;
305+}
306+
307+void
308+tr_rc4_process (tr_rc4_ctx_t raw_handle,
309+ const void * raw_input,
310+ void * raw_output,
311+ size_t length)
312+{
313+ struct tr_rc4 * handle = raw_handle;
314+ const uint8_t * input = raw_input;
315+ uint8_t * output = raw_output;
316+ uint32_t * S, i, j, tmp;
317+
318+ assert (handle != NULL);
319+ assert (handle != NULL);
320+
321+ i = handle->i;
322+ j = handle->j;
323+ S = handle->S;
324+ while (length--) {
325+ i = (i + 1) & 0xff;
326+ j = (j + S[i]) & 0xff;
327+ tmp = S[i];
328+ S[i] = S[j];
329+ S[j] = tmp;
330+ *output++ = S[(S[i] + S[j]) & 0xff] ^ *input++;
331+ }
332+ handle->i = i;
333+ handle->j = j;
334+}
335+
336+#endif /* TR_CRYPTO_RC4_FALLBACK */
337--
3382.26.2
339