crypto.c 62.8 KB
Newer Older
1
/* Copyright (c) 2001, Matej Pfajfar.
Roger Dingledine's avatar
Roger Dingledine committed
2
 * Copyright (c) 2001-2004, Roger Dingledine.
3
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4
 * Copyright (c) 2007-2008, The Tor Project, Inc. */
5
6
/* See LICENSE for licensing information */
/* $Id$ */
7
8
const char crypto_c_id[] =
  "$Id$";
9

Nick Mathewson's avatar
Nick Mathewson committed
10
11
/**
 * \file crypto.c
12
13
 * \brief Wrapper functions to present a consistent interface to
 * public-key and symmetric cryptography operations from OpenSSL.
Nick Mathewson's avatar
Nick Mathewson committed
14
15
 **/

16
#include "orconfig.h"
17

18
19
20
21
22
23
#ifdef MS_WINDOWS
#define WIN32_WINNT 0x400
#define _WIN32_WINNT 0x400
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <wincrypt.h>
24
25
26
/* Windows defines this; so does openssl 0.9.8h and later. We don't actually
 * use either definition. */
#undef OCSP_RESPONSE
27
28
#endif

29
30
31
32
33
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
34
#include <openssl/opensslv.h>
35
36
#include <openssl/bn.h>
#include <openssl/dh.h>
37
#include <openssl/conf.h>
38
#include <openssl/hmac.h>
39

40
41
42
#ifdef HAVE_CTYPE_H
#include <ctype.h>
#endif
43
44
45
46
47
48
49
50
51
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef HAVE_SYS_FCNTL_H
#include <sys/fcntl.h>
#endif
52

53
#define CRYPTO_PRIVATE
54
55
#include "crypto.h"
#include "log.h"
56
#include "aes.h"
57
#include "util.h"
58
#include "container.h"
59
#include "compat.h"
60

61
62
#if OPENSSL_VERSION_NUMBER < 0x00907000l
#error "We require openssl >= 0.9.7"
63
64
#endif

65
66
#include <openssl/engine.h>

Nick Mathewson's avatar
Nick Mathewson committed
67
/** Macro: is k a valid RSA public or private key? */
68
#define PUBLIC_KEY_OK(k) ((k) && (k)->key && (k)->key->n)
Nick Mathewson's avatar
Nick Mathewson committed
69
/** Macro: is k a valid RSA private key? */
70
71
#define PRIVATE_KEY_OK(k) ((k) && (k)->key && (k)->key->p)

72
#ifdef TOR_IS_MULTITHREADED
73
/** A number of prealloced mutexes for use by openssl. */
74
static tor_mutex_t **_openssl_mutexes = NULL;
75
/** How many mutexes have we allocated for use by openssl? */
76
static int _n_openssl_mutexes = 0;
77
78
#endif

79
/** A public key, or a public/private keypair. */
80
81
struct crypto_pk_env_t
{
82
  int refs; /* reference counting so we don't have to copy keys */
83
  RSA *key;
84
85
};

86
/** Key and stream information for a stream cipher. */
87
88
struct crypto_cipher_env_t
{
89
  char key[CIPHER_KEY_LEN];
90
  aes_cnt_cipher_t *cipher;
91
92
};

93
94
/** A structure to hold the first half (x, g^x) of a Diffie-Hellman handshake
 * while we're waiting for the second.*/
95
96
97
struct crypto_dh_env_t {
  DH *dh;
};
Nick Mathewson's avatar
Nick Mathewson committed
98

99
static int setup_openssl_threading(void);
100
static int tor_check_dh_key(BIGNUM *bn);
101

Nick Mathewson's avatar
Nick Mathewson committed
102
/** Return the number of bytes added by padding method <b>padding</b>.
103
 */
104
static INLINE int
105
106
crypto_get_rsa_padding_overhead(int padding)
{
107
  switch (padding)
108
    {
109
110
111
    case RSA_NO_PADDING: return 0;
    case RSA_PKCS1_OAEP_PADDING: return 42;
    case RSA_PKCS1_PADDING: return 11;
112
    default: tor_assert(0); return -1;
113
114
115
    }
}

Nick Mathewson's avatar
Nick Mathewson committed
116
/** Given a padding method <b>padding</b>, return the correct OpenSSL constant.
117
 */
