crypto.c 85 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-2011, The Tor Project, Inc. */
5
6
/* See LICENSE for licensing information */

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

13
#include "orconfig.h"
14

15
#ifdef _WIN32
16
#ifndef WIN32_WINNT
17
#define WIN32_WINNT 0x400
18
19
#endif
#ifndef _WIN32_WINNT
20
#define _WIN32_WINNT 0x400
21
#endif
22
23
24
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <wincrypt.h>
Nick Mathewson's avatar
Nick Mathewson committed
25
/* Windows defines this; so does OpenSSL 0.9.8h and later. We don't actually
26
27
 * use either definition. */
#undef OCSP_RESPONSE
28
29
#endif

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

42
43
44
#ifdef HAVE_CTYPE_H
#include <ctype.h>
#endif
45
46
47
48
49
50
51
52
53
#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
54

55
#define CRYPTO_PRIVATE
56
#include "crypto.h"
Nick Mathewson's avatar
Nick Mathewson committed
57
#include "../common/torlog.h"
58
#include "aes.h"
59
#include "../common/util.h"
60
#include "container.h"
61
#include "compat.h"
62

63
#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,7)
Nick Mathewson's avatar
Nick Mathewson committed
64
#error "We require OpenSSL >= 0.9.7"
65
66
#endif

67
68
69
70
71
#ifdef ANDROID
/* Android's OpenSSL seems to have removed all of its Engine support. */
#define DISABLE_ENGINES
#endif

72
73
74
/** Longest recognized */
#define MAX_DNS_LABEL_SIZE 63

75
#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8)
76
77
/** @{ */
/** On OpenSSL versions before 0.9.8, there is no working SHA256
78
 * implementation, so we use Tom St Denis's nice speedy one, slightly adapted
79
 * to our needs.  These macros make it usable by us. */
80
81
82
83
#define SHA256_CTX sha256_state
#define SHA256_Init sha256_init
#define SHA256_Update sha256_process
#define LTC_ARGCHK(x) tor_assert(x)
84
/** @} */
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "sha256.c"
#define SHA256_Final(a,b) sha256_done(b,a)

static unsigned char *
SHA256(const unsigned char *m, size_t len, unsigned char *d)
{
  SHA256_CTX ctx;
  SHA256_Init(&ctx);
  SHA256_Update(&ctx, m, len);
  SHA256_Final(d, &ctx);
  return d;
}
#endif

Nick Mathewson's avatar
Nick Mathewson committed
99
/** Macro: is k a valid RSA public or private key? */
100
#define PUBLIC_KEY_OK(k) ((k) && (k)->key && (k)->key->n)
Nick Mathewson's avatar
Nick Mathewson committed
101
/** Macro: is k a valid RSA private key? */
102
103
#define PRIVATE_KEY_OK(k) ((k) && (k)->key && (k)->key->p)

104
#ifdef TOR_IS_MULTITHREADED
Nick Mathewson's avatar
Nick Mathewson committed
105
/** A number of preallocated mutexes for use by OpenSSL. */
106
static tor_mutex_t **_openssl_mutexes = NULL;
Nick Mathewson's avatar
Nick Mathewson committed
107
/** How many mutexes have we allocated for use by OpenSSL? */
108
static int _n_openssl_mutexes = 0;
109
110
#endif

Nick Mathewson's avatar
Nick Mathewson committed
111
/** A public key, or a public/private key-pair. */
112
struct crypto_pk_t
113
{
114
115
  int refs; /**< reference count, so we don't have to copy keys */
  RSA *key; /**< The key itself */
116
117
};

118
/** Key and stream information for a stream cipher. */
119
struct crypto_cipher_t
120
{
121
122
123
  char key[CIPHER_KEY_LEN]; /**< The raw key. */
  aes_cnt_cipher_t *cipher; /**< The key in format usable for counter-mode AES
                             * encryption */
124
125
};

