tortls.c 12.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
/* Copyright 2003 Roger Dingledine. */
/* See LICENSE for licensing information */
/* $Id$ */

/* TLS wrappers for The Onion Router.  (Unlike other tor functions, these
 * are prefixed with tor_ in order to avoid conflicting with OpenSSL
 * functions and variables.)
 */

#include "./crypto.h"
#include "./tortls.h"
#include "./util.h"
Nick Mathewson's avatar
Nick Mathewson committed
13
#include "./log.h"
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

#include <assert.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/tls1.h>
#include <openssl/asn1.h>
#include <openssl/bio.h>

struct tor_tls_context_st {
  SSL_CTX *ctx;
};

struct tor_tls_st {
  SSL *ssl;
  int socket;
  enum { 
    TOR_TLS_ST_HANDSHAKE, TOR_TLS_ST_OPEN, TOR_TLS_ST_GOTCLOSE, 
    TOR_TLS_ST_SENTCLOSE, TOR_TLS_ST_CLOSED
  } state;
  int isServer;
};

36
37
38
static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa, 
                                        const char *nickname); 

39
40
/* global tls context, keep it here because nobody else needs to touch it */
static tor_tls_context *global_tls_context=NULL;
41
static int tls_library_is_initialized = 0;
42

43
44
45
#define _TOR_TLS_SYSCALL    -6
#define _TOR_TLS_ZERORETURN -5

46
47

/* These functions are declared in crypto.c but not exported. */
48
EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env);
49
crypto_pk_env_t *_crypto_new_pk_env_rsa(RSA *rsa);
Nick Mathewson's avatar
Nick Mathewson committed
50
51

static void
52
tls_log_error(int severity, const char *doing)
Nick Mathewson's avatar
Nick Mathewson committed
53
{
54
55
  const char *msg = (const char*)ERR_reason_error_string(ERR_get_error());
  if (!msg) msg = "(null)";
Nick Mathewson's avatar
Nick Mathewson committed
56
  if (doing) {
Nick Mathewson's avatar
Nick Mathewson committed
57
    log(severity, "TLS error while %s: %s", doing, msg);
Nick Mathewson's avatar
Nick Mathewson committed
58
  } else {
Nick Mathewson's avatar
Nick Mathewson committed
59
    log(severity, "TLS error: %s", msg);
Nick Mathewson's avatar
Nick Mathewson committed
60
61
  }
}
62

63
64
65
#define CATCH_SYSCALL 1
#define CATCH_ZERO    2

66
static int
67
tor_tls_get_error(tor_tls *tls, int r, int extra,
Nick Mathewson's avatar
Nick Mathewson committed
68
		  const char *doing, int severity)
69
70
71
72
73
74
75
76
77
78
{
  int err = SSL_get_error(tls->ssl, r);
  switch (err) {
    case SSL_ERROR_NONE:
      return TOR_TLS_DONE;
    case SSL_ERROR_WANT_READ:
      return TOR_TLS_WANTREAD;
    case SSL_ERROR_WANT_WRITE:
      return TOR_TLS_WANTWRITE;
    case SSL_ERROR_SYSCALL:
79
80
      if (extra&CATCH_SYSCALL)
	return _TOR_TLS_SYSCALL;
81
      assert(severity != LOG_ERR); /* XXX remove me when the bug is found */
82
83
      log(severity, "TLS error: <syscall error>.");
      return TOR_TLS_ERROR;
84
    case SSL_ERROR_ZERO_RETURN:
85
86
87
88
      if (extra&CATCH_ZERO)
	return _TOR_TLS_ZERORETURN;
      log(severity, "TLS error: Zero return");
      return TOR_TLS_ERROR;
89
    default:
90
      tls_log_error(severity, doing);
91
92
93
94
      return TOR_TLS_ERROR;
  }
}

95
96
97
98
static void
tor_tls_init() {
  if (!tls_library_is_initialized) {
    SSL_library_init();
99
    SSL_load_error_strings();
Nick Mathewson's avatar
Nick Mathewson committed
100
    crypto_global_init();
101
    OpenSSL_add_all_algorithms();
102
103
104
105
    tls_library_is_initialized = 1;
  }
}

106
107
108
static int always_accept_verify_cb(int preverify_ok, 
                                   X509_STORE_CTX *x509_ctx)
{
109
110
  /* We always accept peer certs and complete the handshake.  We don't validate
   * them until later. */
111
112
113
114
115
116
117
  return 1;
}

/* Generate a self-signed certificate with the private key 'rsa' and
 * commonName 'nickname', and write it, PEM-encoded, to the file named
 * by 'certfile'.  Return 0 on success, -1 for failure.
 */
