tortls.c 20.5 KB
Newer Older
1
2
3
4
/* Copyright 2003 Roger Dingledine. */
/* See LICENSE for licensing information */
/* $Id$ */

Nick Mathewson's avatar
Nick Mathewson committed
5
6
7
8
9
10
/**
 * \file tortls.c
 *
 * \brief TLS wrappers for Tor.
 **/
/* (Unlike other tor functions, these
11
12
 * are prefixed with tor_ in order to avoid conflicting with OpenSSL
 * functions and variables.)
Nick Mathewson's avatar
Nick Mathewson committed
13
 */
14
15
16
17

#include "./crypto.h"
#include "./tortls.h"
#include "./util.h"
Nick Mathewson's avatar
Nick Mathewson committed
18
#include "./log.h"
19
#include <string.h>
20

21
22
23
/* Copied from or.h */
#define LEGAL_NICKNAME_CHARACTERS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

24
25
26
27
28
29
30
#include <assert.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/tls1.h>
#include <openssl/asn1.h>
#include <openssl/bio.h>

Nick Mathewson's avatar
Nick Mathewson committed
31
/** How long do identity certificates live? (sec) */
32
#define IDENTITY_CERT_LIFETIME  (365*24*60*60)
Nick Mathewson's avatar
Nick Mathewson committed
33
/** How much clock skew do we tolerate when checking certificates? (sec) */
34
#define CERT_ALLOW_SKEW (90*60)
Nick Mathewson's avatar
Nick Mathewson committed
35

36
typedef struct tor_tls_context_st {
37
  SSL_CTX *ctx;
38
} tor_tls_context;
39

Nick Mathewson's avatar
Nick Mathewson committed
40
/** Holds a SSL object and its associated data.  Members are only
41
 * accessed from within tortls.c.
42
 */
43
struct tor_tls_st {
44
45
  SSL *ssl; /**< An OpenSSL SSL object. */
  int socket; /**< The underlying file descriptor for this TLS connection. */
46
47
  enum {
    TOR_TLS_ST_HANDSHAKE, TOR_TLS_ST_OPEN, TOR_TLS_ST_GOTCLOSE,
48
    TOR_TLS_ST_SENTCLOSE, TOR_TLS_ST_CLOSED
Nick Mathewson's avatar
Nick Mathewson committed
49
  } state; /**< The current SSL state, depending on which operations have
50
            * completed successfully. */
51
  int isServer;
52
  int wantwrite_n; /**< 0 normally, >0 if we returned wantwrite last time. */
53
54
};

55
static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa,
56
57
58
59
                                        crypto_pk_env_t *rsa_sign,
                                        const char *cname,
                                        const char *cname_sign,
                                        unsigned int lifetime);
60

Nick Mathewson's avatar
Nick Mathewson committed
61
/** Global tls context. We keep it here because nobody else needs to
62
 * touch it. */
63
static tor_tls_context *global_tls_context = NULL;
Nick Mathewson's avatar
Nick Mathewson committed
64
/** True iff tor_tls_init() has been called. */
65
static int tls_library_is_initialized = 0;
66

67
/* Module-internal error codes. */
68
69
70
#define _TOR_TLS_SYSCALL    -6
#define _TOR_TLS_ZERORETURN -5

71
/* These functions are declared in crypto.c but not exported. */
72
EVP_PKEY *_crypto_pk_env_get_evp_pkey(crypto_pk_env_t *env, int private);
73
crypto_pk_env_t *_crypto_new_pk_env_rsa(RSA *rsa);
74
DH *_crypto_dh_env_get_dh(crypto_dh_env_t *dh);
Nick Mathewson's avatar
Nick Mathewson committed
75

Nick Mathewson's avatar
Nick Mathewson committed
76
77
/** Log all pending tls errors at level <b>severity</b>.  Use
 * <b>doing</b> to describe our current activities.
78
 */
Nick Mathewson's avatar
Nick Mathewson committed
79
static void
Nick Mathewson's avatar
Nick Mathewson committed
80
tls_log_errors(int severity, const char *doing)
Nick Mathewson's avatar
Nick Mathewson committed
81
{
Nick Mathewson's avatar
Nick Mathewson committed
82
83
84
85
86
87
88
89
90
91
92
93
  int err;
  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)";
    if (doing) {
      log(severity, "TLS error while %s: %s (in %s:%s)", doing, msg, lib,func);
    } else {
      log(severity, "TLS error: %s (in %s:%s)", msg, lib, func);
    }