126
127
/** A structure to hold the first half (x, g^x) of a Diffie-Hellman handshake
 * while we're waiting for the second.*/
128
struct crypto_dh_t {
129
  DH *dh; /**< The openssl DH object */
130
};
Nick Mathewson's avatar
Nick Mathewson committed
131

132
static int setup_openssl_threading(void);
133
static int tor_check_dh_key(int severity, BIGNUM *bn);
134

Nick Mathewson's avatar
Nick Mathewson committed
135
/** Return the number of bytes added by padding method <b>padding</b>.
136
 */
137
static INLINE int
138
139
crypto_get_rsa_padding_overhead(int padding)
{
140
  switch (padding)
141
    {
142
143
144
    case RSA_NO_PADDING: return 0;
    case RSA_PKCS1_OAEP_PADDING: return 42;
    case RSA_PKCS1_PADDING: return 11;
145
    default: tor_assert(0); return -1;
146
147
148
    }
}

Nick Mathewson's avatar
Nick Mathewson committed
149
/** Given a padding method <b>padding</b>, return the correct OpenSSL constant.
150
 */
151
static INLINE int
152
153
crypto_get_rsa_padding(int padding)
{
154
  switch (padding)
155
    {
156
157
158
    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;
159
    default: tor_assert(0); return -1;
160
161
162
    }
}

Nick Mathewson's avatar
Nick Mathewson committed
163
/** Boolean: has OpenSSL's crypto been initialized? */
164
165
static int _crypto_global_initialized = 0;

Nick Mathewson's avatar
Nick Mathewson committed
166
167
/** Log all pending crypto errors at level <b>severity</b>.  Use
 * <b>doing</b> to describe our current activities.
168
 */
169
170
171
static void
crypto_log_errors(int severity, const char *doing)
{
172
  unsigned long err;
173
174
175
176
177
178
  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)";
179
180
    if (!lib) lib = "(null)";
    if (!func) func = "(null)";
181
    if (doing) {
182
183
      log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)",
          doing, msg, lib, func);
184
    } else {
185
      log(severity, LD_CRYPTO, "crypto error: %s (in %s:%s)", msg, lib, func);
186
187
188
    }
  }
}
Nick Mathewson's avatar
Nick Mathewson committed
189

190
#ifndef DISABLE_ENGINES
191
/** Log any OpenSSL engines we're using at NOTICE. */
192
193
194
195
196
197
198
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);
199
    log(LOG_NOTICE, LD_CRYPTO, "Using OpenSSL engine %s [%s] for %s",
200
201
        name?name:"?", id?id:"?", fn);
  } else {
202
    log(LOG_INFO, LD_CRYPTO, "Using default implementation for %s", fn);
203
204
  }
}
205
#endif
206

207
#ifndef DISABLE_ENGINES
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/** Try to load an engine in a shared library via fully qualified path.
 */
static ENGINE *
try_load_engine(const char *path, const char *engine)
{
  ENGINE *e = ENGINE_by_id("dynamic");
  if (e) {
    if (!ENGINE_ctrl_cmd_string(e, "ID", engine, 0) ||
        !ENGINE_ctrl_cmd_string(e, "DIR_LOAD", "2", 0) ||
        !ENGINE_ctrl_cmd_string(e, "DIR_ADD", path, 0) ||
        !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
      ENGINE_free(e);
      e = NULL;
    }
  }
  return e;
}
225
#endif
226

227
/** Initialize the crypto library.  Return 0 on success, -1 on failure.
228
 */
