source: trunk/libtransmission/crypto-utils-openssl.c

Last change on this file was 14640, checked in by mikedld, 5 years ago

Get rid of some more warnings

  • Property svn:keywords set to Date Rev Author Id
File size: 7.0 KB
Line 
1/*
2 * This file Copyright (C) 2007-2014 Mnemosyne LLC
3 *
4 * It may be used under the GNU GPL versions 2 or 3
5 * or any future license endorsed by Mnemosyne LLC.
6 *
7 * $Id: crypto-utils-openssl.c 14640 2015-12-28 23:53:55Z mikedld $
8 */
9
10#ifdef __APPLE__
11 /* OpenSSL "deprecated" as of OS X 10.7, but we still use it */
12 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
13#endif
14
15#include <assert.h>
16
17#include <openssl/bn.h>
18#include <openssl/dh.h>
19#include <openssl/err.h>
20#include <openssl/evp.h>
21#include <openssl/rand.h>
22#include <openssl/opensslv.h>
23
24#include "transmission.h"
25#include "crypto-utils.h"
26#include "log.h"
27#include "utils.h"
28
29#define TR_CRYPTO_DH_SECRET_FALLBACK
30#include "crypto-utils-fallback.c"
31
32/***
33****
34***/
35
36#define MY_NAME "tr_crypto_utils"
37
38static void
39log_openssl_error (const char * file,
40                   int          line)
41{
42  const unsigned long error_code = ERR_get_error ();
43
44  if (tr_logLevelIsActive (TR_LOG_ERROR))
45    {
46      char buf[512];
47
48#ifndef TR_LIGHTWEIGHT
49      static bool strings_loaded = false;
50      if (!strings_loaded)
51        {
52          ERR_load_crypto_strings ();
53          strings_loaded = true;
54        }
55#endif
56
57      ERR_error_string_n (error_code, buf, sizeof (buf));
58      tr_logAddMessage (file, line, TR_LOG_ERROR, MY_NAME, "OpenSSL error: %s", buf);
59    }
60}
61
62#define log_error() log_openssl_error(__FILE__, __LINE__)
63
64static bool
65check_openssl_result (int          result,
66                      int          expected_result,
67                      bool         expected_equal,
68                      const char * file,
69                      int          line)
70{
71  const bool ret = (result == expected_result) == expected_equal;
72  if (!ret)
73    log_openssl_error (file, line);
74  return ret;
75}
76
77#define check_result(result) check_openssl_result ((result), 1, true, __FILE__, __LINE__)
78#define check_result_eq(result, x_result) check_openssl_result ((result), (x_result), true, __FILE__, __LINE__)
79#define check_result_neq(result, x_result) check_openssl_result ((result), (x_result), false, __FILE__, __LINE__)
80
81static bool
82check_openssl_pointer (void       * pointer,
83                       const char * file,
84                       int          line)
85{
86  const bool ret = pointer != NULL;
87  if (!ret)
88    log_openssl_error (file, line);
89  return ret;
90}
91
92#define check_pointer(pointer) check_openssl_pointer ((pointer), __FILE__, __LINE__)
93
94/***
95****
96***/
97
98tr_sha1_ctx_t
99tr_sha1_init (void)
100{
101  EVP_MD_CTX * handle = EVP_MD_CTX_create ();
102
103  if (check_result (EVP_DigestInit_ex (handle, EVP_sha1 (), NULL)))
104    return handle;
105
106  EVP_MD_CTX_destroy (handle);
107  return NULL;
108}
109
110bool
111tr_sha1_update (tr_sha1_ctx_t   handle,
112                const void    * data,
113                size_t          data_length)
114{
115  assert (handle != NULL);
116
117  if (data_length == 0)
118    return true;
119
120  assert (data != NULL);
121
122  return check_result (EVP_DigestUpdate (handle, data, data_length));
123}
124
125bool
126tr_sha1_final (tr_sha1_ctx_t   handle,
127               uint8_t       * hash)
128{
129  bool ret = true;
130
131  if (hash != NULL)
132    {
133      unsigned int hash_length;
134
135      assert (handle != NULL);
136
137      ret = check_result (EVP_DigestFinal_ex (handle, hash, &hash_length));
138
139      assert (!ret || hash_length == SHA_DIGEST_LENGTH);
140    }
141
142  EVP_MD_CTX_destroy (handle);
143  return ret;
144}
145
146/***
147****
148***/
149
150#if OPENSSL_VERSION_NUMBER < 0x0090802fL
151
152static EVP_CIPHER_CTX *
153openssl_evp_cipher_context_new (void)
154{
155  EVP_CIPHER_CTX * handle = tr_new (EVP_CIPHER_CTX, 1);
156  if (handle != NULL)
157    EVP_CIPHER_CTX_init (handle);
158  return handle;
159}
160
161static void
162openssl_evp_cipher_context_free (EVP_CIPHER_CTX * handle)
163{
164  if (handle == NULL)
165    return;
166
167  EVP_CIPHER_CTX_cleanup (handle);
168  tr_free (handle);
169}
170
171#define EVP_CIPHER_CTX_new() openssl_evp_cipher_context_new ()
172#define EVP_CIPHER_CTX_free(x) openssl_evp_cipher_context_free ((x))
173
174#endif
175
176tr_rc4_ctx_t
177tr_rc4_new (void)
178{
179  EVP_CIPHER_CTX * handle = EVP_CIPHER_CTX_new ();
180
181  if (check_result (EVP_CipherInit_ex (handle, EVP_rc4 (), NULL, NULL, NULL, -1)))
182    return handle;
183
184  EVP_CIPHER_CTX_free (handle);
185  return NULL;
186}
187
188void
189tr_rc4_free (tr_rc4_ctx_t handle)
190{
191  if (handle == NULL)
192    return;
193
194  EVP_CIPHER_CTX_free (handle);
195}
196
197void
198tr_rc4_set_key (tr_rc4_ctx_t    handle,
199                const uint8_t * key,
200                size_t          key_length)
201{
202  assert (handle != NULL);
203  assert (key != NULL);
204
205  if (!check_result (EVP_CIPHER_CTX_set_key_length (handle, key_length)))
206    return;
207  check_result (EVP_CipherInit_ex (handle, NULL, NULL, key, NULL, -1));
208}
209
210void
211tr_rc4_process (tr_rc4_ctx_t   handle,
212                const void   * input,
213                void         * output,
214                size_t         length)
215{
216  int output_length;
217
218  assert (handle != NULL);
219
220  if (length == 0)
221    return;
222
223  assert (input != NULL);
224  assert (output != NULL);
225
226  check_result (EVP_CipherUpdate (handle, output, &output_length, input, length));
227}
228
229/***
230****
231***/
232
233tr_dh_ctx_t
234tr_dh_new (const uint8_t * prime_num,
235           size_t          prime_num_length,
236           const uint8_t * generator_num,
237           size_t          generator_num_length)
238{
239  DH * handle = DH_new ();
240
241  assert (prime_num != NULL);
242  assert (generator_num != NULL);
243
244  if (!check_pointer (handle->p = BN_bin2bn (prime_num, prime_num_length, NULL)) ||
245      !check_pointer (handle->g = BN_bin2bn (generator_num, generator_num_length, NULL)))
246    {
247      DH_free (handle);
248      handle = NULL;
249    }
250
251  return handle;
252}
253
254void
255tr_dh_free (tr_dh_ctx_t handle)
256{
257  if (handle == NULL)
258    return;
259
260  DH_free (handle);
261}
262
263bool
264tr_dh_make_key (tr_dh_ctx_t   raw_handle,
265                size_t        private_key_length,
266                uint8_t     * public_key,
267                size_t      * public_key_length)
268{
269  DH * handle = raw_handle;
270  int dh_size, my_public_key_length;
271
272  assert (handle != NULL);
273  assert (public_key != NULL);
274
275  handle->length = private_key_length * 8;
276
277  if (!check_result (DH_generate_key (handle)))
278    return false;
279
280  my_public_key_length = BN_bn2bin (handle->pub_key, public_key);
281  dh_size = DH_size (handle);
282
283  tr_dh_align_key (public_key, my_public_key_length, dh_size);
284
285  if (public_key_length != NULL)
286    *public_key_length = dh_size;
287
288  return true;
289}
290
291tr_dh_secret_t
292tr_dh_agree (tr_dh_ctx_t     handle,
293             const uint8_t * other_public_key,
294             size_t          other_public_key_length)
295{
296  struct tr_dh_secret * ret;
297  int dh_size, secret_key_length;
298  BIGNUM * other_key;
299
300  assert (handle != NULL);
301  assert (other_public_key != NULL);
302
303  if (!check_pointer (other_key = BN_bin2bn (other_public_key, other_public_key_length, NULL)))
304    return NULL;
305
306  dh_size = DH_size (handle);
307  ret = tr_dh_secret_new (dh_size);
308
309  secret_key_length = DH_compute_key (ret->key, other_key, handle);
310  if (check_result_neq (secret_key_length, -1))
311    {
312      tr_dh_secret_align (ret, secret_key_length);
313    }
314  else
315    {
316      tr_dh_secret_free (ret);
317      ret = NULL;
318    }
319
320  BN_free (other_key);
321  return ret;
322}
323
324/***
325****
326***/
327
328bool
329tr_rand_buffer (void   * buffer,
330                size_t   length)
331{
332  assert (buffer != NULL);
333
334  return check_result (RAND_bytes (buffer, (int) length));
335}
Note: See TracBrowser for help on using the repository browser.