118
static INLINE int
119
120
crypto_get_rsa_padding(int padding)
{
121
  switch (padding)
122
    {
123
124
125
    case PK_NO_PADDING: return RSA_NO_PADDING;
    case PK_PKCS1_PADDING: return RSA_PKCS1_PADDING;
    case PK_PKCS1_OAEP_PADDING: return RSA_PKCS1_OAEP_PADDING;
126
    default: tor_assert(0); return -1;
127
128
129
    }
}

Nick Mathewson's avatar
Nick Mathewson committed
130
/** Boolean: has OpenSSL's crypto been initialized? */
131
132
static int _crypto_global_initialized = 0;

Nick Mathewson's avatar
Nick Mathewson committed
133
134
/** Log all pending crypto errors at level <b>severity</b>.  Use
 * <b>doing</b> to describe our current activities.
135
 */
136
137
138
static void
crypto_log_errors(int severity, const char *doing)
{
139
  unsigned long err;
140
141
142
143
144
145
  const char *msg, *lib, *func;
  while ((err = ERR_get_error()) != 0) {
    msg = (const char*)ERR_reason_error_string(err);
    lib = (const char*)ERR_lib_error_string(err);
    func = (const char*)ERR_func_error_string(err);
    if (!msg) msg = "(null)";
146
147
    if (!lib) lib = "(null)";
    if (!func) func = "(null)";
148
    if (doing) {
149
150
      log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)",
          doing, msg, lib, func);
151
    } else {
152
      log(severity, LD_CRYPTO, "crypto error: %s (in %s:%s)", msg, lib, func);
153
154
155
    }
  }
}
Nick Mathewson's avatar
Nick Mathewson committed
156

157
/** Log any OpenSSL engines we're using at NOTICE. */
158
159
160
161
162
163
164
static void
log_engine(const char *fn, ENGINE *e)
{
  if (e) {
    const char *name, *id;
    name = ENGINE_get_name(e);
    id = ENGINE_get_id(e);
165
    log(LOG_NOTICE, LD_CRYPTO, "Using OpenSSL engine %s [%s] for %s",
166
167
        name?name:"?", id?id:"?", fn);
  } else {
168
    log(LOG_INFO, LD_CRYPTO, "Using default implementation for %s", fn);
169
170
171
  }
}

172
/** Initialize the crypto library.  Return 0 on success, -1 on failure.
173
 */
174
175
int
crypto_global_init(int useAccel)
176
{
177
  if (!_crypto_global_initialized) {
178
179
180
181
    ERR_load_crypto_strings();
    OpenSSL_add_all_algorithms();
    _crypto_global_initialized = 1;
    setup_openssl_threading();
182
183
184
185
    /* XXX the below is a bug, since we can't know if we're supposed
     * to be using hardware acceleration or not. we should arrange
     * for this function to be called before init_keys. But make it
     * not complain loudly, at least until we make acceleration work. */
186
    if (useAccel < 0) {
187
      log_info(LD_CRYPTO, "Initializing OpenSSL via tor_tls_init().");
188
189
    }
    if (useAccel > 0) {
190
      log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
191
192
193
194
195
196
197
198
199
200
201
202
      ENGINE_load_builtin_engines();
      if (!ENGINE_register_all_complete())
        return -1;

      /* XXXX make sure this isn't leaking. */
      log_engine("RSA", ENGINE_get_default_RSA());
      log_engine("DH", ENGINE_get_default_DH());
      log_engine("RAND", ENGINE_get_default_RAND());
      log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1));
      log_engine("3DES", ENGINE_get_cipher_engine(NID_des_ede3_ecb));
      log_engine("AES", ENGINE_get_cipher_engine(NID_aes_128_ecb));
    }
203
  }
204
205
206
  return 0;
}

207
208
209
210
211
212
213
/** Free crypto resources held by this thread. */
void
crypto_thread_cleanup(void)
{
  ERR_remove_state(0);
}

214
/** Uninitialize the crypto library. Return 0 on success, -1 on failure.
215
 */
216
217
int
crypto_global_cleanup(void)
218
{
219
  EVP_cleanup();
220
  ERR_remove_state(0);
221
  ERR_free_strings();
222
  ENGINE_cleanup();
223
224
  CONF_modules_unload(1);
  CRYPTO_cleanup_all_ex_data();
225
226
#ifdef TOR_IS_MULTITHREADED
  if (_n_openssl_mutexes) {
227
228
    int n = _n_openssl_mutexes;
    tor_mutex_t **ms = _openssl_mutexes;
229
    int i;
230
    _openssl_mutexes = NULL;
231
    _n_openssl_mutexes = 0;
232
233
234
235
    for (i=0;i<n;++i) {
      tor_mutex_free(ms[i]);
    }
    tor_free(ms);
236
237
  }
#endif
238
239
240
  return 0;
}

Nick Mathewson's avatar
Nick Mathewson committed
241
/** used by tortls.c: wrap an RSA* in a crypto_pk_env_t. */
242
243
crypto_pk_env_t *
_crypto_new_pk_env_rsa(RSA *rsa)
244
245
{
  crypto_pk_env_t *env;
246
  tor_assert(rsa);
247
  env = tor_malloc(sizeof(crypto_pk_env_t));
248
  env->refs = 1;
249
  env->key = rsa;
250
251
252
  return env;
}

253
254
255
256
257
258
259
260
261
262
263
/** used by tortls.c: wrap the RSA from an evp_pkey in a crypto_pk_env_t.
 * returns NULL if this isn't an RSA key. */
crypto_pk_env_t *
_crypto_new_pk_env_evp_pkey(EVP_PKEY *pkey)
{
  RSA *rsa;
  if (!(rsa = EVP_PKEY_get1_RSA(pkey)))
    return NULL;
  return _crypto_new_pk_env_rsa(rsa);
}

264
/* DOCDOC _crypto_pk_env_get_rsa */
265
266
267
268
269
270
RSA *
_crypto_pk_env_get_rsa(crypto_pk_env_t *env)
{
  return env->key;
}

Nick Mathewson's avatar
Nick Mathewson committed
271
/** used by tortls.c: get an equivalent EVP_PKEY* for a crypto_pk_env_t.  Iff
272
 * private is set, include the private-key portion of the key. */
273
274
EVP_PKEY *
_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env, int private)
275
276
277
{
  RSA *key = NULL;
  EVP_PKEY *pkey = NULL;
278
  tor_assert(env->key);
279
280
281
282
283
284
285
  if (private) {
    if (!(key = RSAPrivateKey_dup(env->key)))
      goto error;
  } else {
    if (!(key = RSAPublicKey_dup(env->key)))
      goto error;
  }
286
287
288
289
290
291
292
293
294
295
296
297
298
  if (!(pkey = EVP_PKEY_new()))
    goto error;
  if (!(EVP_PKEY_assign_RSA(pkey, key)))
    goto error;
  return pkey;
 error:
  if (pkey)
    EVP_PKEY_free(pkey);
  if (key)
    RSA_free(key);
  return NULL;
}

Nick Mathewson's avatar
Nick Mathewson committed
299
/** Used by tortls.c: Get the DH* from a crypto_dh_env_t.
300
 */
301
302
DH *
_crypto_dh_env_get_dh(crypto_dh_env_t *dh)
303
304
305
306
{
  return dh->dh;
}

Nick Mathewson's avatar
Nick Mathewson committed
307
/** Allocate and return storage for a public key.  The key itself will not yet
308
309
 * be set.
 */
310
311
crypto_pk_env_t *
crypto_new_pk_env(void)
312
313
314
{
  RSA *rsa;

315
316
317
  rsa = RSA_new();
  if (!rsa) return NULL;
  return _crypto_new_pk_env_rsa(rsa);
318
319
}

Nick Mathewson's avatar
Nick Mathewson committed
320
/** Release a reference to an asymmetric key; when all the references
321
 * are released, free the key.
322
 */
323
324
void
crypto_free_pk_env(crypto_pk_env_t *env)
325
{
326
  tor_assert(env);
327

328
  if (--env->refs > 0)
329
    return;
330

331
332
  if (env->key)
    RSA_free(env->key);
333

334
  tor_free(env);
335
336
}

Nick Mathewson's avatar
Nick Mathewson committed
337
/** Create a new symmetric cipher for a given key and encryption flag
338
339
 * (1=encrypt, 0=decrypt).  Return the crypto object on success; NULL
 * on failure.
340
341
 */