Nick Mathewson's avatar
Nick Mathewson committed
94
95
  }
}
96

97
98
99
#define CATCH_SYSCALL 1
#define CATCH_ZERO    2

Nick Mathewson's avatar
Nick Mathewson committed
100
/** Given a TLS object and the result of an SSL_* call, use
101
102
103
104
105
106
 * SSL_get_error to determine whether an error has occurred, and if so
 * which one.  Return one of TOR_TLS_{DONE|WANTREAD|WANTWRITE|ERROR}.
 * If extra&CATCH_SYSCALL is true, return _TOR_TLS_SYSCALL instead of
 * reporting syscall errors.  If extra&CATCH_ZERO is true, return
 * _TOR_TLS_ZERORETURN instead of reporting zero-return errors.
 *
Nick Mathewson's avatar
Nick Mathewson committed
107
108
 * If an error has occurred, log it at level <b>severity</b> and describe the
 * current action as <b>doing</b>.
109
 */
110
static int
111
tor_tls_get_error(tor_tls *tls, int r, int extra,
112
                  const char *doing, int severity)
113
114
115
116
117
118
119
120
121
122
{
  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:
123
      if (extra&CATCH_SYSCALL)
124
        return _TOR_TLS_SYSCALL;
125
126
127
128
129
      if (r == 0)
        log(severity, "TLS error: unexpected close while %s", doing);
      else {
        int e = tor_socket_errno(tls->socket);
        log(severity, "TLS error: <syscall error while %s> (errno=%d: %s)",
130
            doing, e, tor_socket_strerror(e));
131
      }
Nick Mathewson's avatar
Nick Mathewson committed
132
      tls_log_errors(severity, doing);
133
      return TOR_TLS_ERROR;
134
    case SSL_ERROR_ZERO_RETURN:
135
      if (extra&CATCH_ZERO)
136
        return _TOR_TLS_ZERORETURN;
137
      log(severity, "TLS error: Zero return");
Nick Mathewson's avatar
Nick Mathewson committed
138
      tls_log_errors(severity, doing);
139
      return TOR_TLS_ERROR;
140
    default:
Nick Mathewson's avatar
Nick Mathewson committed
141
      tls_log_errors(severity, doing);
142
143
144
145
      return TOR_TLS_ERROR;
  }
}

Nick Mathewson's avatar
Nick Mathewson committed
146
/** Initialize OpenSSL, unless it has already been initialized.
147
 */
148
149
150
151
static void
tor_tls_init() {
  if (!tls_library_is_initialized) {
    SSL_library_init();
152
    SSL_load_error_strings();
Nick Mathewson's avatar
Nick Mathewson committed
153
    crypto_global_init();
154
    OpenSSL_add_all_algorithms();
155
156
157
158
    tls_library_is_initialized = 1;
  }
}

Nick Mathewson's avatar
Nick Mathewson committed
159
/** We need to give OpenSSL a callback to verify certificates. This is
160
161
162
 * it: We always accept peer certs and complete the handshake.  We
 * don't validate them until later.
 */
163
static int always_accept_verify_cb(int preverify_ok,
164
165
166
167
168
                                   X509_STORE_CTX *x509_ctx)
{
  return 1;
}

Nick Mathewson's avatar
Nick Mathewson committed
169
170
171
172
/** Generate and sign an X509 certificate with the public key <b>rsa</b>,
 * signed by the private key <b>rsa_sign</b>.  The commonName of the
 * certificate will be <b>cname</b>; the commonName of the issuer will be
 * <b>cname_sign</b>. The cert will be valid for <b>cert_lifetime</b> seconds
173
174
 * starting from now.  Return a certificate on success, NULL on
 * failure.
175
 */
176
static X509 *
177
tor_tls_create_certificate(crypto_pk_env_t *rsa,
178
179
180
181
                           crypto_pk_env_t *rsa_sign,
                           const char *cname,
                           const char *cname_sign,
                           unsigned int cert_lifetime)
