tortls.c 12.5 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
81
82
      if (extra&CATCH_SYSCALL)
	return _TOR_TLS_SYSCALL;
      log(severity, "TLS error: <syscall error>.");
      return TOR_TLS_ERROR;
83
    case SSL_ERROR_ZERO_RETURN:
84
85
86
87
      if (extra&CATCH_ZERO)
	return _TOR_TLS_ZERORETURN;
      log(severity, "TLS error: Zero return");
      return TOR_TLS_ERROR;
88
    default:
89
      tls_log_error(severity, doing);
90
91
92
93
      return TOR_TLS_ERROR;
  }
}

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

105
106
107
static int always_accept_verify_cb(int preverify_ok, 
                                   X509_STORE_CTX *x509_ctx)
{
108
109
  /* We always accept peer certs and complete the handshake.  We don't validate
   * them until later. */
110
111
112
113
114
115
116
  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.
 */
117
118
119
X509 *
tor_tls_create_certificate(crypto_pk_env_t *rsa, 
                           const char *nickname)
120
121
122
123
124
125
126
{
  time_t start_time, end_time;
  EVP_PKEY *pkey = NULL;
  X509 *x509 = NULL;
  X509_NAME *name = NULL;
  BIO *out = NULL;
  int nid;
127
  int err;
128
  
129
130
  tor_tls_init();

131
132
  start_time = time(NULL);

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

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

182
183
184
185
186
187
188
189
190

#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.
 */
191
#define CIPHER_LIST (TLS1_TXT_DHE_RSA_WITH_AES_128_SHA ":" \
192
193
194
195
196
197
		     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

198
199
200
/* 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
201
 * used for that certificate. Return -1 if failure, else 0.
202
 */
203
int
204
205
tor_tls_context_new(crypto_pk_env_t *rsa,
                    int isServer, const char *nickname)
206
207
208
209
{
  crypto_dh_env_t *dh = NULL;
  EVP_PKEY *pkey = NULL;
  tor_tls_context *result;
210
211
  X509 *cert = NULL;
  
212
213
  tor_tls_init();

214
215
216
217
  if (rsa) {
    cert = tor_tls_create_certificate(rsa, nickname);
    if (!cert) {
      log(LOG_ERR, "Error creating certificate");
218
      return -1;
219
220
221
    }
  }

222
  result = tor_malloc(sizeof(tor_tls_context));
223
224
225
  result->ctx = NULL;
#ifdef EVERYONE_HAS_AES
  /* Tell OpenSSL to only use TLS1 */
226
  if (!(result->ctx = SSL_CTX_new(TLSv1_method())))
227
228
229
230
231
232
233
234
235
    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;
236
  if (cert && !SSL_CTX_use_certificate(result->ctx,cert))
237
    goto error;
238
239
  SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF);
  if (rsa) {
240
241
    if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa)))
      goto error;
242
    if (!SSL_CTX_use_PrivateKey(result->ctx, pkey))
243
      goto error;
244
    EVP_PKEY_free(pkey);
245
    pkey = NULL;
246
    if (cert) {
247
      if (!SSL_CTX_check_private_key(result->ctx))
248
        goto error;
249
250
251
252
253
254
255
256
    }
  }
  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);
  
257
258
  global_tls_context = result;
  return 0;
259
260
261
262
263
264
265
266
267
268
269
270

 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;
271
272
273
274
275
276
}

/* 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 *
277
tor_tls_new(int sock, int isServer)
278
279
{
  tor_tls *result = tor_malloc(sizeof(tor_tls));
280
281
  assert(global_tls_context); /* make sure somebody made it first */
  if (!(result->ssl = SSL_new(global_tls_context->ctx)))
282
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
    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;
314
315
  err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_ERR);
  if (err == _TOR_TLS_ZERORETURN) {
316
317
318
    tls->state = TOR_TLS_ST_CLOSED;
    return TOR_TLS_CLOSE;
  } else {
Nick Mathewson's avatar
Nick Mathewson committed
319
    assert(err != TOR_TLS_DONE);
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
    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
335
336
  if (n == 0)
    return 0;
337
  r = SSL_write(tls->ssl, cp, n);
338
  err = tor_tls_get_error(tls, r, 0, "writing", LOG_ERR);
Nick Mathewson's avatar
Nick Mathewson committed
339
  if (err == TOR_TLS_DONE) {
340
341
342
343
344
345
346
347
    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,
348
 * or TOR_TLS_WANTWRITE.
349
350
351
352
353
354
355
356
357
358
359
360
 */
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);
  }
Nick Mathewson's avatar
Nick Mathewson committed
361
  r = tor_tls_get_error(tls,r,0, "handshaking", LOG_ERR);
362
363
364
365
366
  if (r == TOR_TLS_DONE) {
    tls->state = TOR_TLS_ST_OPEN; 
  }
  return r;
}
367
  
368
369
370
371
372
373
374
375
376
377
378
/* 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
379
380
381
382
383
384
385
386
  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);
387
388
      err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading to shut down", 
			      LOG_ERR);
Nick Mathewson's avatar
Nick Mathewson committed
389
390
391
392
393
394
395
396
397
398
399
400
401
402
      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;
    }
403
404
    err = tor_tls_get_error(tls, r, CATCH_SYSCALL|CATCH_ZERO, "shutting down", 
			    LOG_ERR);
Nick Mathewson's avatar
Nick Mathewson committed
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
    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) {
	log(LOG_ERR, 
	    "TLS returned \"half-closed\" value while already half-closed");
	return TOR_TLS_ERROR;
      }
      tls->state = TOR_TLS_ST_SENTCLOSE;
      /* fall through ... */
423
424
425
    } else {
      return err;
    }
Nick Mathewson's avatar
Nick Mathewson committed
426
  } /* end loop */
427
}
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
/* 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)))
454
    return NULL;
455
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
  
  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;
}
486