crypto_cipher_env_t *
342
crypto_create_init_cipher(const char *key, int encrypt_mode)
343
344
345
346
{
  int r;
  crypto_cipher_env_t *crypto = NULL;

347
  if (! (crypto = crypto_new_cipher_env())) {
348
    log_warn(LD_CRYPTO, "Unable to allocate crypto object");
349
350
351
352
    return NULL;
  }

  if (crypto_cipher_set_key(crypto, key)) {
353
    crypto_log_errors(LOG_WARN, "setting symmetric key");
354
355
356
357
358
359
360
361
    goto error;
  }

  if (encrypt_mode)
    r = crypto_cipher_encrypt_init_cipher(crypto);
  else
    r = crypto_cipher_decrypt_init_cipher(crypto);

362
  if (r)
363
364
365
366
367
368
369
370
371
    goto error;
  return crypto;

 error:
  if (crypto)
    crypto_free_cipher_env(crypto);
  return NULL;
}

Nick Mathewson's avatar
Nick Mathewson committed
372
/** Allocate and return a new symmetric cipher.
373
 */
374
375
crypto_cipher_env_t *
crypto_new_cipher_env(void)
376
377
{
  crypto_cipher_env_t *env;
378

379
380
  env = tor_malloc_zero(sizeof(crypto_cipher_env_t));
  env->cipher = aes_new_cipher();
381
  return env;
382
383
}

Nick Mathewson's avatar
Nick Mathewson committed
384
/** Free a symmetric cipher.
385
 */
386
387
void
crypto_free_cipher_env(crypto_cipher_env_t *env)
388
{
389
  tor_assert(env);
390

391
  tor_assert(env->cipher);
392
  aes_free_cipher(env->cipher);
393
  memset(env, 0, sizeof(crypto_cipher_env_t));
394
  tor_free(env);
395
396
397
}

/* public key crypto */
398

Nick Mathewson's avatar
Nick Mathewson committed
399
/** Generate a new public/private keypair in <b>env</b>.  Return 0 on
400
401
 * success, -1 on failure.
 */
402
403
int
crypto_pk_generate_key(crypto_pk_env_t *env)
404
{
405
  tor_assert(env);
406

407
408
  if (env->key)
    RSA_free(env->key);
409
  env->key = RSA_generate_key(PK_BYTES*8,65537, NULL, NULL);
410
411
  if (!env->key) {
    crypto_log_errors(LOG_WARN, "generating RSA key");
412
    return -1;
413
  }
414

415
416
417
  return 0;
}

418
/** Read a PEM-encoded private key from the string <b>s</b> into <b>env</b>.
419
 * Return 0 on success, -1 on failure.
420
 */
421
422
/* Used here, and used for testing. */
int
423
424
crypto_pk_read_private_key_from_string(crypto_pk_env_t *env,
                                       const char *s)
425
{
426
427
  BIO *b;

428
429
  tor_assert(env);
  tor_assert(s);
430
431
432

  /* Create a read-only memory BIO, backed by the nul-terminated string 's' */
  b = BIO_new_mem_buf((char*)s, -1);
433

434
435
  if (env->key)
    RSA_free(env->key);
436
437
438
439
440

  env->key = PEM_read_bio_RSAPrivateKey(b,NULL,NULL,NULL);

  BIO_free(b);

441
  if (!env->key) {
442
    crypto_log_errors(LOG_WARN, "Error parsing private key");
443
    return -1;
444
  }
445
446
  return 0;
}
447

Nick Mathewson's avatar
Nick Mathewson committed
448
449
/** Read a PEM-encoded private key from the file named by
 * <b>keyfile</b> into <b>env</b>.  Return 0 on success, -1 on failure.
450
 */
451
int
452
453
crypto_pk_read_private_key_from_filename(crypto_pk_env_t *env,
                                         const char *keyfile)