182
183
{
  time_t start_time, end_time;
184
  EVP_PKEY *sign_pkey = NULL, *pkey=NULL;
185
  X509 *x509 = NULL;
186
  X509_NAME *name = NULL, *name_issuer=NULL;
187
  int nid;
188

189
190
  tor_tls_init();

191
192
  start_time = time(NULL);

193
  tor_assert(rsa && cname && rsa_sign && cname_sign);
194
195
196
197
  if (!(sign_pkey = _crypto_pk_env_get_evp_pkey(rsa_sign,1)))
    goto error;
  if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,0)))
    goto error;
198
  if (!(x509 = X509_new()))
199
    goto error;
200
  if (!(X509_set_version(x509, 2)))
201
    goto error;
202
  if (!(ASN1_INTEGER_set(X509_get_serialNumber(x509), (long)start_time)))
203
    goto error;
204

205
  if (!(name = X509_NAME_new()))
206
    goto error;
207
  if ((nid = OBJ_txt2nid("organizationName")) == NID_undef) goto error;
208
  if (!(X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC,
209
                                   "TOR", -1, -1, 0))) goto error;
210
  if ((nid = OBJ_txt2nid("commonName")) == NID_undef) goto error;
211
  if (!(X509_NAME_add_entry_by_NID(name, nid, MBSTRING_ASC,
212
213
214
                                   (char*)cname, -1, -1, 0))) goto error;
  if (!(X509_set_subject_name(x509, name)))
    goto error;
215

216
  if (!(name_issuer = X509_NAME_new()))
217
    goto error;
218
219
220
221
222
223
224
  if ((nid = OBJ_txt2nid("organizationName")) == NID_undef) goto error;
  if (!(X509_NAME_add_entry_by_NID(name_issuer, nid, MBSTRING_ASC,
                                   "TOR", -1, -1, 0))) goto error;
  if ((nid = OBJ_txt2nid("commonName")) == NID_undef) goto error;
  if (!(X509_NAME_add_entry_by_NID(name_issuer, nid, MBSTRING_ASC,
                                (char*)cname_sign, -1, -1, 0))) goto error;
  if (!(X509_set_issuer_name(x509, name_issuer)))
225
    goto error;
226

227
  if (!X509_time_adj(X509_get_notBefore(x509),0,&start_time))
228
    goto error;
229
  end_time = start_time + cert_lifetime;
230
  if (!X509_time_adj(X509_get_notAfter(x509),0,&end_time))
231
    goto error;
232
  if (!X509_set_pubkey(x509, pkey))
233
    goto error;
234
  if (!X509_sign(x509, sign_pkey, EVP_sha1()))
235
    goto error;
236

237
238
  goto done;
 error:
239
  tls_log_errors(LOG_WARN, "generating certificate");
240
  if (x509) {
241
    X509_free(x509);
242
243
    x509 = NULL;
  }
244
 done:
245
246
  if (sign_pkey)
    EVP_PKEY_free(sign_pkey);
247
248
249
250
  if (pkey)
    EVP_PKEY_free(pkey);
  if (name)
    X509_NAME_free(name);
251
252
  if (name_issuer)
    X509_NAME_free(name_issuer);
253
  return x509;
254
255
}

256
257

#ifdef EVERYONE_HAS_AES
Roger Dingledine's avatar
Roger Dingledine committed
258
/* Everybody is running OpenSSL 0.9.7 or later, so no backward compatibility
259
260
261
 * is needed. */
#define CIPHER_LIST TLS1_TXT_DHE_RSA_WITH_AES_128_SHA
#elif defined(TLS1_TXT_DHE_RSA_WITH_AES_128_SHA)
262
/* Some people are running OpenSSL before 0.9.7, but we aren't.
263
264
 * We can support AES and 3DES.
 */
265
#define CIPHER_LIST (TLS1_TXT_DHE_RSA_WITH_AES_128_SHA ":" \
266
                     SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA)
267
268
269
270
271
#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

Nick Mathewson's avatar
Nick Mathewson committed
272
273
274
/** Create a new TLS context.  If we are going to be using it as a
 * server, it must have isServer set to true, <b>identity</b> set to the
 * identity key used to sign that certificate, and <b>nickname</b> set to
275
276
277
278
279
280
281
 * the server's nickname.  If we're only going to be a client,
 * isServer should be false, identity should be NULL, and nickname
 * should be NULL.  Return -1 if failure, else 0.
 *
 * You can call this function multiple times.  Each time you call it,
 * it generates new certificates; all new connections will be begin
 * with the new SSL context.
282
 */
283
int
284
285
286
tor_tls_context_new(crypto_pk_env_t *identity,
                    int isServer, const char *nickname,
                    unsigned int key_lifetime)
287
{
288
  crypto_pk_env_t *rsa = NULL;
289
290
  crypto_dh_env_t *dh = NULL;
  EVP_PKEY *pkey = NULL;
291
292
293
294
  tor_tls_context *result = NULL;
  X509 *cert = NULL, *idcert = NULL;
  char nn2[1024];
  sprintf(nn2, "%s <identity>", nickname);
295

296
297
  tor_tls_init();

298
  if (isServer) {
299
    /* Generate short-term RSA key. */
300
301
302
303
    if (!(rsa = crypto_new_pk_env()))
      goto error;
    if (crypto_pk_generate_key(rsa)<0)
      goto error;
304
    /* Create certificate signed by identity key. */
305
306
    cert = tor_tls_create_certificate(rsa, identity, nickname, nn2,
                                      key_lifetime);
307
    /* Create self-signed certificate for identity key. */
308
309
310
    idcert = tor_tls_create_certificate(identity, identity, nn2, nn2,
                                        IDENTITY_CERT_LIFETIME);
    if (!cert || !idcert) {
Roger Dingledine's avatar
Roger Dingledine committed
311
      log(LOG_WARN, "Error creating certificate");
312
      goto error;
313
314
315
    }
  }

316
  result = tor_malloc(sizeof(tor_tls_context));
317
318
319
  result->ctx = NULL;
#ifdef EVERYONE_HAS_AES
  /* Tell OpenSSL to only use TLS1 */
320
  if (!(result->ctx = SSL_CTX_new(TLSv1_method())))
321
322
323
324
325
326
327
328
329
    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;
330
  if (cert && !SSL_CTX_use_certificate(result->ctx,cert))
331
    goto error;
332
333
  if (idcert && !SSL_CTX_add_extra_chain_cert(result->ctx,idcert))
    goto error;
334
  SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF);
335
  if (isServer) {
336
    tor_assert(rsa);
337
    if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,1)))
338
      goto error;
339
    if (!SSL_CTX_use_PrivateKey(result->ctx, pkey))
340
      goto error;
341
    EVP_PKEY_free(pkey);
342
    pkey = NULL;
343
    if (cert) {
344
      if (!SSL_CTX_check_private_key(result->ctx))
345
        goto error;
346
347
348
    }
  }
  dh = crypto_dh_new();
349
  SSL_CTX_set_tmp_dh(result->ctx, _crypto_dh_env_get_dh(dh));
350
  crypto_dh_free(dh);
351
  SSL_CTX_set_verify(result->ctx, SSL_VERIFY_PEER,
352
                     always_accept_verify_cb);
353
  /* let us realloc bufs that we're writing from */
354
  SSL_CTX_set_mode(result->ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
355
356
357
358
359

  /* Free the old context if one exists. */
  if (global_tls_context) {
    /* This is safe even if there are open connections: OpenSSL does
     * reference counting with SSL and SSL_CTX objects. */
Nick Mathewson's avatar
Nick Mathewson committed
360
361
    SSL_CTX_free(global_tls_context->ctx);
    free(global_tls_context);
362
  }
363
364
  global_tls_context = result;
  return 0;
365
366

 error:
367
  tls_log_errors(LOG_WARN, "creating TLS context");
368
369
  if (pkey)
    EVP_PKEY_free(pkey);
370
371
  if (rsa)
    crypto_free_pk_env(rsa);
372
373
374
375
376
377
  if (dh)
    crypto_dh_free(dh);
  if (result && result->ctx)
    SSL_CTX_free(result->ctx);
  if (result)
    free(result);
378
  /* leak certs XXXX ? */
379
  return -1;
380
381
}

Nick Mathewson's avatar
Nick Mathewson committed
382
383
/** Create a new TLS object from a file descriptor, and a flag to
 * determine whether it is functioning as a server.
384
385
 */
tor_tls *
386
tor_tls_new(int sock, int isServer)
387
388
{
  tor_tls *result = tor_malloc(sizeof(tor_tls));
389
  tor_assert(global_tls_context); /* make sure somebody made it first */
390
  if (!(result->ssl = SSL_new(global_tls_context->ctx)))
391
392
393
394
395
    return NULL;
  result->socket = sock;
  SSL_set_fd(result->ssl, sock);
  result->state = TOR_TLS_ST_HANDSHAKE;
  result->isServer = isServer;
396
  result->wantwrite_n = 0;
397
398
399
  return result;
}

Nick Mathewson's avatar
Nick Mathewson committed
400
/** Release resources associated with a TLS object.  Does not close the
401
402
403
404
405
406
407
408
409
 * underlying file descriptor.
 */
void
tor_tls_free(tor_tls *tls)
{
  SSL_free(tls->ssl);
  free(tls);
}

Nick Mathewson's avatar
Nick Mathewson committed
410
411
412
413
/** Underlying function for TLS reading.  Reads up to <b>len</b>
 * characters from <b>tls</b> into <b>cp</b>.  On success, returns the
 * number of characters read.  On failure, returns TOR_TLS_ERROR,
 * TOR_TLS_CLOSE, TOR_TLS_WANTREAD, or TOR_TLS_WANTWRITE.
414
415
416
417
418
 */
int
tor_tls_read(tor_tls *tls, char *cp, int len)
{
  int r, err;
419
420
  tor_assert(tls && tls->ssl);
  tor_assert(tls->state == TOR_TLS_ST_OPEN);
421
422
423
  r = SSL_read(tls->ssl, cp, len);
  if (r > 0)
    return r;
424
  err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_INFO);
425
  log_fn(LOG_DEBUG,"returned r=%d, err=%d",r,err);
426
  if (err == _TOR_TLS_ZERORETURN) {
427
428
429
    tls->state = TOR_TLS_ST_CLOSED;
    return TOR_TLS_CLOSE;
  } else {
430
    tor_assert(err != TOR_TLS_DONE);
431
432
433
434
    return err;
  }
}

Nick Mathewson's avatar
Nick Mathewson committed
435
436
437
438
/** Underlying function for TLS writing.  Write up to <b>n</b>
 * characters from <b>cp</b> onto <b>tls</b>.  On success, returns the
 * number of characters written.  On failure, returns TOR_TLS_ERROR,
 * TOR_TLS_WANTREAD, or TOR_TLS_WANTWRITE.
439
440
441
442
443
 */
int
tor_tls_write(tor_tls *tls, char *cp, int n)
{
  int r, err;
444
445
  tor_assert(tls && tls->ssl);
  tor_assert(tls->state == TOR_TLS_ST_OPEN);
Nick Mathewson's avatar
Nick Mathewson committed
446
447
  if (n == 0)
    return 0;
448
449
  if(tls->wantwrite_n) {
    /* if WANTWRITE last time, we must use the _same_ n as before */
450
    tor_assert(n >= tls->wantwrite_n);
451
    log_fn(LOG_DEBUG,"resuming pending-write, (%d to flush, reusing %d)",
452
453
454
455
           n, tls->wantwrite_n);
    n = tls->wantwrite_n;
    tls->wantwrite_n = 0;
  }
456
  r = SSL_write(tls->ssl, cp, n);
457
  err = tor_tls_get_error(tls, r, 0, "writing", LOG_INFO);
Nick Mathewson's avatar
Nick Mathewson committed
458
  if (err == TOR_TLS_DONE) {
459
    return r;
460
  }
461
  if (err == TOR_TLS_WANTWRITE || err == TOR_TLS_WANTREAD) {
462
//    log_fn(LOG_INFO,"wantwrite or wantread. remembering the number %d.",n);
463
464
465
    tls->wantwrite_n = n;
  }
  return err;
466
467
}

Nick Mathewson's avatar
Nick Mathewson committed
468
/** Perform initial handshake on <b>tls</b>.  When finished, returns
469
 * TOR_TLS_DONE.  On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD,
470
 * or TOR_TLS_WANTWRITE.
471
472
473
474
475
 */
int
tor_tls_handshake(tor_tls *tls)
{
  int r;
476
477
  tor_assert(tls && tls->ssl);
  tor_assert(tls->state == TOR_TLS_ST_HANDSHAKE);
478
479
480
481
482
  if (tls->isServer) {
    r = SSL_accept(tls->ssl);
  } else {
    r = SSL_connect(tls->ssl);
  }
483
  r = tor_tls_get_error(tls,r,0, "handshaking", LOG_INFO);
484
  if (r == TOR_TLS_DONE) {
485
    tls->state = TOR_TLS_ST_OPEN;
486
  }
487
488
  return r;
}
489

Nick Mathewson's avatar
Nick Mathewson committed
490
/** Shut down an open tls connection <b>tls</b>.  When finished, returns
491
492
493
494
495
496
497
498
 * 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];
499
  tor_assert(tls && tls->ssl);
500

Nick Mathewson's avatar
Nick Mathewson committed
501
502
503
504
505
506
  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 {
507
        r = SSL_read(tls->ssl, buf, 128);
Nick Mathewson's avatar
Nick Mathewson committed
508
      } while (r>0);
509
510
      err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading to shut down",
                              LOG_INFO);
Nick Mathewson's avatar
Nick Mathewson committed
511
      if (err == _TOR_TLS_ZERORETURN) {
512
513
        tls->state = TOR_TLS_ST_GOTCLOSE;
        /* fall through... */
Nick Mathewson's avatar
Nick Mathewson committed
514
      } else {
515
        return err;
Nick Mathewson's avatar
Nick Mathewson committed
516
517
518
519
520
521
522
523
524
      }
    }

    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;
    }
525
526
    err = tor_tls_get_error(tls, r, CATCH_SYSCALL|CATCH_ZERO, "shutting down",
                            LOG_INFO);
Nick Mathewson's avatar
Nick Mathewson committed
527
528
    if (err == _TOR_TLS_SYSCALL) {
      /* The underlying TCP connection closed while we were shutting down. */
529
      tls->state = TOR_TLS_ST_CLOSED;
Nick Mathewson's avatar
Nick Mathewson committed
530
531
532
533
534
535
536
      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.
       */
537
538
539
540
541
      if (tls->state == TOR_TLS_ST_GOTCLOSE ||
         tls->state == TOR_TLS_ST_SENTCLOSE) {
        log(LOG_WARN,
            "TLS returned \"half-closed\" value while already half-closed");
        return TOR_TLS_ERROR;
Nick Mathewson's avatar
Nick Mathewson committed
542
543
544
      }
      tls->state = TOR_TLS_ST_SENTCLOSE;
      /* fall through ... */
545
546
547
    } else {
      return err;
    }
Nick Mathewson's avatar
Nick Mathewson committed
548
  } /* end loop */
549
}
550

Nick Mathewson's avatar
Nick Mathewson committed
551
/** Return true iff this TLS connection is authenticated.
552
553
554
555
556
557
558
559
560
561
562
 */
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;
}

Nick Mathewson's avatar
Nick Mathewson committed
563
/** Return the nickname (if any) that the peer connected on <b>tls</b>
564
565
 * claims to have.
 */
566
567
568
569
570
571
572
int
tor_tls_get_peer_cert_nickname(tor_tls *tls, char *buf, int buflen)
{
  X509 *cert = NULL;
  X509_NAME *name = NULL;
  int nid;
  int lenout;
573

574
  if (!(cert = SSL_get_peer_certificate(tls->ssl))) {
Roger Dingledine's avatar
Roger Dingledine committed
575
    log_fn(LOG_WARN, "Peer has no certificate");
576
    goto error;
577
578
  }
  if (!(name = X509_get_subject_name(cert))) {
Roger Dingledine's avatar
Roger Dingledine committed
579
    log_fn(LOG_WARN, "Peer certificate has no subject name");
580
    goto error;
581
582
  }
  if ((nid = OBJ_txt2nid("commonName")) == NID_undef)
583
    goto error;
584

585
586
  lenout = X509_NAME_get_text_by_NID(name, nid, buf, buflen);
  if (lenout == -1)
587
    goto error;
588
  if (((int)strspn(buf, LEGAL_NICKNAME_CHARACTERS)) < lenout) {
Roger Dingledine's avatar
Roger Dingledine committed
589
    log_fn(LOG_WARN, "Peer certificate nickname has illegal characters.");
590
    goto error;
591
592
  }
  return 0;
593
594
595
596
597
598
 error:
  if (cert)
    X509_free(cert);
  if (name)
    X509_NAME_free(name);
  return -1;
599
600
}

