Back to index

tor  0.2.3.18-rc
Defines | Typedefs | Functions
tortls.h File Reference

Headers for tortls.c. More...

#include "crypto.h"
#include "compat.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define _MIN_TOR_TLS_ERROR_VAL   -9
#define TOR_TLS_ERROR_MISC   -9
#define TOR_TLS_ERROR_IO   -8
#define TOR_TLS_ERROR_CONNREFUSED   -7
#define TOR_TLS_ERROR_CONNRESET   -6
#define TOR_TLS_ERROR_NO_ROUTE   -5
#define TOR_TLS_ERROR_TIMEOUT   -4
#define TOR_TLS_CLOSE   -3
#define TOR_TLS_WANTREAD   -2
#define TOR_TLS_WANTWRITE   -1
#define TOR_TLS_DONE   0
#define CASE_TOR_TLS_ERROR_ANY_NONIO
 Collection of case statements for all TLS errors that are not due to underlying IO failure.
#define CASE_TOR_TLS_ERROR_ANY
 Use this macro in a switch statement to catch any TLS error.
#define TOR_TLS_IS_ERROR(rv)   ((rv) < TOR_TLS_CLOSE)
#define check_no_tls_errors()   _check_no_tls_errors(__FILE__,__LINE__)

Typedefs

typedef struct tor_tls_t
typedef struct tor_cert_t

Functions

const char * tor_tls_err_to_string (int err)
 Given a TOR_TLS_* error code, return a string equivalent.
void tor_tls_get_state_description (tor_tls_t *tls, char *buf, size_t sz)
 Write a description of the current state of tls into the sz-byte buffer at buf.
void tor_tls_free_all (void)
 Free all global TLS structures.
int tor_tls_context_init (int is_public_server, crypto_pk_t *client_identity, crypto_pk_t *server_identity, unsigned int key_lifetime)
 Create new global client and server TLS contexts.
tor_tls_ttor_tls_new (int sock, int is_server)
 Create a new TLS object from a file descriptor, and a flag to determine whether it is functioning as a server.
void tor_tls_set_logged_address (tor_tls_t *tls, const char *address)
 Make future log messages about tls display the address address.
void tor_tls_set_renegotiate_callback (tor_tls_t *tls, void(*cb)(tor_tls_t *, void *arg), void *arg)
 Set cb to be called with argument arg whenever tls next gets a client-side renegotiate in the middle of a read.
int tor_tls_is_server (tor_tls_t *tls)
 Return whether this tls initiated the connect (client) or received it (server).
void tor_tls_free (tor_tls_t *tls)
 Release resources associated with a TLS object.
int tor_tls_peer_has_cert (tor_tls_t *tls)
 Return true iff this TLS connection is authenticated.
tor_cert_ttor_tls_get_peer_cert (tor_tls_t *tls)
 Return the peer certificate, or NULL if there isn't one.
int tor_tls_verify (int severity, tor_tls_t *tls, crypto_pk_t **identity)
 If the provided tls connection is authenticated and has a certificate chain that is currently valid and signed, then set *identity_key to the identity certificate's key and return 0.
int tor_tls_check_lifetime (int severity, tor_tls_t *tls, int past_tolerance, int future_tolerance)
 Check whether the certificate set on the connection tls is expired give or take past_tolerance seconds, or not-yet-valid give or take future_tolerance seconds.
int tor_tls_read (tor_tls_t *tls, char *cp, size_t len)
 Underlying function for TLS reading.
int tor_tls_write (tor_tls_t *tls, const char *cp, size_t n)
 Underlying function for TLS writing.
int tor_tls_handshake (tor_tls_t *tls)
 Perform initial handshake on tls.
int tor_tls_finish_handshake (tor_tls_t *tls)
 Perform the final part of the intial TLS handshake on tls.
int tor_tls_renegotiate (tor_tls_t *tls)
 Client only: Renegotiate a TLS session.
void tor_tls_unblock_renegotiation (tor_tls_t *tls)
 If this version of openssl requires it, turn on renegotiation on tls.
void tor_tls_block_renegotiation (tor_tls_t *tls)
 If this version of openssl supports it, turn off renegotiation on tls.
void tor_tls_assert_renegotiation_unblocked (tor_tls_t *tls)
 Assert that the flags that allow legacy renegotiation are still set.
int tor_tls_shutdown (tor_tls_t *tls)
 Shut down an open tls connection tls.
int tor_tls_get_pending_bytes (tor_tls_t *tls)
 Return the number of bytes available for reading from tls.
size_t tor_tls_get_forced_write_size (tor_tls_t *tls)
 If tls requires that the next write be of a particular size, return that size.
void tor_tls_get_n_raw_bytes (tor_tls_t *tls, size_t *n_read, size_t *n_written)
 Sets n_read and n_written to the number of bytes read and written, respectively, on the raw socket used by tls since the last time this function was called on tls.
void tor_tls_get_buffer_sizes (tor_tls_t *tls, size_t *rbuf_capacity, size_t *rbuf_bytes, size_t *wbuf_capacity, size_t *wbuf_bytes)
 Examine the amount of memory used and available for buffers in tls.
int tor_tls_used_v1_handshake (tor_tls_t *tls)
 Return true iff the initial TLS connection at tls did not use a v2 TLS handshake.
int tor_tls_received_v3_certificate (tor_tls_t *tls)
 Return true iff the peer certificate we're received on tls indicates that this connection should use the v3 (in-protocol) authentication handshake.
int tor_tls_get_num_server_handshakes (tor_tls_t *tls)
 Return the number of server handshakes that we've noticed doing on tls.
int tor_tls_server_got_renegotiate (tor_tls_t *tls)
 Return true iff the server TLS connection tls got the renegotiation request it was waiting for.
int tor_tls_get_tlssecrets (tor_tls_t *tls, uint8_t *secrets_out)
 Set the DIGEST256_LEN buffer at secrets_out to the value used in the v3 handshake to prove that the client knows the TLS secrets for the connection tls.
void _check_no_tls_errors (const char *fname, int line)
 Implement check_no_tls_errors: If there are any pending OpenSSL errors, log an error message.