454
{
455
456
  char *contents;
  int r;
457

458
  /* Read the file into a string. */
459
  contents = read_file_to_str(keyfile, 0, NULL);
460
  if (!contents) {
461
    log_warn(LD_CRYPTO, "Error reading private key from \"%s\"", keyfile);
462
463
    return -1;
  }
464

465
466
467
468
469
470
471
  /* Try to parse it. */
  r = crypto_pk_read_private_key_from_string(env, contents);
  tor_free(contents);
  if (r)
    return -1; /* read_private_key_from_string already warned, so we don't.*/

  /* Make sure it's valid. */
472
  if (crypto_pk_check_key(env) <= 0)
473
    return -1;
474

475
476
  return 0;
}
477

478
479
480
481
/** Helper function to implement crypto_pk_write_*_key_to_string. */
static int
crypto_pk_write_key_to_string_impl(crypto_pk_env_t *env, char **dest,
                                   size_t *len, int is_public)
482
{
483
  BUF_MEM *buf;
484
  BIO *b;
485
  int r;
486

487
488
489
  tor_assert(env);
  tor_assert(env->key);
  tor_assert(dest);
490

491
  b = BIO_new(BIO_s_mem()); /* Create a memory BIO */
492

493
494
495
  /* Now you can treat b as if it were a file.  Just use the
   * PEM_*_bio_* functions instead of the non-bio variants.
   */
496
497
498
499
500
501
502
  if (is_public)
    r = PEM_write_bio_RSAPublicKey(b, env->key);
  else
    r = PEM_write_bio_RSAPrivateKey(b, env->key, NULL,NULL,0,NULL,NULL);

  if (!r) {
    crypto_log_errors(LOG_WARN, "writing RSA key to string");
503
    BIO_free(b);
504
    return -1;
505
  }
506

507
  BIO_get_mem_ptr(b, &buf);
508
  (void)BIO_set_close(b, BIO_NOCLOSE); /* so BIO_free doesn't free buf */
509
  BIO_free(b);
510

Roger Dingledine's avatar
Roger Dingledine committed
511
  tor_assert(buf->length >= 0);
512
513
  *dest = tor_malloc(buf->length+1);
  memcpy(*dest, buf->data, buf->length);
514
  (*dest)[buf->length] = 0; /* nul terminate it */
515
516
  *len = buf->length;
  BUF_MEM_free(buf);
517

518
519
520
  return 0;
}

521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
/** PEM-encode the public key portion of <b>env</b> and write it to a
 * newly allocated string.  On success, set *<b>dest</b> to the new
 * string, *<b>len</b> to the string's length, and return 0.  On
 * failure, return -1.
 */
int
crypto_pk_write_public_key_to_string(crypto_pk_env_t *env, char **dest,
                                     size_t *len)
{
  return crypto_pk_write_key_to_string_impl(env, dest, len, 1);
}

/** PEM-encode the private key portion of <b>env</b> and write it to a
 * newly allocated string.  On success, set *<b>dest</b> to the new
 * string, *<b>len</b> to the string's length, and return 0.  On
 * failure, return -1.
 */
int
crypto_pk_write_private_key_to_string(crypto_pk_env_t *env, char **dest,
                                     size_t *len)
{
  return crypto_pk_write_key_to_string_impl(env, dest, len, 0);
}

Nick Mathewson's avatar
Nick Mathewson committed
545
546
/** Read a PEM-encoded public key from the first <b>len</b> characters of
 * <b>src</b>, and store the result in <b>env</b>.  Return 0 on success, -1 on
547
548
 * failure.
 */
549
int
550
551
crypto_pk_read_public_key_from_string(crypto_pk_env_t *env, const char *src,
                                      size_t len)
552
{
553
  BIO *b;
554

555
556
  tor_assert(env);
  tor_assert(src);
557
  tor_assert(len<INT_MAX);
558

559
  b = BIO_new(BIO_s_mem()); /* Create a memory BIO */
560

561
  BIO_write(b, src, (int)len);
562

563
564
565
  if (env->key)
    RSA_free(env->key);
  env->key = PEM_read_bio_RSAPublicKey(b, NULL, NULL, NULL);
566
  BIO_free(b);
567
  if (!env->key) {
568
    crypto_log_errors(LOG_WARN, "reading public key from string");
569
    return -1;
570
  }
571

572
573
574
  return 0;
}

575
/** Write the private key from <b>env</b> into the file named by <b>fname</b>,
576
577
 * PEM-encoded.  Return 0 on success, -1 on failure.
 */