Nick Mathewson's avatar
Nick Mathewson committed
601
/** If the provided tls connection is authenticated and has a
602
 * certificate that is currently valid and is correctly signed by
Nick Mathewson's avatar
Nick Mathewson committed
603
 * <b>identity_key</b>, return 0.  Else, return -1.
604
 */
605
606
int
tor_tls_verify(tor_tls *tls, crypto_pk_env_t *identity_key)
607
608
{
  X509 *cert = NULL;
609
  EVP_PKEY *id_pkey = NULL;
Nick Mathewson's avatar
Nick Mathewson committed
610
  time_t now, t;
611
612
  int r = -1;

613
  if (!(cert = SSL_get_peer_certificate(tls->ssl)))
614
    return -1;
615

616
  now = time(NULL);
617
  t = now + CERT_ALLOW_SKEW;
Nick Mathewson's avatar
Nick Mathewson committed
618
619
  if (X509_cmp_time(X509_get_notBefore(cert), &t) > 0) {
    log_fn(LOG_WARN,"Certificate becomes valid in the future: possible clock skew.");
620
    goto done;
621
  }
622
  t = now - CERT_ALLOW_SKEW;
Nick Mathewson's avatar
Nick Mathewson committed
623
624
  if (X509_cmp_time(X509_get_notAfter(cert), &t) < 0) {
    log_fn(LOG_WARN,"Certificate already expired; possible clock skew.");
625
    goto done;
626
  }
627

628
  /* Get the public key. */
629
630
  if (!(id_pkey = _crypto_pk_env_get_evp_pkey(identity_key,0)) ||
      X509_verify(cert, id_pkey) <= 0) {
631
    log_fn(LOG_WARN,"X509_verify on cert and pkey returned <= 0");
632
    tls_log_errors(LOG_WARN,"verifying certificate");
633
    goto done;
634
  }
635

636
  r = 0;
637

638
639
640
 done:
  if (cert)
    X509_free(cert);
641
642
  if (id_pkey)
    EVP_PKEY_free(id_pkey);
643

644
  /* XXXX This should never get invoked, but let's make sure for now. */
645
646
  tls_log_errors(LOG_WARN, "finishing tor_tls_verify");

647
648
  return r;
}
649

Nick Mathewson's avatar
Nick Mathewson committed
650
651
/** Return the number of bytes available for reading from <b>tls</b>.
 */
652
int
653
tor_tls_get_pending_bytes(tor_tls *tls)
654
{
655
  tor_assert(tls);
656
657
658
659
660
661
#if OPENSSL_VERSION_NUMBER < 0x0090700fl
  if (tls->ssl->rstate == SSL_ST_READ_BODY)
    return 0;
  if (tls->ssl->s3->rrec.type != SSL3_RT_APPLICATION_DATA)
    return 0;
#endif
662
  return SSL_pending(tls->ssl);
663

664
}
665

Nick Mathewson's avatar
Nick Mathewson committed
666
/** Return the number of bytes read across the underlying socket. */
667
668
unsigned long tor_tls_get_n_bytes_read(tor_tls *tls)
{
669
  tor_assert(tls);
670
671
  return BIO_number_read(SSL_get_rbio(tls->ssl));
}
Nick Mathewson's avatar
Nick Mathewson committed
672
/** Return the number of bytes written across the underlying socket. */
673
674
unsigned long tor_tls_get_n_bytes_written(tor_tls *tls)
{
675
  tor_assert(tls);
676
677
  return BIO_number_written(SSL_get_wbio(tls->ssl));
}
678

Nick Mathewson's avatar
Nick Mathewson committed
679
/** Implement assert_no_tls_errors: If there are any pending OpenSSL
680
 * errors, log an error message and assert(0). */
681
682
683
684
685
686
687
688
689
690
691
void _assert_no_tls_errors(const char *fname, int line)
{
  if (ERR_peek_error() == 0)
    return;
  log_fn(LOG_ERR, "Unhandled OpenSSL errors found at %s:%d: ",
         fname, line);
  tls_log_errors(LOG_ERR, NULL);

  tor_assert(0);
}

692
693
694
695
696
697
698
/*
  Local Variables:
  mode:c
  indent-tabs-mode:nil
  c-basic-offset:2
  End:
*/