master hovercats/oakiss / pkg / transmission / patch / 0001-Use-BearSSL-for-SHA1-and-DH-add-fallback-RC4.patch
  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