void tor_tls_log_one_error (tor_tls_t *tls, unsigned long err, int severity, int domain, const char *doing)
 Log a single error err as returned by ERR_get_error(), which was received while performing an operation doing on tls.
void tor_cert_free (tor_cert_t *cert)
 Free all storage held in cert
tor_cert_ttor_cert_decode (const uint8_t *certificate, size_t certificate_len)
 Read a DER-encoded X509 cert, of length exactly certificate_len, from a certificate.
void tor_cert_get_der (const tor_cert_t *cert, const uint8_t **encoded_out, size_t *size_out)
 Set *encoded_out and *size_out to cert's encoded DER representation and length, respectively.
const digests_ttor_cert_get_id_digests (const tor_cert_t *cert)
 Return a set of digests for the public key in cert, or NULL if this cert's public key is not one we know how to take the digest of.
const digests_ttor_cert_get_cert_digests (const tor_cert_t *cert)
 Return a set of digests for the public key in cert.
int tor_tls_get_my_certs (int server, const tor_cert_t **link_cert_out, const tor_cert_t **id_cert_out)
 Set *link_cert_out and *id_cert_out to the link certificate and ID certificate that we're currently using for our V3 in-protocol handshake's certificate chain.
crypto_pk_ttor_tls_get_my_client_auth_key (void)
 Return the authentication key that we use to authenticate ourselves as a client in the V3 in-protocol handshake.
crypto_pk_ttor_tls_cert_get_key (tor_cert_t *cert)
 Return a newly allocated copy of the public key that a certificate certifies.
int tor_tls_cert_matches_key (const tor_tls_t *tls, const tor_cert_t *cert)
 Return true iff the other side of tls has authenticated to us, and the key certified in cert is the same as the key they used to do it.
int tor_tls_cert_is_valid (int severity, const tor_cert_t *cert, const tor_cert_t *signing_cert, int check_rsa_1024)
 Check whether cert is well-formed, currently live, and correctly signed by the public key in signing_cert.

Detailed Description

Headers for tortls.c.

Definition in file tortls.h.


Define Documentation

#define _MIN_TOR_TLS_ERROR_VAL   -9

Definition at line 24 of file tortls.h.

Value:

Use this macro in a switch statement to catch any TLS error.

That way, if more errors are added, your switches will still work.

Definition at line 48 of file tortls.h.

Value:

Collection of case statements for all TLS errors that are not due to underlying IO failure.

Definition at line 39 of file tortls.h.

#define check_no_tls_errors ( )    _check_no_tls_errors(__FILE__,__LINE__)

Definition at line 101 of file tortls.h.

#define TOR_TLS_CLOSE   -3

Definition at line 32 of file tortls.h.

#define TOR_TLS_DONE   0

Definition at line 35 of file tortls.h.

#define TOR_TLS_ERROR_CONNREFUSED   -7

Definition at line 28 of file tortls.h.

#define TOR_TLS_ERROR_CONNRESET   -6

Definition at line 29 of file tortls.h.

#define TOR_TLS_ERROR_IO   -8

Definition at line 27 of file tortls.h.

#define TOR_TLS_ERROR_MISC   -9

Definition at line 25 of file tortls.h.

#define TOR_TLS_ERROR_NO_ROUTE   -5

Definition at line 30 of file tortls.h.

#define TOR_TLS_ERROR_TIMEOUT   -4

Definition at line 31 of file tortls.h.

#define TOR_TLS_IS_ERROR (   rv)    ((rv) < TOR_TLS_CLOSE)

Definition at line 52 of file tortls.h.

#define TOR_TLS_WANTREAD   -2

Definition at line 33 of file tortls.h.

#define TOR_TLS_WANTWRITE   -1

Definition at line 34 of file tortls.h.


Typedef Documentation

typedef struct tor_cert_t

Definition at line 21 of file tortls.h.

typedef struct tor_tls_t

Definition at line 18 of file tortls.h.


Function Documentation

void _check_no_tls_errors ( const char *  fname,
int  line 
)

Implement check_no_tls_errors: If there are any pending OpenSSL errors, log an error message.

Definition at line 2289 of file tortls.c.

{
  if (ERR_peek_error() == 0)
    return;
  log(LOG_WARN, LD_CRYPTO, "Unhandled OpenSSL errors found at %s:%d: ",
      tor_fix_source_file(fname), line);
  tls_log_errors(NULL, LOG_WARN, LD_NET, NULL);
}

Here is the call graph for this function:

tor_cert_t* tor_cert_decode ( const uint8_t *  certificate,
size_t  certificate_len 
)

Read a DER-encoded X509 cert, of length exactly certificate_len, from a certificate.

Return a newly allocated tor_cert_t on success and NULL on failure.

Definition at line 771 of file tortls.c.