578
579
int
crypto_pk_write_private_key_to_filename(crypto_pk_env_t *env,
580
581
582
583
584
                                        const char *fname)
{
  BIO *bio;
  char *cp;
  long len;
585
  char *s;
586
  int r;
587

588
  tor_assert(PRIVATE_KEY_OK(env));
589

590
591
  if (!(bio = BIO_new(BIO_s_mem())))
    return -1;
592
  if (PEM_write_bio_RSAPrivateKey(bio, env->key, NULL,NULL,0,NULL,NULL)
593
      == 0) {
594
    crypto_log_errors(LOG_WARN, "writing private key");
595
596
597
598
    BIO_free(bio);
    return -1;
  }
  len = BIO_get_mem_data(bio, &cp);
Roger Dingledine's avatar
Roger Dingledine committed
599
  tor_assert(len >= 0);
600
  s = tor_malloc(len+1);
601
602
  memcpy(s, cp, len);
  s[len]='\0';
603
  r = write_str_to_file(fname, s, 0);
604
  BIO_free(bio);
605
  tor_free(s);
606
607
608
  return r;
}

Nick Mathewson's avatar
Nick Mathewson committed
609
/** Return true iff <b>env</b> has a valid key.
610
 */
611
612
int
crypto_pk_check_key(crypto_pk_env_t *env)
613
{
614
  int r;
615
  tor_assert(env);
616

617
618
619
620
  r = RSA_check_key(env->key);
  if (r <= 0)
    crypto_log_errors(LOG_WARN,"checking RSA key");
  return r;
621
622
}

623
624
625
626
627
628
629
630
631
/** Return true iff <b>key</b> contains the private-key portion of the RSA
 * key. */
int
crypto_pk_key_is_private(const crypto_pk_env_t *key)
{
  tor_assert(key);
  return PRIVATE_KEY_OK(key);
}

Nick Mathewson's avatar
Nick Mathewson committed
632
633
/** Compare the public-key components of a and b.  Return -1 if a\<b, 0
 * if a==b, and 1 if a\>b.
634
 */
635
636
637
int
crypto_pk_cmp_keys(crypto_pk_env_t *a, crypto_pk_env_t *b)
{
638
639
  int result;

640
641
  if (!a || !b)
    return -1;
642

643
644
  if (!a->key || !b->key)
    return -1;
645

646
647
  tor_assert(PUBLIC_KEY_OK(a));
  tor_assert(PUBLIC_KEY_OK(b));
648
649
650
651
  result = BN_cmp((a->key)->n, (b->key)->n);
  if (result)
    return result;
  return BN_cmp((a->key)->e, (b->key)->e);
652
653
}

Nick Mathewson's avatar
Nick Mathewson committed
654
/** Return the size of the public key modulus in <b>env</b>, in bytes. */
655
656
size_t
crypto_pk_keysize(crypto_pk_env_t *env)
657
{
658
659
  tor_assert(env);
  tor_assert(env->key);
660

661
  return (size_t) RSA_size(env->key);
662
}
663

664
/** Increase the reference count of <b>env</b>, and return it.
665
 */
666
667
668
crypto_pk_env_t *
crypto_pk_dup_key(crypto_pk_env_t *env)
{
669
670
  tor_assert(env);
  tor_assert(env->key);
671

672
  env->refs++;
673
674
675
  return env;
}

676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
/** Make a real honest-to-goodness copy of <b>env</b>, and return it. */
crypto_pk_env_t *
crypto_pk_copy_full(crypto_pk_env_t *env)
{
  RSA *new_key;
  tor_assert(env);
  tor_assert(env->key);

  if (PRIVATE_KEY_OK(env)) {
    new_key = RSAPrivateKey_dup(env->key);
  } else {
    new_key = RSAPublicKey_dup(env->key);
  }

  return _crypto_new_pk_env_rsa(new_key);
}

Nick Mathewson's avatar
Nick Mathewson committed
693
694
695
696
/** Encrypt <b>fromlen</b> bytes from <b>from</b> with the public key
 * in <b>env</b>, using the padding method <b>padding</b>.  On success,
 * write the result to <b>to</b>, and return the number of bytes
 * written.  On failure, return -1.
697
 */