229
int
230
crypto_global_init(int useAccel, const char *accelName, const char *accelDir)
231
{
232
  if (!_crypto_global_initialized) {
233
234
235
236
    ERR_load_crypto_strings();
    OpenSSL_add_all_algorithms();
    _crypto_global_initialized = 1;
    setup_openssl_threading();
237
    if (useAccel > 0) {
238
239
240
241
242
#ifdef DISABLE_ENGINES
      (void)accelName;
      (void)accelDir;
      log_warn(LD_CRYPTO, "No OpenSSL hardware acceleration support enabled.");
#else
243
      ENGINE *e = NULL;
244

245
      log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
246
      ENGINE_load_builtin_engines();
247
      ENGINE_register_all_complete();
248

249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
      if (accelName) {
        if (accelDir) {
          log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\""
                   " via path \"%s\".", accelName, accelDir);
          e = try_load_engine(accelName, accelDir);
        } else {
          log_info(LD_CRYPTO, "Initializing dynamic OpenSSL engine \"%s\""
                   " acceleration support.", accelName);
          e = ENGINE_by_id(accelName);
        }
        if (!e) {
          log_warn(LD_CRYPTO, "Unable to load dynamic OpenSSL engine \"%s\".",
                   accelName);
        } else {
          log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
                   accelName);
        }
      }
      if (e) {
        log_info(LD_CRYPTO, "Loaded OpenSSL hardware acceleration engine,"
                 " setting default ciphers.");
        ENGINE_set_default(e, ENGINE_METHOD_ALL);
      }
272
273
274
275
276
277
      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));
278
#endif
279
280
    } else {
      log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
281
    }
282
283

    evaluate_evp_for_aes(-1);
284
    evaluate_ctr_for_aes();
285

286
    return crypto_seed_rng(1);
287
  }
288
289
290
  return 0;
}

291
292
293
294
295
296
297
/** Free crypto resources held by this thread. */
void
crypto_thread_cleanup(void)
{
  ERR_remove_state(0);
}

298
299
300
/** used by tortls.c: wrap an RSA* in a crypto_pk_t. */
crypto_pk_t *
_crypto_new_pk_from_rsa(RSA *rsa)
301
{
302
  crypto_pk_t *env;
303
  tor_assert(rsa);
304
  env = tor_malloc(sizeof(crypto_pk_t));
305
  env->refs = 1;
306
  env->key = rsa;
307
308
309
  return env;
}

310
/** Helper, used by tor-checkkey.c and tor-gencert.c.  Return the RSA from a
311
 * crypto_pk_t. */
312
RSA *
313
_crypto_pk_get_rsa(crypto_pk_t *env)
314
315
316
317
{
  return env->key;
}

318
/** used by tortls.c: get an equivalent EVP_PKEY* for a crypto_pk_t.  Iff
319
 * private is set, include the private-key portion of the key. */
320
EVP_PKEY *
321
_crypto_pk_get_evp_pkey(crypto_pk_t *env, int private)
322
323
324
{
  RSA *key = NULL;
  EVP_PKEY *pkey = NULL;
325
  tor_assert(env->key);
326
327
328
329
330
331
332
  if (private) {
    if (!(key = RSAPrivateKey_dup(env->key)))
      goto error;
  } else {
    if (!(key = RSAPublicKey_dup(env->key)))
      goto error;
  }
333
334
335
336
337
338
339
340
341
342
343
344
345
  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;
}

346
/** Used by tortls.c: Get the DH* from a crypto_dh_t.
347
 */
348
DH *
349
_crypto_dh_get_dh(crypto_dh_t *dh)
350
351
352
353
{
  return dh->dh;
}

Nick Mathewson's avatar
Nick Mathewson committed
354
/** Allocate and return storage for a public key.  The key itself will not yet
355
356
 * be set.
 */
357
358
crypto_pk_t *
crypto_pk_new(void)
359
360
361
{
  RSA *rsa;

362
  rsa = RSA_new();
363
  tor_assert(rsa);
364
  return _crypto_new_pk_from_rsa(rsa);
365
366
}

Nick Mathewson's avatar
Nick Mathewson committed
367
/** Release a reference to an asymmetric key; when all the references
368
 * are released, free the key.
369
 */
370
void
371
crypto_pk_free(crypto_pk_t *env)
372
{
373
374
  if (!env)
    return;
375

376
  if (--env->refs > 0)
377
    return;
378
  tor_assert(env->refs == 0);
379

380
381
  if (env->key)
    RSA_free(env->key);
382

383
  tor_free(env);
384
385
}

Nick Mathewson's avatar
Nick Mathewson committed
386
/** Create a new symmetric cipher for a given key and encryption flag
387
388
 * (1=encrypt, 0=decrypt).  Return the crypto object on success; NULL
 * on failure.
389
 */
390
crypto_cipher_t *
391
crypto_create_init_cipher(const char *key, int encrypt_mode)
392
393
{
  int r;
394
  crypto_cipher_t *crypto = NULL;
395

396
  if (! (crypto = crypto_cipher_new())) {
397
    log_warn(LD_CRYPTO, "Unable to allocate crypto object");
398
399
400
    return NULL;
  }

401
  crypto_cipher_set_key(crypto, key);
402
403
404
405
406
407

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

408
  if (r)
409
410
411
412
413
    goto error;
  return crypto;

 error:
  if (crypto)
414
    crypto_cipher_free(crypto);
415
416
417
  return NULL;
}

Nick Mathewson's avatar
Nick Mathewson committed
418
/** Allocate and return a new symmetric cipher.
419
 */
420
421
crypto_cipher_t *
crypto_cipher_new(void)
422
{
423
  crypto_cipher_t *env;
424

425
  env = tor_malloc_zero(sizeof(crypto_cipher_t));
426
  env->cipher = aes_new_cipher();
427
  return env;
428
429
}

Nick Mathewson's avatar
Nick Mathewson committed
430
/** Free a symmetric cipher.
431
 */
432
void
433
crypto_cipher_free(crypto_cipher_t *env)
434
{
435
436
  if (!env)
    return;
437

438
  tor_assert(env->cipher);
439
440
  aes_cipher_free(env->cipher);
  memset(env, 0, sizeof(crypto_cipher_t));
441
  tor_free(env);
442
443
444
}

/* public key crypto */
445

446
447
/** Generate a <b>bits</b>-bit new public/private keypair in <b>env</b>.
 * Return 0 on success, -1 on failure.
448
 */
449
int
450
crypto_pk_generate_key_with_bits(crypto_pk_t *env, int bits)
451
{
452
  tor_assert(env);
453

454
455
  if (env->key)
    RSA_free(env->key);
456
#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8)
Nick Mathewson's avatar
Nick Mathewson committed
457
  /* In OpenSSL 0.9.7, RSA_generate_key is all we have. */
458
  env->key = RSA_generate_key(bits, 65537, NULL, NULL);
459
#else
Nick Mathewson's avatar
Nick Mathewson committed
460
  /* In OpenSSL 0.9.8, RSA_generate_key is deprecated. */
461
462
463
464
465
466
467
468
469
470
  {
    BIGNUM *e = BN_new();
    RSA *r = NULL;
    if (!e)
      goto done;
    if (! BN_set_word(e, 65537))
      goto done;
    r = RSA_new();
    if (!r)
      goto done;
471
    if (RSA_generate_key_ex(r, bits, e, NULL) == -1)
472
473
474
475
476
477
478
479
480
481
482
      goto done;

    env->key = r;
    r = NULL;
  done:
    if (e)
      BN_free(e);
    if (r)
      RSA_free(r);
    }
#endif
483
484
  if (!env->key) {
    crypto_log_errors(LOG_WARN, "generating RSA key");
485
    return -1;
486
  }
487

488
489
490
  return 0;
}

491
492
493
/** Read a PEM-encoded private key from the <b>len</b>-byte string <b>s</b>
 * into <b>env</b>.  Return 0 on success, -1 on failure.  If len is -1,
 * the string is nul-terminated.
494
 */
495
496
/* Used here, and used for testing. */
int
497
crypto_pk_read_private_key_from_string(crypto_pk_t *env,
498
                                       const char *s, ssize_t len)