118
119
120
X509 *
tor_tls_create_certificate(crypto_pk_env_t *rsa, 
                           const char *nickname)
121
122
123
124
125
126
127
{
  time_t start_time, end_time;
  EVP_PKEY *pkey = NULL;
  X509 *x509 = NULL;
  X509_NAME *name = NULL;
  BIO *out = NULL;
  int nid;
128
  int err;
129
  
130
131
  tor_tls_init();

132
133
  start_time = time(NULL);

134
  assert(rsa && nickname);
135
  if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa)))
136
    return NULL;
137
  if (!(x509 = X509_new()))
138
    goto error;
139
  if (!(X509_set_version(x509, 2)))
140
    goto error;
141
  if (!(ASN1_INTEGER_set(X509_get_serialNumber(x509), (long)start_time)))
142
    goto error;
143
144
  
  if (!(name = X509_NAME_new()))
145
    goto error;
146
  if ((nid = OBJ_txt2nid("organizationName")) == NID_undef) goto error;
147
  if (!(X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC,
148
                                   "TOR", -1, -1, 0))) goto error;
149
  if ((nid = OBJ_txt2nid("commonName")) == NID_undef) goto error;
150
  if (!(X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC,
151
                                   (char*)nickname, -1, -1, 0))) goto error;
152
153
  
  if (!(X509_set_issuer_name(x509, name)))
154
    goto error;
155
  if (!(X509_set_subject_name(x509, name)))
156
    goto error;
157
  if (!X509_time_adj(X509_get_notBefore(x509),0,&start_time))
158
    goto error;
159
160
  end_time = start_time + 24*60*60*365;
  if (!X509_time_adj(X509_get_notAfter(x509),0,&end_time))
161
    goto error;
162
  if (!X509_set_pubkey(x509, pkey))
163
    goto error;
164
  if (!X509_sign(x509, pkey, EVP_sha1()))
165
    goto error;
166

167
  err = 0;
168
169
  goto done;
 error:
170
  err = 1;
171
172
173
 done:
  if (out)
    BIO_free(out);
174
  if (x509 && err)
175
176
177
178
179
    X509_free(x509);
  if (pkey)
    EVP_PKEY_free(pkey);
  if (name)
    X509_NAME_free(name);
180
  return x509;
181
182
}

183
184
185
186
187
188
189
190
191

#ifdef EVERYONE_HAS_AES
/* Everybody is running OpenSSL 0.9.7 or later, so no backward compatibiliy
 * is needed. */
#define CIPHER_LIST TLS1_TXT_DHE_RSA_WITH_AES_128_SHA
#elif defined(TLS1_TXT_DHE_RSA_WITH_AES_128_SHA)
/* Some people are running OpenSSL before 0.9.7, but we aren't.  
 * We can support AES and 3DES.
 */
192
#define CIPHER_LIST (TLS1_TXT_DHE_RSA_WITH_AES_128_SHA ":" \
193
194
195
196
197
198
		     SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA)
#else
/* We're running OpenSSL before 0.9.7. We only support 3DES. */
#define CIPHER_LIST SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA
#endif

199
200
201
/* Create a new TLS context.  If we are going to be using it as a
 * server, it must have isServer set to true, certfile set to a
 * filename for a certificate file, and RSA set to the private key
202
 * used for that certificate. Return -1 if failure, else 0.
203
 */
204
int
205
206
tor_tls_context_new(crypto_pk_env_t *rsa,
                    int isServer, const char *nickname)
207
208
209
210
{
  crypto_dh_env_t *dh = NULL;
  EVP_PKEY *pkey = NULL;
  tor_tls_context *result;
211
212
  X509 *cert = NULL;
  
213
214
  tor_tls_init();

215
216
217
  if (rsa) {
    cert = tor_tls_create_certificate(rsa, nickname);
    if (!cert) {
Roger Dingledine's avatar
Roger Dingledine committed
218
      log(LOG_WARN, "Error creating certificate");
219
      return -1;
220
221
222
    }
  }

223
  result = tor_malloc(sizeof(tor_tls_context));
224
225
226
  result->ctx = NULL;
#ifdef EVERYONE_HAS_AES
  /* Tell OpenSSL to only use TLS1 */
227
  if (!(result->ctx = SSL_CTX_new(TLSv1_method())))
228
229
230
231
232
233
234
235
236
    goto error;
#else
  /* Tell OpenSSL to use SSL3 or TLS1 but not SSL2. */
  if (!(result->ctx = SSL_CTX_new(SSLv23_method())))
    goto error;
  SSL_CTX_set_options(result->ctx, SSL_OP_NO_SSLv2);
#endif
  if (!SSL_CTX_set_cipher_list(result->ctx, CIPHER_LIST))
    goto error;
237
  if (cert && !SSL_CTX_use_certificate(result->ctx,cert))
238
    goto error;
239
240
  SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF);
  if (rsa) {
241
242
    if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa)))
      goto error;