698
int
699
700
crypto_pk_public_encrypt(crypto_pk_env_t *env, char *to,
                         const char *from, size_t fromlen, int padding)
701
{
702
  int r;
703
704
705
  tor_assert(env);
  tor_assert(from);
  tor_assert(to);
706
  tor_assert(fromlen<INT_MAX);
707

708
709
  r = RSA_public_encrypt((int)fromlen,
                         (unsigned char*)from, (unsigned char*)to,
710
                         env->key, crypto_get_rsa_padding(padding));
711
  if (r<0) {
712
    crypto_log_errors(LOG_WARN, "performing RSA encryption");
713
714
    return -1;
  }
715
  return r;
716
717
}

Nick Mathewson's avatar
Nick Mathewson committed
718
719
720
721
/** Decrypt <b>fromlen</b> bytes from <b>from</b> with the private key
 * in <b>env</b>, using the padding method <b>padding</b>.  On success,
 * write the result to <b>to</b>, and return the number of bytes
 * written.  On failure, return -1.
722
 */
723
int
724
725
crypto_pk_private_decrypt(crypto_pk_env_t *env, char *to,
                          const char *from, size_t fromlen,
726
                          int padding, int warnOnFailure)
727
{
728
  int r;
729
730
731
732
  tor_assert(env);
  tor_assert(from);
  tor_assert(to);
  tor_assert(env->key);
733
  tor_assert(fromlen<INT_MAX);
734
735
736
  if (!env->key->p)
    /* Not a private key */
    return -1;
737

738
739
  r = RSA_private_decrypt((int)fromlen,
                          (unsigned char*)from, (unsigned char*)to,
740
741
                          env->key, crypto_get_rsa_padding(padding));

742
  if (r<0) {
743
    crypto_log_errors(warnOnFailure?LOG_WARN:LOG_DEBUG,
744
                      "performing RSA decryption");
745
746
    return -1;
  }
747
  return r;
748
749
}

Nick Mathewson's avatar
Nick Mathewson committed
750
751
752
/** Check the signature in <b>from</b> (<b>fromlen</b> bytes long) with the
 * public key in <b>env</b>, using PKCS1 padding.  On success, write the
 * signed data to <b>to</b>, and return the number of bytes written.
Roger Dingledine's avatar
Roger Dingledine committed
753
 * On failure, return -1.
754
 */
755
int
756
757
crypto_pk_public_checksig(crypto_pk_env_t *env, char *to,
                          const char *from, size_t fromlen)
758
{
759
  int r;
760
761
762
  tor_assert(env);
  tor_assert(from);
  tor_assert(to);
763
  tor_assert(fromlen < INT_MAX);
764
765
  r = RSA_public_decrypt((int)fromlen,
                         (unsigned char*)from, (unsigned char*)to,
766
                         env->key, RSA_PKCS1_PADDING);
767

Roger Dingledine's avatar
Roger Dingledine committed
768
  if (r<0) {
769
    crypto_log_errors(LOG_WARN, "checking RSA signature");
Roger Dingledine's avatar
Roger Dingledine committed
770
771
    return -1;
  }
772
  return r;
773
774
}

Nick Mathewson's avatar
Nick Mathewson committed
775
776
777
778
/** Check a siglen-byte long signature at <b>sig</b> against
 * <b>datalen</b> bytes of data at <b>data</b>, using the public key
 * in <b>env</b>. Return 0 if <b>sig</b> is a correct signature for
 * SHA1(data).  Else return -1.
779
 */
780
int
781
crypto_pk_public_checksig_digest(crypto_pk_env_t *env, const char *data,
782
                               size_t datalen, const char *sig, size_t siglen)
783
{
784
  char digest[DIGEST_LEN];
785
  char *buf;
786
787
  int r;

788
789
790
  tor_assert(env);
  tor_assert(data);
  tor_assert(sig);
791

792
  if (crypto_digest(digest,data,datalen)<0) {
793
    log_warn(LD_BUG, "couldn't compute digest");
794
795
    return -1;
  }
796
  buf = tor_malloc(crypto_pk_keysize(env)+1);
797
  r = crypto_pk_public_checksig(env,buf,sig,siglen);
798
  if (r != DIGEST_LEN) {
799
    log_warn(LD_CRYPTO, "Invalid signature");
800
    tor_free(buf);
801
802
    return -1;
  }
803
  if (memcmp(buf, digest, DIGEST_LEN)) {
804
    log_warn(LD_CRYPTO, "Signature mismatched with digest.");
805
    tor_free(buf);
806
807
    return -1;
  }
808
  tor_free(buf);
809
810
811
812

  return 0;
}

813
814
815
816
817
818
/** Sign <b>fromlen</b> bytes of data from <b>from</b> with the private key in
 * <b>env</b>, using PKCS1 padding.  On success, write the signature to
 * <b>to</b>, and return the number of bytes written.  On failure, return
 * -1.
 */
int
819
820
crypto_pk_private_sign(crypto_pk_env_t *env, char *to,
                       const char *from, size_t fromlen)
821
822
823
824
825
{
  int r;
  tor_assert(env);
  tor_assert(from);
  tor_assert(to);
826
  tor_assert(fromlen < INT_MAX);
827
828
829
830
  if (!env->key->p)
    /* Not a private key */
    return -1;

831
832
  r = RSA_private_encrypt((int)fromlen,
                          (unsigned char*)from, (unsigned char*)to,
833
                          env->key, RSA_PKCS1_PADDING);
834
835
836
837
838
839
840
  if (r<0) {
    crypto_log_errors(LOG_WARN, "generating RSA signature");
    return -1;
  }
  return r;
}

Nick Mathewson's avatar
Nick Mathewson committed
841
842
843
844
/** Compute a SHA1 digest of <b>fromlen</b> bytes of data stored at
 * <b>from</b>; sign the data with the private key in <b>env</b>, and
 * store it in <b>to</b>.  Return the number of bytes written on
 * success, and -1 on failure.
845
 */
846
int
847
848
crypto_pk_private_sign_digest(crypto_pk_env_t *env, char *to,
                              const char *from, size_t fromlen)
849
{
850
  int r;
851
  char digest[DIGEST_LEN];
852
  if (crypto_digest(digest,from,fromlen)<0)
853
    return -1;
854
855
856
  r = crypto_pk_private_sign(env,to,digest,DIGEST_LEN);
  memset(digest, 0, sizeof(digest));
  return r;
857
858
}

Nick Mathewson's avatar
Nick Mathewson committed
859
860
861
/** Perform a hybrid (public/secret) encryption on <b>fromlen</b>
 * bytes of data from <b>from</b>, with padding type 'padding',
 * storing the results on <b>to</b>.
862
863
 *
 * If no padding is used, the public key must be at least as large as
Nick Mathewson's avatar
Nick Mathewson committed
864
 * <b>from</b>.
865
866
867
868
 *
 * Returns the number of bytes written on success, -1 on failure.
 *
 * The encrypted data consists of:
Nick Mathewson's avatar
Nick Mathewson committed
869
870
871
872
873
874
 *   - The source data, padded and encrypted with the public key, if the
 *     padded source data is no longer than the public key, and <b>force</b>
 *     is false, OR
 *   - The beginning of the source data prefixed with a 16-byte symmetric key,
 *     padded and encrypted with the public key; followed by the rest of
 *     the source data encrypted in AES-CTR mode with the symmetric key.
875
 */
876
877
878
879
880
881
int
crypto_pk_public_hybrid_encrypt(crypto_pk_env_t *env,
                                char *to,
                                const char *from,
                                size_t fromlen,
                                int padding, int force)
882
{
883
884
  int overhead, outlen, r;
  size_t pkeylen, symlen;
885
  crypto_cipher_env_t *cipher = NULL;
886
  char *buf = NULL;
887

888
889
890
  tor_assert(env);
  tor_assert(from);
  tor_assert(to);
891

892
  overhead = crypto_get_rsa_padding_overhead(crypto_get_rsa_padding(padding));
893
894
  pkeylen = crypto_pk_keysize(env);

895
  if (padding == PK_NO_PADDING && fromlen < pkeylen)
896
897
    return -1;

898
  if (!force && fromlen+overhead <= pkeylen) {
899
    /* It all fits in a single encrypt. */
900
    return crypto_pk_public_encrypt(env,to,from,fromlen,padding);
901
  }
902
  cipher = crypto_new_cipher_env();