499
{
500
501
  BIO *b;

502
503
  tor_assert(env);
  tor_assert(s);
504
  tor_assert(len < INT_MAX && len < SSIZE_T_CEILING);
505

506
507
  /* Create a read-only memory BIO, backed by the string 's' */
  b = BIO_new_mem_buf((char*)s, (int)len);
508
509
  if (!b)
    return -1;
510

511
512
  if (env->key)
    RSA_free(env->key);
513
514
515
516
517

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

  BIO_free(b);

518
  if (!env->key) {
519
    crypto_log_errors(LOG_WARN, "Error parsing private key");
520
    return -1;
521
  }
522
523
  return 0;
}
524

Nick Mathewson's avatar
Nick Mathewson committed
525
526
/** 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.
527
 */
528
int
529
crypto_pk_read_private_key_from_filename(crypto_pk_t *env,
530
                                         const char *keyfile)
531
{
532
533
  char *contents;
  int r;
534

535
  /* Read the file into a string. */
536
  contents = read_file_to_str(keyfile, 0, NULL);
537
  if (!contents) {
538
    log_warn(LD_CRYPTO, "Error reading private key from \"%s\"", keyfile);
539
540
    return -1;
  }
541

542
  /* Try to parse it. */
543
  r = crypto_pk_read_private_key_from_string(env, contents, -1);
544
  memset(contents, 0, strlen(contents));
545
546
547
548
549
  tor_free(contents);
  if (r)
    return -1; /* read_private_key_from_string already warned, so we don't.*/

  /* Make sure it's valid. */
550
  if (crypto_pk_check_key(env) <= 0)
551
    return -1;
552

553
554
  return 0;
}
555

556
557
/** Helper function to implement crypto_pk_write_*_key_to_string. */
static int
558
crypto_pk_write_key_to_string_impl(crypto_pk_t *env, char **dest,
559
                                   size_t *len, int is_public)
560
{
561
  BUF_MEM *buf;
562
  BIO *b;
563
  int r;
564

565
566
567
  tor_assert(env);
  tor_assert(env->key);
  tor_assert(dest);
568

569
  b = BIO_new(BIO_s_mem()); /* Create a memory BIO */
570
571
  if (!b)
    return -1;
572

573
574
575
  /* Now you can treat b as if it were a file.  Just use the
   * PEM_*_bio_* functions instead of the non-bio variants.
   */
576
577
578
579
580
581
582
  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");
583
    BIO_free(b);
584
    return -1;
585
  }
586

587
  BIO_get_mem_ptr(b, &buf);
588
  (void)BIO_set_close(b, BIO_NOCLOSE); /* so BIO_free doesn't free buf */
589
  BIO_free(b);
590

591
592
  *dest = tor_malloc(buf->length+1);
  memcpy(*dest, buf->data, buf->length);
593
  (*dest)[buf->length] = 0; /* nul terminate it */
594
595
  *len = buf->length;
  BUF_MEM_free(buf);
596

597
598
599
  return 0;
}

600
601
602
603
604
605
/** 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
606
crypto_pk_write_public_key_to_string(crypto_pk_t *env, char **dest,
607
608
609
610
611
612
613
614
615
616
617
                                     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
618
crypto_pk_write_private_key_to_string(crypto_pk_t *env, char **dest,
619
620
621
622
623
                                     size_t *len)
{
  return crypto_pk_write_key_to_string_impl(env, dest, len, 0);
}

Nick Mathewson's avatar
Nick Mathewson committed
624
625
/** 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
626
627
 * failure.
 */
628
int
629
crypto_pk_read_public_key_from_string(crypto_pk_t *env, const char *src,
630
                                      size_t len)
631
{
632
  BIO *b;
633

634
635
  tor_assert(env);
  tor_assert(src);
636
  tor_assert(len<INT_MAX);
637

638
  b = BIO_new(BIO_s_mem()); /* Create a memory BIO */
639
640
  if (!b)
    return -1;
641

642
  BIO_write(b, src, (int)len);
643

644
645
646
  if (env->key)
    RSA_free(env->key);
  env->key = PEM_read_bio_RSAPublicKey(b, NULL, NULL, NULL);
647
  BIO_free(b);
648
  if (!env->key) {
649
    crypto_log_errors(LOG_WARN, "reading public key from string");
650
    return -1;
651
  }
652

653
654
655
  return 0;
}

656
/** Write the private key from <b>env</b> into the file named by <b>fname</b>,
657
658
 * PEM-encoded.  Return 0 on success, -1 on failure.
 */
659
int
660
crypto_pk_write_private_key_to_filename(crypto_pk_t *env,
661
662
663
664
665
                                        const char *fname)
{
  BIO *bio;
  char *cp;
  long len;
666
  char *s;
667
  int r;
668

669
  tor_assert(PRIVATE_KEY_OK(env));
670

671
672
  if (!(bio = BIO_new(BIO_s_mem())))
    return -1;
673
  if (PEM_write_bio_RSAPrivateKey(bio, env->key, NULL,NULL,0,NULL,NULL)
674
      == 0) {
675
    crypto_log_errors(LOG_WARN, "writing private key");
676
677
678
679
    BIO_free(bio);
    return -1;
  }
  len = BIO_get_mem_data(bio, &cp);
Roger Dingledine's avatar
Roger Dingledine committed
680
  tor_assert(len >= 0);
681
  s = tor_malloc(len+1);
682
683
  memcpy(s, cp, len);
  s[len]='\0';
684
  r = write_str_to_file(fname, s, 0);
685
  BIO_free(bio);
686
  memset(s, 0, strlen(s));
687
  tor_free(s);
688
689
690
  return r;
}

Nick Mathewson's avatar
Nick Mathewson committed
691
/** Return true iff <b>env</b> has a valid key.
692
 */
693
int
694
crypto_pk_check_key(crypto_pk_t *env)
695
{
696
  int r;
697
  tor_assert(env);
698

699
700
701
702
  r = RSA_check_key(env->key);
  if (r <= 0)
    crypto_log_errors(LOG_WARN,"checking RSA key");
  return r;
703
704
}

705
706
707
/** Return true iff <b>key</b> contains the private-key portion of the RSA
 * key. */
int
708
crypto_pk_key_is_private(const crypto_pk_t *key)
709
710
711
712
713
{
  tor_assert(key);
  return PRIVATE_KEY_OK(key);
}

714
715
716
717
/** Return true iff <b>env</b> contains a public key whose public exponent
 * equals 65537.
 */
int
718
crypto_pk_public_exponent_ok(crypto_pk_t *env)
719
720
721
722
723
724
725
{
  tor_assert(env);
  tor_assert(env->key);

  return BN_is_word(env->key->e, 65537);
}

Nick Mathewson's avatar
Nick Mathewson committed
726
727
/** Compare the public-key components of a and b.  Return -1 if a\<b, 0
 * if a==b, and 1 if a\>b.
728
 */
729
int
730
crypto_pk_cmp_keys(crypto_pk_t *a, crypto_pk_t *b)
731
{
732
733
  int result;

734
735
  if (!a || !b)
    return -1;
736

737
738
  if (!a->key || !b->key)
    return -1;
739

740
741
  tor_assert(PUBLIC_KEY_OK(a));
  tor_assert(PUBLIC_KEY_OK(b));
742
743
744
745
  result = BN_cmp((a->key)->n, (b->key)->n);
  if (result)
    return result;
  return BN_cmp((a->key)->e, (b->key)->e);
746
747
}

Nick Mathewson's avatar
Nick Mathewson committed
748
/** Return the size of the public key modulus in <b>env</b>, in bytes. */
749
size_t
750
crypto_pk_keysize(crypto_pk_t *env)
751
{
752
753
  tor_assert(env);
  tor_assert(env->key);
754

755
  return (size_t) RSA_size(env->key);
756
}
757

758
759
/** Return the size of the public key modulus of <b>env</b>, in bits. */
int
760
crypto_pk_num_bits(crypto_pk_t *env)
761
762
763
764
765
766
767
768
{
  tor_assert(env);
  tor_assert(env->key);
  tor_assert(env->key->n);

  return BN_num_bits(env->key->n);
}

769
/** Increase the reference count of <b>env</b>, and return it.
770
 */
771
772
crypto_pk_t *
crypto_pk_dup_key(crypto_pk_t *env)
773
{
774
775
  tor_assert(env);
  tor_assert(env->key);
776

777
  env->refs++;
778
779
780
  return env;
}

781
/** Make a real honest-to-goodness copy of <b>env</b>, and return it. */
782
783
crypto_pk_t *
crypto_pk_copy_full(crypto_pk_t *env)
784
785
{
  RSA *new_key;
786
  int privatekey = 0;
787
788
789
790
791
  tor_assert(env);
  tor_assert(env->key);

  if (PRIVATE_KEY_OK(env)) {
    new_key = RSAPrivateKey_dup(env->key);
792
    privatekey = 1;
793
794
795
  } else {
    new_key = RSAPublicKey_dup(env->key);
  }
796
797
798
799
800
801
802
803
804
  if (!new_key) {
    log_err(LD_CRYPTO, "Unable to duplicate a %s key: openssl failed.",
            privatekey?"private":"public");
    crypto_log_errors(LOG_ERR,
                      privatekey ? "Duplicating a private key" :
                      "Duplicating a public key");
    tor_fragile_assert();
    return NULL;
  }
805

806
  return _crypto_new_pk_from_rsa(new_key);
807
808
}

Nick Mathewson's avatar
Nick Mathewson committed
809
810
811
812
/** 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.
813
814
815
 *
 * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
 * at least the length of the modulus of <b>env</b>.
816
 */
817
int
818
crypto_pk_public_encrypt(crypto_pk_t *env, char *to, size_t tolen,
819
                         const char *from, size_t fromlen, int padding)
820
{
821
  int r;
822
823
824
  tor_assert(env);
  tor_assert(from);
  tor_assert(to);
825
  tor_assert(fromlen<INT_MAX);
826
  tor_assert(tolen >= crypto_pk_keysize(env));
827

828
829
  r = RSA_public_encrypt((int)fromlen,
                         (unsigned char*)from, (unsigned char*)to,
830
                         env->key, crypto_get_rsa_padding(padding));
831
  if (r<0) {
832
    crypto_log_errors(LOG_WARN, "performing RSA encryption");
833
834
    return -1;
  }
835
  return r;
836
837
}

Nick Mathewson's avatar
Nick Mathewson committed
838
839
840
841
/** 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.
842
843
844
 *
 * <b>tolen</b> is the number of writable bytes in <b>to</b>, and must be
 * at least the length of the modulus of <b>env</b>.
845
 */
846
int
847
crypto_pk_private_decrypt(crypto_pk_t *env, char *to,
848
                          size_t tolen,
849
                          const char *from, size_t fromlen,
850
                          int padding, int warnOnFailure)
851
{
852
  int r;
853
854
855
856
  tor_assert(env);
  tor_assert(from);
  tor_assert(to);
  tor_assert(env->key);
857
  tor_assert(fromlen<INT_MAX);
858
  tor_assert(tolen >= crypto_pk_keysize(env));
859
860
861
  if (!env->key->p)
    /* Not a private key */
    return -1;
862

863
864
  r = RSA_private_decrypt((int)fromlen,
                          (unsigned char*)from, (unsigned char*)to,
865
866
                          env->key, crypto_get_rsa_padding(padding));

867
  if (r<0) {
868
    crypto_log_errors(warnOnFailure?LOG_WARN:LOG_DEBUG,