243
    if (!SSL_CTX_use_PrivateKey(result->ctx, pkey))
244
      goto error;
245
    EVP_PKEY_free(pkey);
246
    pkey = NULL;
247
    if (cert) {
248
      if (!SSL_CTX_check_private_key(result->ctx))
249
        goto error;
250
251
252
253
254
255
256
257
    }
  }
  dh = crypto_dh_new();
  SSL_CTX_set_tmp_dh(result->ctx, dh->dh);
  crypto_dh_free(dh);
  SSL_CTX_set_verify(result->ctx, SSL_VERIFY_PEER, 
                     always_accept_verify_cb);
  
258
259
  global_tls_context = result;
  return 0;
260
261
262
263
264
265
266
267
268
269
270
271

 error:
  if (pkey)
    EVP_PKEY_free(pkey);
  if (dh)
    crypto_dh_free(dh);
  if (result && result->ctx)
    SSL_CTX_free(result->ctx);
  if (result)
    free(result);

  return -1;
272
273
274
275
276
277
}

/* Create a new TLS object from a TLS context, a filedescriptor, and 
 * a flag to determine whether it is functioning as a server.
 */
tor_tls *
278
tor_tls_new(int sock, int isServer)
279
280
{
  tor_tls *result = tor_malloc(sizeof(tor_tls));
281
282
  assert(global_tls_context); /* make sure somebody made it first */
  if (!(result->ssl = SSL_new(global_tls_context->ctx)))
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
    return NULL;
  result->socket = sock;
  SSL_set_fd(result->ssl, sock);
  result->state = TOR_TLS_ST_HANDSHAKE;
  result->isServer = isServer;
  return result;
}

/* Release resources associated with a TLS object.  Does not close the
 * underlying file descriptor.
 */
void
tor_tls_free(tor_tls *tls)
{
  SSL_free(tls->ssl);
  free(tls);
}

/* Underlying function for TLS reading.  Reads up to 'len' characters
 * from 'tls' into 'cp'.  On success, returns the number of characters
 * read.  On failure, returns TOR_TLS_ERROR, TOR_TLS_CLOSE,
 * TOR_TLS_WANTREAD, or TOR_TLS_WANTWRITE.
 */
int
tor_tls_read(tor_tls *tls, char *cp, int len)
{
  int r, err;
  assert(tls && tls->ssl);
  assert(tls->state == TOR_TLS_ST_OPEN);
  r = SSL_read(tls->ssl, cp, len);
  if (r > 0)
    return r;
315
  err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_INFO);
316
  if (err == _TOR_TLS_ZERORETURN) {
317
318
319
    tls->state = TOR_TLS_ST_CLOSED;
    return TOR_TLS_CLOSE;
  } else {
Nick Mathewson's avatar
Nick Mathewson committed
320
    assert(err != TOR_TLS_DONE);
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
    return err;
  }
}

/* Underlying function for TLS writing.  Write up to 'n' characters
 * from 'cp' onto 'tls'.  On success, returns the number of characters
 * written.  On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD, 
 * or TOR_TLS_WANTWRITE.
 */
int
tor_tls_write(tor_tls *tls, char *cp, int n)
{
  int r, err;
  assert(tls && tls->ssl);
  assert(tls->state == TOR_TLS_ST_OPEN);
Nick Mathewson's avatar
Nick Mathewson committed
336
337
  if (n == 0)
    return 0;
338
  r = SSL_write(tls->ssl, cp, n);
339
  err = tor_tls_get_error(tls, r, 0, "writing", LOG_INFO);
Nick Mathewson's avatar
Nick Mathewson committed
340
  if (err == TOR_TLS_DONE) {
341
342
343
344
345
346
347
348
    return r;
  } else {
    return err;
  }  
}

/* Perform initial handshake on 'tls'.  When finished, returns
 * TOR_TLS_DONE.  On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD,
349
 * or TOR_TLS_WANTWRITE.
350
351
352
353
354
355
356
357
358
359
360
361
 */
int
tor_tls_handshake(tor_tls *tls)
{
  int r;
  assert(tls && tls->ssl);
  assert(tls->state == TOR_TLS_ST_HANDSHAKE);
  if (tls->isServer) {
    r = SSL_accept(tls->ssl);
  } else {
    r = SSL_connect(tls->ssl);
  }
362
  r = tor_tls_get_error(tls,r,0, "handshaking", LOG_INFO);
363
364
365
366
367
  if (r == TOR_TLS_DONE) {
    tls->state = TOR_TLS_ST_OPEN; 
  }
  return r;
}
368
  
369
370
371
372
373
374
375
376
377
378
379
/* Shut down an open tls connection 'tls'.  When finished, returns
 * TOR_TLS_DONE.  On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD,
 * or TOR_TLS_WANTWRITE.
 */
int
tor_tls_shutdown(tor_tls *tls)
{
  int r, err;
  char buf[128];
  assert(tls && tls->ssl);

Nick Mathewson's avatar
Nick Mathewson committed
380
381
382
383
384
385
386
387
  while (1) {
    if (tls->state == TOR_TLS_ST_SENTCLOSE) {
      /* If we've already called shutdown once to send a close message,
       * we read until the other side has closed too.
       */
      do {
	r = SSL_read(tls->ssl, buf, 128);
      } while (r>0);
388
      err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading to shut down", 
389
			      LOG_INFO);
Nick Mathewson's avatar
Nick Mathewson committed
390
391
392
393
394
395
396
397
398
399
400
401
402
403
      if (err == _TOR_TLS_ZERORETURN) {
	tls->state = TOR_TLS_ST_GOTCLOSE;
	/* fall through... */
      } else {
	return err;
      }
    }

    r = SSL_shutdown(tls->ssl);
    if (r == 1) {
      /* If shutdown returns 1, the connection is entirely closed. */
      tls->state = TOR_TLS_ST_CLOSED;
      return TOR_TLS_DONE;
    }
404
    err = tor_tls_get_error(tls, r, CATCH_SYSCALL|CATCH_ZERO, "shutting down", 
405
			    LOG_INFO);
Nick Mathewson's avatar
Nick Mathewson committed
406
407
408
409
410
411
412
413
414
415
416
417
    if (err == _TOR_TLS_SYSCALL) {
      /* The underlying TCP connection closed while we were shutting down. */
      tls->state = TOR_TLS_ST_CLOSED; 
      return TOR_TLS_DONE;
    } else if (err == _TOR_TLS_ZERORETURN) {
      /* The TLS connection says that it sent a shutdown record, but
       * isn't done shutting down yet.  Make sure that this hasn't
       * happened before, then go back to the start of the function
       * and try to read.
       */
      if (tls->state == TOR_TLS_ST_GOTCLOSE || 
	  tls->state == TOR_TLS_ST_SENTCLOSE) {
Roger Dingledine's avatar
Roger Dingledine committed
418
	log(LOG_WARN, 
Nick Mathewson's avatar
Nick Mathewson committed
419
420
421
422
423
	    "TLS returned \"half-closed\" value while already half-closed");
	return TOR_TLS_ERROR;
      }
      tls->state = TOR_TLS_ST_SENTCLOSE;
      /* fall through ... */
424
425
426
    } else {
      return err;
    }
Nick Mathewson's avatar
Nick Mathewson committed
427
  } /* end loop */
428
}
429

430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
/* Return true iff this TLS connection is authenticated.
 */
int
tor_tls_peer_has_cert(tor_tls *tls)
{
  X509 *cert;
  if (!(cert = SSL_get_peer_certificate(tls->ssl)))
    return 0;
  X509_free(cert);
  return 1;
}

/* If the provided tls connection is authenticated and has a
 * certificate that is currently valid and is correctly self-signed,
 * return its public key.  Otherwise return NULL.
 */
crypto_pk_env_t *
tor_tls_verify(tor_tls *tls)
{
  X509 *cert = NULL;
  EVP_PKEY *pkey = NULL;
  RSA *rsa = NULL;
  time_t now;
  crypto_pk_env_t *r = NULL;
  if (!(cert = SSL_get_peer_certificate(tls->ssl)))
455
    return NULL;
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
  
  now = time(NULL);
  if (X509_cmp_time(X509_get_notBefore(cert), &now) > 0)
    goto done;
  if (X509_cmp_time(X509_get_notAfter(cert), &now) < 0)
    goto done;
  
  /* Get the public key. */
  if (!(pkey = X509_get_pubkey(cert)))
    goto done;
  if (X509_verify(cert, pkey) <= 0)
    goto done;

  rsa = EVP_PKEY_get1_RSA(pkey);
  EVP_PKEY_free(pkey);
  pkey = NULL;
  if (!rsa)
    goto done;

  r = _crypto_new_pk_env_rsa(rsa);
  rsa = NULL;
  
 done:
  if (cert)
    X509_free(cert);
  if (pkey)
    EVP_PKEY_free(pkey);
  if (rsa)
    RSA_free(rsa);
  return r;
}
487

488
int 
489
tor_tls_get_pending_bytes(tor_tls *tls)
490
491
492
493
{
  assert(tls);
  return SSL_pending(tls->ssl);
}