{
  X509 *x509;
  const unsigned char *cp = (const unsigned char *)certificate;
  tor_cert_t *newcert;
  tor_assert(certificate);

  if (certificate_len > INT_MAX)
    return NULL;

#if OPENSSL_VERSION_NUMBER < OPENSSL_V_SERIES(0,9,8)
  /* This ifdef suppresses a type warning.  Take out this case once everybody
   * is using OpenSSL 0.9.8 or later. */
  x509 = d2i_X509(NULL, (unsigned char**)&cp, (int)certificate_len);
#else
  x509 = d2i_X509(NULL, &cp, (int)certificate_len);
#endif
  if (!x509)
    return NULL; /* Couldn't decode */
  if (cp - certificate != (int)certificate_len) {
    X509_free(x509);
    return NULL; /* Didn't use all the bytes */
  }
  newcert = tor_cert_new(x509);
  if (!newcert) {
    return NULL;
  }
  if (newcert->encoded_len != certificate_len ||
      fast_memneq(newcert->encoded, certificate, certificate_len)) {
    /* Cert wasn't in DER */
    tor_cert_free(newcert);
    return NULL;
  }
  return newcert;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void tor_cert_free ( tor_cert_t cert)

Free all storage held in cert

Definition at line 709 of file tortls.c.

{
  if (! cert)
    return;
  if (cert->cert)
    X509_free(cert->cert);
  tor_free(cert->encoded);
  memset(cert, 0x03, sizeof(*cert));
  tor_free(cert);
}

Here is the caller graph for this function:

Return a set of digests for the public key in cert.

Definition at line 833 of file tortls.c.

{
  return &cert->cert_digests;
}

Here is the caller graph for this function:

void tor_cert_get_der ( const tor_cert_t cert,
const uint8_t **  encoded_out,
size_t *  size_out 
)

Set *encoded_out and *size_out to cert's encoded DER representation and length, respectively.

Definition at line 810 of file tortls.c.

{
  tor_assert(cert);
  tor_assert(encoded_out);
  tor_assert(size_out);
  *encoded_out = cert->encoded;
  *size_out = cert->encoded_len;
}

Here is the caller graph for this function:

const digests_t* tor_cert_get_id_digests ( const tor_cert_t cert)

Return a set of digests for the public key in cert, or NULL if this cert's public key is not one we know how to take the digest of.

Definition at line 823 of file tortls.c.

{
  if (cert->pkey_digests_set)
    return &cert->pkey_digests;
  else
    return NULL;
}

Here is the caller graph for this function:

Assert that the flags that allow legacy renegotiation are still set.

Definition at line 1686 of file tortls.c.

{
  if (use_unsafe_renegotiation_flag) {
    tor_assert(0 != (tls->ssl->s3->flags &
                     SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
  }
  if (use_unsafe_renegotiation_op) {
    long options = SSL_get_options(tls->ssl);
    tor_assert(0 != (options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
  }
}

If this version of openssl supports it, turn off renegotiation on tls.

(Our protocol never requires this for security, but it's nice to use belt-and-suspenders here.)

Definition at line 1679 of file tortls.c.

Here is the caller graph for this function:

Return a newly allocated copy of the public key that a certificate certifies.

Return NULL if the cert's key is not RSA.

Definition at line 892 of file tortls.c.

{
  crypto_pk_t *result = NULL;
  EVP_PKEY *pkey = X509_get_pubkey(cert->cert);
  RSA *rsa;
  if (!pkey)
    return NULL;
  rsa = EVP_PKEY_get1_RSA(pkey);
  if (!rsa) {
    EVP_PKEY_free(pkey);
    return NULL;
  }
  result = _crypto_new_pk_from_rsa(rsa);
  EVP_PKEY_free(pkey);
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tor_tls_cert_is_valid ( int  severity,
const tor_cert_t cert,
const tor_cert_t signing_cert,
int  check_rsa_1024 
)

Check whether cert is well-formed, currently live, and correctly signed by the public key in signing_cert.

If check_rsa_1024, make sure that it has an RSA key with 1024 bits; otherwise, just check that the key is long enough. Return 1 if the cert is good, and 0 if it's bad or we couldn't check it.

Definition at line 966 of file tortls.c.

{
  EVP_PKEY *cert_key;
  EVP_PKEY *signing_key = X509_get_pubkey(signing_cert->cert);
  int r, key_ok = 0;
  if (!signing_key)
    return 0;
  r = X509_verify(cert->cert, signing_key);
  EVP_PKEY_free(signing_key);
  if (r <= 0)
    return 0;

  /* okay, the signature checked out right.  Now let's check the check the
   * lifetime. */
  if (check_cert_lifetime_internal(severity, cert->cert,
                                   48*60*60, 30*24*60*60) < 0)
    return 0;

  cert_key = X509_get_pubkey(cert->cert);
  if (check_rsa_1024 && cert_key) {
    RSA *rsa = EVP_PKEY_get1_RSA(cert_key);
    if (rsa && BN_num_bits(rsa->n) == 1024)
      key_ok = 1;
    if (rsa)
      RSA_free(rsa);
  } else if (cert_key) {
    int min_bits = 1024;
#ifdef EVP_PKEY_EC
    if (EVP_PKEY_type(cert_key->type) == EVP_PKEY_EC)
      min_bits = 128;
#endif
    if (EVP_PKEY_bits(cert_key) >= min_bits)
      key_ok = 1;
  }
  EVP_PKEY_free(cert_key);
  if (!key_ok)
    return 0;

  /* XXXX compare DNs or anything? */

  return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tor_tls_cert_matches_key ( const tor_tls_t tls,
const tor_cert_t cert 
)

Return true iff the other side of tls has authenticated to us, and the key certified in cert is the same as the key they used to do it.

Definition at line 938 of file tortls.c.

{
  X509 *peercert = SSL_get_peer_certificate(tls->ssl);
  EVP_PKEY *link_key = NULL, *cert_key = NULL;
  int result;

  if (!peercert)
    return 0;
  link_key = X509_get_pubkey(peercert);
  cert_key = X509_get_pubkey(cert->cert);

  result = link_key && cert_key && pkey_eq(cert_key, link_key);

  X509_free(peercert);
  if (link_key)
    EVP_PKEY_free(link_key);
  if (cert_key)
    EVP_PKEY_free(cert_key);

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tor_tls_check_lifetime ( int  severity,
tor_tls_t tls,
int  past_tolerance,
int  future_tolerance 
)

Check whether the certificate set on the connection tls is expired give or take past_tolerance seconds, or not-yet-valid give or take future_tolerance seconds.

Return 0 for valid, -1 for failure.

NOTE: you should call tor_tls_verify before tor_tls_check_lifetime.

Definition at line 2183 of file tortls.c.

{
  X509 *cert;
  int r = -1;

  if (!(cert = SSL_get_peer_certificate(tls->ssl)))
    goto done;

  if (check_cert_lifetime_internal(severity, cert,
                                   past_tolerance, future_tolerance) < 0)
    goto done;

  r = 0;
 done:
  if (cert)
    X509_free(cert);
  /* Not expected to get invoked */
  tls_log_errors(tls, LOG_WARN, LD_NET, "checking certificate lifetime");

  return r;
}

Here is the call graph for this function:

int tor_tls_context_init ( int  is_public_server,
crypto_pk_t client_identity,
crypto_pk_t server_identity,
unsigned int  key_lifetime 
)

Create new global client and server TLS contexts.

If server_identity is NULL, this will not generate a server TLS context. If is_public_server is non-zero, this will use the same TLS context for incoming and outgoing connections, and ignore client_identity.

Definition at line 1026 of file tortls.c.

{
  int rv1 = 0;
  int rv2 = 0;

  if (is_public_server) {
    tor_tls_context_t *new_ctx;
    tor_tls_context_t *old_ctx;

    tor_assert(server_identity != NULL);

    rv1 = tor_tls_context_init_one(&server_tls_context,
                                   server_identity,
                                   key_lifetime, 0);

    if (rv1 >= 0) {
      new_ctx = server_tls_context;
      tor_tls_context_incref(new_ctx);
      old_ctx = client_tls_context;
      client_tls_context = new_ctx;

      if (old_ctx != NULL) {
        tor_tls_context_decref(old_ctx);
      }
    }
  } else {
    if (server_identity != NULL) {
      rv1 = tor_tls_context_init_one(&server_tls_context,
                                     server_identity,
                                     key_lifetime,
                                     0);
    } else {
      tor_tls_context_t *old_ctx = server_tls_context;
      server_tls_context = NULL;

      if (old_ctx != NULL) {
        tor_tls_context_decref(old_ctx);
      }
    }

    rv2 = tor_tls_context_init_one(&client_tls_context,
                                   client_identity,
                                   key_lifetime,
                                   1);
  }

  return MIN(rv1, rv2);
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* tor_tls_err_to_string ( int  err)

Given a TOR_TLS_* error code, return a string equivalent.

Definition at line 372 of file tortls.c.

{
  if (err >= 0)
    return "[Not an error.]";
  switch (err) {
    case TOR_TLS_ERROR_MISC: return "misc error";
    case TOR_TLS_ERROR_IO: return "unexpected close";
    case TOR_TLS_ERROR_CONNREFUSED: return "connection refused";
    case TOR_TLS_ERROR_CONNRESET: return "connection reset";
    case TOR_TLS_ERROR_NO_ROUTE: return "host unreachable";
    case TOR_TLS_ERROR_TIMEOUT: return "connection timed out";
    case TOR_TLS_CLOSE: return "closed";
    case TOR_TLS_WANTREAD: return "want to read";
    case TOR_TLS_WANTWRITE: return "want to write";
    default: return "(unknown error code)";
  }
}

Here is the caller graph for this function:

Perform the final part of the intial TLS handshake on tls.

This should be called for the first handshake only: it determines whether the v1 or the v2 handshake was used, and adjusts things for the renegotiation handshake as appropriate.

tor_tls_handshake() calls this on its own; you only need to call this if bufferevent is doing the handshake for you.

Definition at line 1852 of file tortls.c.

{
  int r = TOR_TLS_DONE;
  if (tls->isServer) {
    SSL_set_info_callback(tls->ssl, NULL);
    SSL_set_verify(tls->ssl, SSL_VERIFY_PEER, always_accept_verify_cb);
    /* There doesn't seem to be a clear OpenSSL API to clear mode flags. */
    tls->ssl->mode &= ~SSL_MODE_NO_AUTO_CHAIN;
#ifdef V2_HANDSHAKE_SERVER
    if (tor_tls_client_is_using_v2_ciphers(tls->ssl, ADDR(tls))) {
      /* This check is redundant, but back when we did it in the callback,
       * we might have not been able to look up the tor_tls_t if the code
       * was buggy.  Fixing that. */
      if (!tls->wasV2Handshake) {
        log_warn(LD_BUG, "For some reason, wasV2Handshake didn't"
                 " get set. Fixing that.");
      }
      tls->wasV2Handshake = 1;
      log_debug(LD_HANDSHAKE, "Completed V2 TLS handshake with client; waiting"
                " for renegotiation.");
    } else {
      tls->wasV2Handshake = 0;
    }
#endif
  } else {
#ifdef V2_HANDSHAKE_CLIENT
    /* If we got no ID cert, we're a v2 handshake. */
    X509 *cert = SSL_get_peer_certificate(tls->ssl);
    STACK_OF(X509) *chain = SSL_get_peer_cert_chain(tls->ssl);
    int n_certs = sk_X509_num(chain);
    if (n_certs > 1 || (n_certs == 1 && cert != sk_X509_value(chain, 0))) {
      log_debug(LD_HANDSHAKE, "Server sent back multiple certificates; it "
                "looks like a v1 handshake on %p", tls);
      tls->wasV2Handshake = 0;
    } else {
      log_debug(LD_HANDSHAKE,
                "Server sent back a single certificate; looks like "
                "a v2 handshake on %p.", tls);
      tls->wasV2Handshake = 1;
    }
    if (cert)
      X509_free(cert);
#endif
    if (SSL_set_cipher_list(tls->ssl, SERVER_CIPHER_LIST) == 0) {
      tls_log_errors(NULL, LOG_WARN, LD_HANDSHAKE, "re-setting ciphers");
      r = TOR_TLS_ERROR_MISC;
    }
  }
  return r;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void tor_tls_free ( tor_tls_t tls)

Release resources associated with a TLS object.

Does not close the underlying file descriptor.

Definition at line 1711 of file tortls.c.

{
  if (!tls)
    return;
  tor_assert(tls->ssl);
#ifdef SSL_set_tlsext_host_name
  SSL_set_tlsext_host_name(tls->ssl, NULL);
#endif
  SSL_free(tls->ssl);
  tls->ssl = NULL;
  tls->negotiated_callback = NULL;
  if (tls->context)
    tor_tls_context_decref(tls->context);
  tor_free(tls->address);
  tls->magic = 0x99999999;
  tor_free(tls);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void tor_tls_free_all ( void  )

Free all global TLS structures.

Definition at line 516 of file tortls.c.

{
  if (server_tls_context) {
    tor_tls_context_t *ctx = server_tls_context;
    server_tls_context = NULL;
    tor_tls_context_decref(ctx);
  }
  if (client_tls_context) {
    tor_tls_context_t *ctx = client_tls_context;
    client_tls_context = NULL;
    tor_tls_context_decref(ctx);
  }
#ifdef V2_HANDSHAKE_CLIENT
  if (CLIENT_CIPHER_DUMMIES)
    tor_free(CLIENT_CIPHER_DUMMIES);
  if (CLIENT_CIPHER_STACK)
    sk_SSL_CIPHER_free(CLIENT_CIPHER_STACK);
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

void tor_tls_get_buffer_sizes ( tor_tls_t tls,
size_t *  rbuf_capacity,
size_t *  rbuf_bytes,
size_t *  wbuf_capacity,
size_t *  wbuf_bytes 
)

Examine the amount of memory used and available for buffers in tls.

Set *rbuf_capacity to the amount of storage allocated for the read buffer and *rbuf_bytes to the amount actually used. Set *wbuf_capacity to the amount of storage allocated for the write buffer and *wbuf_bytes to the amount actually used.

Definition at line 2453 of file tortls.c.

{
  if (tls->ssl->s3->rbuf.buf)
    *rbuf_capacity = tls->ssl->s3->rbuf.len;
  else
    *rbuf_capacity = 0;
  if (tls->ssl->s3->wbuf.buf)
    *wbuf_capacity = tls->ssl->s3->wbuf.len;
  else
    *wbuf_capacity = 0;
  *rbuf_bytes = tls->ssl->s3->rbuf.left;
  *wbuf_bytes = tls->ssl->s3->wbuf.left;
}

Here is the caller graph for this function:

If tls requires that the next write be of a particular size, return that size.

Otherwise, return 0.

Definition at line 2244 of file tortls.c.

{
  return tls->wantwrite_n;
}

Here is the caller graph for this function:

int tor_tls_get_my_certs ( int  server,
const tor_cert_t **  link_cert_out,
const tor_cert_t **  id_cert_out 
)

Set *link_cert_out and *id_cert_out to the link certificate and ID certificate that we're currently using for our V3 in-protocol handshake's certificate chain.

If server is true, provide the certs that we use in server mode; otherwise, provide the certs that we use in client mode.

Definition at line 861 of file tortls.c.

{
  tor_tls_context_t *ctx = server ? server_tls_context : client_tls_context;
  if (! ctx)
    return -1;
  if (link_cert_out)
    *link_cert_out = server ? ctx->my_link_cert : ctx->my_auth_cert;
  if (id_cert_out)
    *id_cert_out = ctx->my_id_cert;
  return 0;
}

Here is the caller graph for this function:

Return the authentication key that we use to authenticate ourselves as a client in the V3 in-protocol handshake.

Definition at line 880 of file tortls.c.

{
  if (! client_tls_context)
    return NULL;
  return client_tls_context->auth_key;
}

Here is the caller graph for this function:

void tor_tls_get_n_raw_bytes ( tor_tls_t tls,
size_t *  n_read,
size_t *  n_written 
)

Sets n_read and n_written to the number of bytes read and written, respectively, on the raw socket used by tls since the last time this function was called on tls.

Definition at line 2253 of file tortls.c.

{
  BIO *wbio, *tmpbio;
  unsigned long r, w;
  r = BIO_number_read(SSL_get_rbio(tls->ssl));
  /* We want the number of bytes actually for real written.  Unfortunately,
   * sometimes OpenSSL replaces the wbio on tls->ssl with a buffering bio,
   * which makes the answer turn out wrong.  Let's cope with that.  Note
   * that this approach will fail if we ever replace tls->ssl's BIOs with
   * buffering bios for reasons of our own.  As an alternative, we could
   * save the original BIO for  tls->ssl in the tor_tls_t structure, but
   * that would be tempting fate. */
  wbio = SSL_get_wbio(tls->ssl);
  if (wbio->method == BIO_f_buffer() && (tmpbio = BIO_next(wbio)) != NULL)
    wbio = tmpbio;
  w = BIO_number_written(wbio);

  /* We are ok with letting these unsigned ints go "negative" here:
   * If we wrapped around, this should still give us the right answer, unless
   * we wrapped around by more than ULONG_MAX since the last time we called
   * this function.
   */
  *n_read = (size_t)(r - tls->last_read_count);
  *n_written = (size_t)(w - tls->last_write_count);
  if (*n_read > INT_MAX || *n_written > INT_MAX) {
    log_warn(LD_BUG, "Preposterously large value in tor_tls_get_n_raw_bytes. "
             "r=%lu, last_read=%lu, w=%lu, last_written=%lu",
             r, tls->last_read_count, w, tls->last_write_count);
  }
  tls->last_read_count = r;
  tls->last_write_count = w;
}

Here is the caller graph for this function:

Return the number of server handshakes that we've noticed doing on tls.

Definition at line 2404 of file tortls.c.

{
  return tls->server_handshake_count;
}

Return the peer certificate, or NULL if there isn't one.

Definition at line 2025 of file tortls.c.

{
  X509 *cert;
  cert = SSL_get_peer_certificate(tls->ssl);
  tls_log_errors(tls, LOG_WARN, LD_HANDSHAKE, "getting peer certificate");
  if (!cert)
    return NULL;
  return tor_cert_new(cert);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return the number of bytes available for reading from tls.

Definition at line 2235 of file tortls.c.

{
  tor_assert(tls);
  return SSL_pending(tls->ssl);
}

Here is the caller graph for this function:

void tor_tls_get_state_description ( tor_tls_t tls,
char *  buf,
size_t  sz 
)

Write a description of the current state of tls into the sz-byte buffer at buf.

Definition at line 243 of file tortls.c.

{
  const char *ssl_state;
  const char *tortls_state;

  if (PREDICT_UNLIKELY(!tls || !tls->ssl)) {
    strlcpy(buf, "(No SSL object)", sz);
    return;
  }

  ssl_state = SSL_state_string_long(tls->ssl);
  switch (tls->state) {
#define CASE(st) case TOR_TLS_ST_##st: tortls_state = " in "#st ; break
    CASE(HANDSHAKE);
    CASE(OPEN);
    CASE(GOTCLOSE);
    CASE(SENTCLOSE);
    CASE(CLOSED);
    CASE(RENEGOTIATE);
#undef CASE
  case TOR_TLS_ST_BUFFEREVENT:
    tortls_state = "";
    break;
  default:
    tortls_state = " in unknown TLS state";
    break;
  }

  tor_snprintf(buf, sz, "%s%s", ssl_state, tortls_state);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tor_tls_get_tlssecrets ( tor_tls_t tls,
uint8_t *  secrets_out 
)

Set the DIGEST256_LEN buffer at secrets_out to the value used in the v3 handshake to prove that the client knows the TLS secrets for the connection tls.

Return 0 on success, -1 on failure.

Definition at line 2422 of file tortls.c.

{
#define TLSSECRET_MAGIC "Tor V3 handshake TLS cross-certification"
  char buf[128];
  size_t len;
  tor_assert(tls);
  tor_assert(tls->ssl);
  tor_assert(tls->ssl->s3);
  tor_assert(tls->ssl->session);
  /*
    The value is an HMAC, using the TLS master key as the HMAC key, of
    client_random | server_random | TLSSECRET_MAGIC
  */
  memcpy(buf +  0, tls->ssl->s3->client_random, 32);
  memcpy(buf + 32, tls->ssl->s3->server_random, 32);
  memcpy(buf + 64, TLSSECRET_MAGIC, strlen(TLSSECRET_MAGIC) + 1);
  len = 64 + strlen(TLSSECRET_MAGIC) + 1;
  crypto_hmac_sha256((char*)secrets_out,
                     (char*)tls->ssl->session->master_key,
                     tls->ssl->session->master_key_length,
                     buf, len);
  memset(buf, 0, sizeof(buf));
  return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tor_tls_handshake ( tor_tls_t tls)

Perform initial handshake on tls.

When finished, returns TOR_TLS_DONE. On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD, or TOR_TLS_WANTWRITE.

Definition at line 1806 of file tortls.c.

{
  int r;
  int oldstate;
  tor_assert(tls);
  tor_assert(tls->ssl);
  tor_assert(tls->state == TOR_TLS_ST_HANDSHAKE);
  check_no_tls_errors();
  oldstate = tls->ssl->state;
  if (tls->isServer) {
    log_debug(LD_HANDSHAKE, "About to call SSL_accept on %p (%s)", tls,
              SSL_state_string_long(tls->ssl));
    r = SSL_accept(tls->ssl);
  } else {
    log_debug(LD_HANDSHAKE, "About to call SSL_connect on %p (%s)", tls,
              SSL_state_string_long(tls->ssl));
    r = SSL_connect(tls->ssl);
  }
  if (oldstate != tls->ssl->state)
    log_debug(LD_HANDSHAKE, "After call, %p was in state %s",
              tls, SSL_state_string_long(tls->ssl));
  /* We need to call this here and not earlier, since OpenSSL has a penchant
   * for clearing its flags when you say accept or connect. */
  tor_tls_unblock_renegotiation(tls);
  r = tor_tls_get_error(tls,r,0, "handshaking", LOG_INFO, LD_HANDSHAKE);
  if (ERR_peek_error() != 0) {
    tls_log_errors(tls, tls->isServer ? LOG_INFO : LOG_WARN, LD_HANDSHAKE,
                   "handshaking");
    return TOR_TLS_ERROR_MISC;
  }
  if (r == TOR_TLS_DONE) {
    tls->state = TOR_TLS_ST_OPEN;
    return tor_tls_finish_handshake(tls);
  }
  return r;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tor_tls_is_server ( tor_tls_t tls)

Return whether this tls initiated the connect (client) or received it (server).

Definition at line 1701 of file tortls.c.

{
  tor_assert(tls);
  return tls->isServer;
}

Here is the caller graph for this function:

void tor_tls_log_one_error ( tor_tls_t tls,
unsigned long  err,
int  severity,
int  domain,
const char *  doing 
)

Log a single error err as returned by ERR_get_error(), which was received while performing an operation doing on tls.

Log the message at severity, in log domain domain.

Definition at line 278 of file tortls.c.

{
  const char *state = NULL, *addr;
  const char *msg, *lib, *func;

  state = (tls && tls->ssl)?SSL_state_string_long(tls->ssl):"---";

  addr = tls ? tls->address : NULL;

  /* Some errors are known-benign, meaning they are the fault of the other
   * side of the connection. The caller doesn't know this, so override the
   * priority for those cases. */
  switch (ERR_GET_REASON(err)) {
    case SSL_R_HTTP_REQUEST:
    case SSL_R_HTTPS_PROXY_REQUEST:
    case SSL_R_RECORD_LENGTH_MISMATCH:
    case SSL_R_RECORD_TOO_LARGE:
    case SSL_R_UNKNOWN_PROTOCOL:
    case SSL_R_UNSUPPORTED_PROTOCOL:
      severity = LOG_INFO;
      break;
    default:
      break;
  }

  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 (!lib) lib = "(null)";
  if (!func) func = "(null)";
  if (doing) {
    log(severity, domain, "TLS error while %s%s%s: %s (in %s:%s:%s)",
        doing, addr?" with ":"", addr?addr:"",
        msg, lib, func, state);
  } else {
    log(severity, domain, "TLS error%s%s: %s (in %s:%s:%s)",
        addr?" with ":"", addr?addr:"",
        msg, lib, func, state);
  }
}

Here is the caller graph for this function:

tor_tls_t* tor_tls_new ( int  sock,
int  is_server 
)

Create a new TLS object from a file descriptor, and a flag to determine whether it is functioning as a server.

Definition at line 1544 of file tortls.c.

{
  BIO *bio = NULL;
  tor_tls_t *result = tor_malloc_zero(sizeof(tor_tls_t));
  tor_tls_context_t *context = isServer ? server_tls_context :
    client_tls_context;
  result->magic = TOR_TLS_MAGIC;

  tor_assert(context); /* make sure somebody made it first */
  if (!(result->ssl = SSL_new(context->ctx))) {
    tls_log_errors(NULL, LOG_WARN, LD_NET, "creating SSL object");
    tor_free(result);
    return NULL;
  }

#ifdef SSL_set_tlsext_host_name
  /* Browsers use the TLS hostname extension, so we should too. */
  if (!isServer) {
    char *fake_hostname = crypto_random_hostname(4,25, "www.",".com");
    SSL_set_tlsext_host_name(result->ssl, fake_hostname);
    tor_free(fake_hostname);
  }
#endif

  if (!SSL_set_cipher_list(result->ssl,
                     isServer ? SERVER_CIPHER_LIST : CLIENT_CIPHER_LIST)) {
    tls_log_errors(NULL, LOG_WARN, LD_NET, "setting ciphers");
#ifdef SSL_set_tlsext_host_name
    SSL_set_tlsext_host_name(result->ssl, NULL);
#endif
    SSL_free(result->ssl);
    tor_free(result);
    return NULL;
  }
  if (!isServer)
    rectify_client_ciphers(&result->ssl->cipher_list);
  result->socket = sock;
  bio = BIO_new_socket(sock, BIO_NOCLOSE);
  if (! bio) {
    tls_log_errors(NULL, LOG_WARN, LD_NET, "opening BIO");
#ifdef SSL_set_tlsext_host_name
    SSL_set_tlsext_host_name(result->ssl, NULL);
#endif
    SSL_free(result->ssl);
    tor_free(result);
    return NULL;
  }
  {
    int set_worked =
      SSL_set_ex_data(result->ssl, tor_tls_object_ex_data_index, result);
    if (!set_worked) {
      log_warn(LD_BUG,
               "Couldn't set the tls for an SSL*; connection will fail");
    }
  }
  SSL_set_bio(result->ssl, bio, bio);
  tor_tls_context_incref(context);
  result->context = context;
  result->state = TOR_TLS_ST_HANDSHAKE;
  result->isServer = isServer;
  result->wantwrite_n = 0;
  result->last_write_count = BIO_number_written(bio);
  result->last_read_count = BIO_number_read(bio);
  if (result->last_write_count || result->last_read_count) {
    log_warn(LD_NET, "Newly created BIO has read count %lu, write count %lu",
             result->last_read_count, result->last_write_count);
  }
#ifdef V2_HANDSHAKE_SERVER
  if (isServer) {
    SSL_set_info_callback(result->ssl, tor_tls_server_info_callback);
  } else
#endif
  {
    SSL_set_info_callback(result->ssl, tor_tls_debug_state_callback);
  }

  /* Not expected to get called. */
  tls_log_errors(NULL, LOG_WARN, LD_NET, "creating tor_tls_t object");
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return true iff this TLS connection is authenticated.

Definition at line 2012 of file tortls.c.

{
  X509 *cert;
  cert = SSL_get_peer_certificate(tls->ssl);
  tls_log_errors(tls, LOG_WARN, LD_HANDSHAKE, "getting peer certificate");
  if (!cert)
    return 0;
  X509_free(cert);
  return 1;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tor_tls_read ( tor_tls_t tls,
char *  cp,
size_t  len 
)

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.

Definition at line 1735 of file tortls.c.

{
  int r, err;
  tor_assert(tls);
  tor_assert(tls->ssl);
  tor_assert(tls->state == TOR_TLS_ST_OPEN);
  tor_assert(len<INT_MAX);
  r = SSL_read(tls->ssl, cp, (int)len);
  if (r > 0) {
#ifdef V2_HANDSHAKE_SERVER
    if (tls->got_renegotiate) {
      /* Renegotiation happened! */
      log_info(LD_NET, "Got a TLS renegotiation from %s", ADDR(tls));
      if (tls->negotiated_callback)
        tls->negotiated_callback(tls, tls->callback_arg);
      tls->got_renegotiate = 0;
    }
#endif
    return r;
  }
  err = tor_tls_get_error(tls, r, CATCH_ZERO, "reading", LOG_DEBUG, LD_NET);
  if (err == _TOR_TLS_ZERORETURN || err == TOR_TLS_CLOSE) {
    log_debug(LD_NET,"read returned r=%d; TLS is closed",r);
    tls->state = TOR_TLS_ST_CLOSED;
    return TOR_TLS_CLOSE;
  } else {
    tor_assert(err != TOR_TLS_DONE);
    log_debug(LD_NET,"read returned r=%d, err=%d",r,err);
    return err;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return true iff the peer certificate we're received on tls indicates that this connection should use the v3 (in-protocol) authentication handshake.

Only the connection initiator should use this, and only once the initial handshake is done; the responder detects a v1 handshake by cipher types, and a v3/v2 handshake by Versions cell vs renegotiation.

Definition at line 2359 of file tortls.c.

{
  X509 *cert = SSL_get_peer_certificate(tls->ssl);
  EVP_PKEY *key = NULL;
  X509_NAME *issuer_name, *subject_name;
  int is_v3 = 0;

  if (!cert) {
    log_warn(LD_BUG, "Called on a connection with no peer certificate");
    goto done;
  }

  subject_name = X509_get_subject_name(cert);
  issuer_name = X509_get_issuer_name(cert);

  if (X509_name_cmp(subject_name, issuer_name) == 0) {
    is_v3 = 1; /* purportedly self signed */
    goto done;
  }

  if (dn_indicates_v3_cert(subject_name) ||
      dn_indicates_v3_cert(issuer_name)) {
    is_v3 = 1; /* DN is fancy */
    goto done;
  }

  key = X509_get_pubkey(cert);
  if (EVP_PKEY_bits(key) != 1024 ||
      EVP_PKEY_type(key->type) != EVP_PKEY_RSA) {
    is_v3 = 1; /* Key is fancy */
    goto done;
  }

 done:
  if (key)
    EVP_PKEY_free(key);
  if (cert)
    X509_free(cert);

  return is_v3;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Client only: Renegotiate a TLS session.

When finished, returns TOR_TLS_DONE. On failure, returns TOR_TLS_ERROR, TOR_TLS_WANTREAD, or TOR_TLS_WANTWRITE.

Definition at line 1923 of file tortls.c.

{
  int r;
  tor_assert(tls);
  /* We could do server-initiated renegotiation too, but that would be tricky.
   * Instead of "SSL_renegotiate, then SSL_do_handshake until done" */
  tor_assert(!tls->isServer);
  if (tls->state != TOR_TLS_ST_RENEGOTIATE) {
    int r = SSL_renegotiate(tls->ssl);
    if (r <= 0) {
      return tor_tls_get_error(tls, r, 0, "renegotiating", LOG_WARN,
                               LD_HANDSHAKE);
    }
    tls->state = TOR_TLS_ST_RENEGOTIATE;
  }
  r = SSL_do_handshake(tls->ssl);
  if (r == 1) {
    tls->state = TOR_TLS_ST_OPEN;
    return TOR_TLS_DONE;
  } else
    return tor_tls_get_error(tls, r, 0, "renegotiating handshake", LOG_INFO,
                             LD_HANDSHAKE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Return true iff the server TLS connection tls got the renegotiation request it was waiting for.

Definition at line 2412 of file tortls.c.

{
  return tls->got_renegotiate;
}

Here is the caller graph for this function:

void tor_tls_set_logged_address ( tor_tls_t tls,
const char *  address 
)

Make future log messages about tls display the address address.

Definition at line 1629 of file tortls.c.

Here is the caller graph for this function:

void tor_tls_set_renegotiate_callback ( tor_tls_t tls,
void(*)(tor_tls_t *, void *arg)  cb,
void *  arg 
)

Set cb to be called with argument arg whenever tls next gets a client-side renegotiate in the middle of a read.

Do not invoke this function until after initial handshaking is done!

Definition at line 1641 of file tortls.c.

{
  tls->negotiated_callback = cb;
  tls->callback_arg = arg;
  tls->got_renegotiate = 0;
#ifdef V2_HANDSHAKE_SERVER
  if (cb) {
    SSL_set_info_callback(tls->ssl, tor_tls_server_info_callback);
  } else {
    SSL_set_info_callback(tls->ssl, tor_tls_debug_state_callback);
  }
#endif
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tor_tls_shutdown ( tor_tls_t tls)

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.

Definition at line 1952 of file tortls.c.

{
  int r, err;
  char buf[128];
  tor_assert(tls);
  tor_assert(tls->ssl);

  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, CATCH_ZERO, "reading to shut down",
                              LOG_INFO, LD_NET);
      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;
    }
    err = tor_tls_get_error(tls, r, CATCH_SYSCALL|CATCH_ZERO, "shutting down",
                            LOG_INFO, LD_NET);
    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_WARN, LD_NET,
            "TLS returned \"half-closed\" value while already half-closed");
        return TOR_TLS_ERROR_MISC;
      }
      tls->state = TOR_TLS_ST_SENTCLOSE;
      /* fall through ... */
    } else {
      return err;
    }
  } /* end loop */
}

Here is the call graph for this function:

If this version of openssl requires it, turn on renegotiation on tls.

Definition at line 1661 of file tortls.c.

{
  /* Yes, we know what we are doing here.  No, we do not treat a renegotiation
   * as authenticating any earlier-received data. */
  if (use_unsafe_renegotiation_flag) {
    tls->ssl->s3->flags |= SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION;
  }
  if (use_unsafe_renegotiation_op) {
    SSL_set_options(tls->ssl,
                    SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION);
  }
}

Here is the caller graph for this function:

Return true iff the initial TLS connection at tls did not use a v2 TLS handshake.

Output is undefined if the handshake isn't finished.

Definition at line 2301 of file tortls.c.

{
  if (tls->isServer) {
#ifdef V2_HANDSHAKE_SERVER
    return ! tls->wasV2Handshake;
#endif
  } else {
#ifdef V2_HANDSHAKE_CLIENT
    return ! tls->wasV2Handshake;
#endif
  }
  return 1;
}

Here is the caller graph for this function:

int tor_tls_verify ( int  severity,
tor_tls_t tls,
crypto_pk_t **  identity_key 
)

If the provided tls connection is authenticated and has a certificate chain that is currently valid and signed, then set *identity_key to the identity certificate's key and return 0.

Else, return -1 and log complaints with log-level severity.

Definition at line 2131 of file tortls.c.

{
  X509 *cert = NULL, *id_cert = NULL;
  EVP_PKEY *id_pkey = NULL;
  RSA *rsa;
  int r = -1;

  *identity_key = NULL;

  try_to_extract_certs_from_tls(severity, tls, &cert, &id_cert);
  if (!cert)
    goto done;
  if (!id_cert) {
    log_fn(severity,LD_PROTOCOL,"No distinct identity certificate found");
    goto done;
  }
  tls_log_errors(tls, severity, LD_HANDSHAKE, "before verifying certificate");

  if (!(id_pkey = X509_get_pubkey(id_cert)) ||
      X509_verify(cert, id_pkey) <= 0) {
    log_fn(severity,LD_PROTOCOL,"X509_verify on cert and pkey returned <= 0");
    tls_log_errors(tls, severity, LD_HANDSHAKE, "verifying certificate");
    goto done;
  }

  rsa = EVP_PKEY_get1_RSA(id_pkey);
  if (!rsa)
    goto done;
  *identity_key = _crypto_new_pk_from_rsa(rsa);

  r = 0;

 done:
  if (cert)
    X509_free(cert);
  if (id_pkey)
    EVP_PKEY_free(id_pkey);

  /* This should never get invoked, but let's make sure in case OpenSSL
   * acts unexpectedly. */
  tls_log_errors(tls, LOG_WARN, LD_HANDSHAKE, "finishing tor_tls_verify");

  return r;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tor_tls_write ( tor_tls_t tls,
const char *  cp,
size_t  n 
)

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.

Definition at line 1773 of file tortls.c.

{
  int r, err;
  tor_assert(tls);
  tor_assert(tls->ssl);
  tor_assert(tls->state == TOR_TLS_ST_OPEN);
  tor_assert(n < INT_MAX);
  if (n == 0)
    return 0;
  if (tls->wantwrite_n) {
    /* if WANTWRITE last time, we must use the _same_ n as before */
    tor_assert(n >= tls->wantwrite_n);
    log_debug(LD_NET,"resuming pending-write, (%d to flush, reusing %d)",
              (int)n, (int)tls->wantwrite_n);
    n = tls->wantwrite_n;
    tls->wantwrite_n = 0;
  }
  r = SSL_write(tls->ssl, cp, (int)n);
  err = tor_tls_get_error(tls, r, 0, "writing", LOG_INFO, LD_NET);
  if (err == TOR_TLS_DONE) {
    return r;
  }
  if (err == TOR_TLS_WANTWRITE || err == TOR_TLS_WANTREAD) {
    tls->wantwrite_n = n;
  }
  return err;
}

Here is the call graph for this function:

Here is the caller graph for this function: