tortls.c 11.4 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
/* global tls context, keep it here because nobody else needs to touch it */
static tor_tls_context *global_tls_context=NULL;

39
40
41
#define _TOR_TLS_SYSCALL    -6
#define _TOR_TLS_ZERORETURN -5

42
43

/* These functions are declared in crypto.c but not exported. */
44
EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env);
45
46
crypto_pk_env_t *_crypto_new_pk_env_rsa(RSA *rsa);

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
static int
tor_tls_get_error(tor_tls *tls, int r, int extra)
{
  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:
      return extra ? _TOR_TLS_SYSCALL : TOR_TLS_ERROR;
    case SSL_ERROR_ZERO_RETURN:
      return extra ? _TOR_TLS_ZERORETURN : TOR_TLS_ERROR;
    default:
      return TOR_TLS_ERROR;
  }
}

static int always_accept_verify_cb(int preverify_ok, 
                                   X509_STORE_CTX *x509_ctx)
{
70
71
  /* We always accept peer certs and complete the handshake.  We don't validate
   * them until later. */
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  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.
 */
int
tor_tls_write_certificate(char *certfile, crypto_pk_env_t *rsa, char *nickname)
{
  time_t start_time, end_time;
  EVP_PKEY *pkey = NULL;
  X509 *x509 = NULL;
  X509_NAME *name = NULL;
  BIO *out = NULL;
  int nid;
88
  int r;
89
90
91
  
  start_time = time(NULL);

92
  assert(rsa);
93
  if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa)))
94
95
    return -1;
  if (!(x509 = X509_new()))
96
    goto error;
97
  if (!(X509_set_version(x509, 2)))
98
    goto error;
99
  if (!(ASN1_INTEGER_set(X509_get_serialNumber(x509), (long)start_time)))
100
    goto error;
101
102
  
  if (!(name = X509_NAME_new()))
103
104
    goto error;
  if ((nid = OBJ_txt2nid("organizationName")) != NID_undef) goto error;
105
  if (!(X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC,
106
107
                                   "TOR", -1, -1, 0))) goto error;
  if ((nid = OBJ_txt2nid("commonName")) != NID_undef) goto error;
108
  if (!(X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC,
109
                                   nickname, -1, -1, 0))) goto error;
110
111
  
  if (!(X509_set_issuer_name(x509, name)))
112
    goto error;
113
  if (!(X509_set_subject_name(x509, name)))
114
    goto error;
115
  if (!X509_time_adj(X509_get_notBefore(x509),0,&start_time))
116
    goto error;
117
118
  end_time = start_time + 24*60*60*365;
  if (!X509_time_adj(X509_get_notAfter(x509),0,&end_time))
119
    goto error;
120
  if (!X509_set_pubkey(x509, pkey))
121
    goto error;
122
  if (!X509_sign(x509, pkey, EVP_sha1()))
123
    goto error;
124
  if (!(out = BIO_new_file(certfile, "w")))
125
    goto error;
126
  if (!(PEM_write_bio_X509(out, x509)))
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
    goto error;
  
  r = 0;
  goto done;
 error:
  r = -1;
 done:
  if (out)
    BIO_free(out);
  if (x509)
    X509_free(x509);
  if (pkey)
    EVP_PKEY_free(pkey);
  if (name)
    X509_NAME_free(name);
  return r;
143
144
}

145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160

#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.
 */
#define CIPHER_LIST (TLS1_TXT_DHE_RSA_WITH_AES_128_SHA \
		     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

161
162
163
/* 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
164
 * used for that certificate. Return -1 if failure, else 0.
165
 */
166
int
167
168
169
170
171
172
tor_tls_context_new(char *certfile, crypto_pk_env_t *rsa, int isServer)
{
  crypto_dh_env_t *dh = NULL;
  EVP_PKEY *pkey = NULL;
  tor_tls_context *result;

173
174
  assert((certfile && rsa) || (!certfile && !rsa));

175
  result = tor_malloc(sizeof(tor_tls_context));
176
177
178
  result->ctx = NULL;
#ifdef EVERYONE_HAS_AES
  /* Tell OpenSSL to only use TLS1 */
179
  if (!(result->ctx = SSL_CTX_new(TLSv1_method())))
180
181
182
183
184
185
186
187
188
    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;
189
190
  if (certfile && !SSL_CTX_use_certificate_file(result->ctx,certfile,
                                                SSL_FILETYPE_PEM))
191
    goto error;
192
193
  SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF);
  if (rsa) {
194
195
    if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa)))
      goto error;
196
    if (!SSL_CTX_use_PrivateKey(result->ctx, pkey))
197
      goto error;
198
    EVP_PKEY_free(pkey);
199
    pkey = NULL;
200
201
    if (certfile) {
      if (!SSL_CTX_check_private_key(result->ctx))
202
        goto error;
203
204
205
206
207
208
209
210
    }
  }
  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);
  
211
212
  global_tls_context = result;
  return 0;
213
214
215
216
217
218
219
220
221
222
223
224

 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;
225
226
227
228
229
230
}

/* 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 *
231
tor_tls_new(int sock, int isServer)
232
233
{
  tor_tls *result = tor_malloc(sizeof(tor_tls));
234
235
  assert(global_tls_context); /* make sure somebody made it first */
  if (!(result->ssl = SSL_new(global_tls_context->ctx)))
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
    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;
  err = tor_tls_get_error(tls, r, 1);
  if (err == _TOR_TLS_SYSCALL)
    return TOR_TLS_ERROR;
  else if (err == _TOR_TLS_ZERORETURN) {
    tls->state = TOR_TLS_ST_CLOSED;
    return TOR_TLS_CLOSE;
  } else {
Nick Mathewson's avatar
Nick Mathewson committed
275
    assert(err != TOR_TLS_DONE);
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
    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
291
292
  if (n == 0)
    return 0;
293
294
  r = SSL_write(tls->ssl, cp, n);
  err = tor_tls_get_error(tls, r, 1);
Nick Mathewson's avatar
Nick Mathewson committed
295
296
  assert(err != _TOR_TLS_ZERORETURN);
  if (err == TOR_TLS_DONE) {
297
298
299
300
301
302
303
304
    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,
305
 * or TOR_TLS_WANTWRITE.
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
 */
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);
  }
  r = tor_tls_get_error(tls,r,0);
  if (r == TOR_TLS_DONE) {
    tls->state = TOR_TLS_ST_OPEN; 
  }
  return r;
}

/* 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
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
  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);
      err = tor_tls_get_error(tls, r, 1);
      if (err == _TOR_TLS_ZERORETURN) {
	tls->state = TOR_TLS_ST_GOTCLOSE;
	/* fall through... */
      } else {
	if (err == _TOR_TLS_SYSCALL)
	  err = TOR_TLS_ERROR;
	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;
    }
361
    err = tor_tls_get_error(tls, r, 1);
Nick Mathewson's avatar
Nick Mathewson committed
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
    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 ... */
380
381
382
    } else {
      return err;
    }
Nick Mathewson's avatar
Nick Mathewson committed
383
  } /* end loop */
384
}
385

386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
/* 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)))
    return 0;
  
  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;
}