Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
David Goulet
Tor
Commits
5205c7fd
Commit
5205c7fd
authored
Aug 17, 2018
by
Nick Mathewson
🥄
Browse files
Initial NSS support for TLS.
This is enough to get a chutney network to bootstrap, though a bunch of work remains.
parent
c567b8fc
Changes
7
Hide whitespace changes
Inline
Side-by-side
src/lib/tls/tortls.c
View file @
5205c7fd
...
...
@@ -4,6 +4,7 @@
/* See LICENSE for licensing information */
#define TORTLS_PRIVATE
#define TOR_X509_PRIVATE
#include
"lib/tls/x509.h"
#include
"lib/tls/x509_internal.h"
#include
"lib/tls/tortls.h"
...
...
@@ -14,6 +15,8 @@
#include
"lib/crypt_ops/crypto_rsa.h"
#include
"lib/crypt_ops/crypto_rand.h"
#include
<time.h>
/** Global TLS contexts. We keep them here because nobody else needs
* to touch them.
*
...
...
@@ -31,6 +34,26 @@ tor_tls_context_get(int is_server)
return
is_server
?
server_tls_context
:
client_tls_context
;
}
/** Convert an errno (or a WSAerrno on windows) into a TOR_TLS_* error
* code. */
int
tor_errno_to_tls_error
(
int
e
)
{
switch
(
e
)
{
case
SOCK_ERRNO
(
ECONNRESET
):
// most common
return
TOR_TLS_ERROR_CONNRESET
;
case
SOCK_ERRNO
(
ETIMEDOUT
):
return
TOR_TLS_ERROR_TIMEOUT
;
case
SOCK_ERRNO
(
EHOSTUNREACH
):
case
SOCK_ERRNO
(
ENETUNREACH
):
return
TOR_TLS_ERROR_NO_ROUTE
;
case
SOCK_ERRNO
(
ECONNREFUSED
):
return
TOR_TLS_ERROR_CONNREFUSED
;
// least common
default:
return
TOR_TLS_ERROR_MISC
;
}
}
/** Set *<b>link_cert_out</b> and *<b>id_cert_out</b> to the link certificate
* and ID certificate that we're currently using for our V3 in-protocol
* handshake's certificate chain. If <b>server</b> is true, provide the certs
...
...
@@ -334,3 +357,102 @@ tor_tls_is_server(tor_tls_t *tls)
tor_assert
(
tls
);
return
tls
->
isServer
;
}
/** Release resources associated with a TLS object. Does not close the
* underlying file descriptor.
*/
void
tor_tls_free_
(
tor_tls_t
*
tls
)
{
if
(
!
tls
)
return
;
tor_assert
(
tls
->
ssl
);
{
size_t
r
,
w
;
tor_tls_get_n_raw_bytes
(
tls
,
&
r
,
&
w
);
/* ensure written_by_tls is updated */
}
tor_tls_impl_free_
(
tls
->
ssl
);
tls
->
ssl
=
NULL
;
#ifdef ENABLE_OPENSSL
tls
->
negotiated_callback
=
NULL
;
#endif
if
(
tls
->
context
)
tor_tls_context_decref
(
tls
->
context
);
tor_free
(
tls
->
address
);
tls
->
magic
=
0x99999999
;
tor_free
(
tls
);
}
/** If the provided tls connection is authenticated and has a
* certificate chain that is currently valid and signed, then set
* *<b>identity_key</b> to the identity certificate's key and return
* 0. Else, return -1 and log complaints with log-level <b>severity</b>.
*/
int
tor_tls_verify
(
int
severity
,
tor_tls_t
*
tls
,
crypto_pk_t
**
identity
)
{
tor_x509_cert_impl_t
*
cert
=
NULL
,
*
id_cert
=
NULL
;
tor_x509_cert_t
*
peer_x509
=
NULL
,
*
id_x509
=
NULL
;
tor_assert
(
tls
);
tor_assert
(
identity
);
int
rv
=
-
1
;
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
;
}
peer_x509
=
tor_x509_cert_new
(
cert
);
id_x509
=
tor_x509_cert_new
(
id_cert
);
cert
=
id_cert
=
NULL
;
/* Prevent double-free */
if
(
!
tor_tls_cert_is_valid
(
severity
,
peer_x509
,
id_x509
,
time
(
NULL
),
0
))
{
goto
done
;
}
*
identity
=
tor_tls_cert_get_key
(
id_x509
);
rv
=
0
;
done:
if
(
cert
)
tor_x509_cert_impl_free_
(
cert
);
if
(
id_cert
)
tor_x509_cert_impl_free_
(
id_cert
);
tor_x509_cert_free
(
peer_x509
);
tor_x509_cert_free
(
id_x509
);
return
rv
;
}
/** Check whether the certificate set on the connection <b>tls</b> is expired
* give or take <b>past_tolerance</b> seconds, or not-yet-valid give or take
* <b>future_tolerance</b> seconds. Return 0 for valid, -1 for failure.
*
* NOTE: you should call tor_tls_verify before tor_tls_check_lifetime.
*/
int
tor_tls_check_lifetime
(
int
severity
,
tor_tls_t
*
tls
,
time_t
now
,
int
past_tolerance
,
int
future_tolerance
)
{
tor_x509_cert_t
*
cert
;
int
r
=
-
1
;
if
(
!
(
cert
=
tor_tls_get_peer_cert
(
tls
)))
goto
done
;
if
(
tor_x509_check_cert_lifetime_internal
(
severity
,
cert
->
cert
,
now
,
past_tolerance
,
future_tolerance
)
<
0
)
goto
done
;
r
=
0
;
done:
tor_x509_cert_free
(
cert
);
/* Not expected to get invoked */
tls_log_errors
(
tls
,
LOG_WARN
,
LD_NET
,
"checking certificate lifetime"
);
return
r
;
}
src/lib/tls/tortls.h
View file @
5205c7fd
...
...
@@ -13,10 +13,25 @@
#include
"lib/crypt_ops/crypto_rsa.h"
#include
"lib/testsupport/testsupport.h"
#include
"lib/net/nettypes.h"
/* Opaque structure to hold a TLS connection. */
typedef
struct
tor_tls_t
tor_tls_t
;
#ifdef TORTLS_PRIVATE
#ifdef ENABLE_OPENSSL
struct
ssl_st
;
struct
ssl_ctx_st
;
struct
ssl_session_st
;
typedef
struct
ssl_ctx_st
tor_tls_context_impl_t
;
typedef
struct
ssl_st
tor_tls_impl_t
;
#else
struct
PRFileDesc
;
typedef
struct
PRFileDesc
tor_tls_context_impl_t
;
typedef
struct
PRFileDesc
tor_tls_impl_t
;
#endif
#endif
struct
tor_x509_cert_t
;
/* Possible return values for most tor_tls_* functions. */
...
...
@@ -73,7 +88,7 @@ int tor_tls_context_init(unsigned flags,
void
tor_tls_context_incref
(
tor_tls_context_t
*
ctx
);
void
tor_tls_context_decref
(
tor_tls_context_t
*
ctx
);
tor_tls_context_t
*
tor_tls_context_get
(
int
is_server
);
tor_tls_t
*
tor_tls_new
(
in
t
sock
,
int
is_server
);
tor_tls_t
*
tor_tls_new
(
tor_socket_
t
sock
,
int
is_server
);
void
tor_tls_set_logged_address
(
tor_tls_t
*
tls
,
const
char
*
address
);
void
tor_tls_set_renegotiate_callback
(
tor_tls_t
*
tls
,
void
(
*
cb
)(
tor_tls_t
*
,
void
*
arg
),
...
...
@@ -121,13 +136,17 @@ MOCK_DECL(int,tor_tls_export_key_material,(
size_t
context_len
,
const
char
*
label
));
#ifdef ENABLE_OPENSSL
/* Log and abort if there are unhandled TLS errors in OpenSSL's error stack.
*/
#define check_no_tls_errors() check_no_tls_errors_(__FILE__,__LINE__)
void
check_no_tls_errors_
(
const
char
*
fname
,
int
line
);
void
tor_tls_log_one_error
(
tor_tls_t
*
tls
,
unsigned
long
err
,
int
severity
,
int
domain
,
const
char
*
doing
);
#else
#define check_no_tls_errors() STMT_NIL
#endif
int
tor_tls_get_my_certs
(
int
server
,
const
struct
tor_x509_cert_t
**
link_cert_out
,
...
...
src/lib/tls/tortls_internal.h
View file @
5205c7fd
...
...
@@ -6,15 +6,11 @@
#ifndef TORTLS_INTERNAL_H
#define TORTLS_INTERNAL_H
#ifdef ENABLE_OPENSSL
struct
ssl_st
;
struct
ssl_ctx_st
;
struct
ssl_session_st
;
#endif
int
tor_errno_to_tls_error
(
int
e
);
#ifdef ENABLE_OPENSSL
int
tor_tls_get_error
(
tor_tls_t
*
tls
,
int
r
,
int
extra
,
const
char
*
doing
,
int
severity
,
int
domain
);
#endif
MOCK_DECL
(
void
,
try_to_extract_certs_from_tls
,
(
int
severity
,
tor_tls_t
*
tls
,
tor_x509_cert_impl_t
**
cert_out
,
...
...
@@ -31,13 +27,9 @@ int tor_tls_context_init_certificates(tor_tls_context_t *result,
crypto_pk_t
*
identity
,
unsigned
key_lifetime
,
unsigned
flags
);
void
tor_tls_impl_free_
(
tor_tls_impl_t
*
ssl
);
#ifdef ENABLE_OPENSSL
void
tor_tls_context_impl_free
(
struct
ssl_ctx_st
*
);
#else
struct
ssl_ctx_st
;
// XXXX replace
void
tor_tls_context_impl_free
(
struct
ssl_ctx_st
*
);
#endif
void
tor_tls_context_impl_free
(
tor_tls_context_impl_t
*
);
#ifdef ENABLE_OPENSSL
tor_tls_t
*
tor_tls_get_by_ssl
(
const
struct
ssl_st
*
ssl
);
...
...
src/lib/tls/tortls_nss.c
View file @
5205c7fd
...
...
@@ -12,6 +12,7 @@
#include
"orconfig.h"
#define TORTLS_PRIVATE
#define TOR_X509_PRIVATE
#ifdef _WIN32
/*wrkard for dtls1.h >= 0.9.8m of "#include <winsock.h>"*/
#include
<winsock2.h>
...
...
@@ -22,6 +23,9 @@
#include
"lib/crypt_ops/crypto_rand.h"
#include
"lib/crypt_ops/crypto_dh.h"
#include
"lib/crypt_ops/crypto_util.h"
#include
"lib/crypt_ops/crypto_nss_mgt.h"
#include
"lib/string/printf.h"
#include
"lib/tls/x509.h"
#include
"lib/tls/x509_internal.h"
#include
"lib/tls/tortls.h"
...
...
@@ -29,26 +33,16 @@
#include
"lib/tls/tortls_internal.h"
#include
"lib/log/util_bug.h"
int
tor_errno_to_tls_error
(
int
e
)
{
(
void
)
e
;
// XXXX
return
-
1
;
}
int
tor_tls_get_error
(
tor_tls_t
*
tls
,
int
r
,
int
extra
,
const
char
*
doing
,
int
severity
,
int
domain
)
{
(
void
)
tls
;
(
void
)
r
;
(
void
)
extra
;
(
void
)
doing
;
(
void
)
severity
;
(
void
)
domain
;
// XXXX
return
-
1
;
}
#include
<prio.h>
// For access to raw sockets.
#include
<private/pprio.h>
#include
<ssl.h>
#include
<sslt.h>
#include
<sslproto.h>
#include
<certt.h>
static
SECStatus
always_accept_cert_cb
(
void
*
,
PRFileDesc
*
,
PRBool
,
PRBool
);
MOCK_IMPL
(
void
,
try_to_extract_certs_from_tls
,(
int
severity
,
tor_tls_t
*
tls
,
tor_x509_cert_impl_t
**
cert_out
,
...
...
@@ -57,14 +51,109 @@ try_to_extract_certs_from_tls,(int severity, tor_tls_t *tls,
tor_assert
(
tls
);
tor_assert
(
cert_out
);
tor_assert
(
id_cert_out
);
(
void
)
severity
;
// XXXX
(
void
)
severity
;
*
cert_out
=
*
id_cert_out
=
NULL
;
CERTCertificate
*
peer
=
SSL_PeerCertificate
(
tls
->
ssl
);
if
(
!
peer
)
return
;
*
cert_out
=
peer
;
/* Now owns pointer. */
CERTCertList
*
chain
=
SSL_PeerCertificateChain
(
tls
->
ssl
);
CERTCertListNode
*
c
=
CERT_LIST_HEAD
(
chain
);
for
(;
!
CERT_LIST_END
(
c
,
chain
);
c
=
CERT_LIST_NEXT
(
c
))
{
if
(
CERT_CompareCerts
(
c
->
cert
,
peer
)
==
PR_FALSE
)
{
*
id_cert_out
=
CERT_DupCertificate
(
c
->
cert
);
break
;
}
}
CERT_DestroyCertList
(
chain
);
}
static
bool
we_like_ssl_cipher
(
SSLCipherAlgorithm
ca
)
{
switch
(
ca
)
{
case
ssl_calg_null
:
return
false
;
case
ssl_calg_rc4
:
return
false
;
case
ssl_calg_rc2
:
return
false
;
case
ssl_calg_des
:
return
false
;
case
ssl_calg_3des
:
return
false
;
/* ???? */
case
ssl_calg_idea
:
return
false
;
case
ssl_calg_fortezza
:
return
false
;
case
ssl_calg_camellia
:
return
false
;
case
ssl_calg_seed
:
return
false
;
case
ssl_calg_aes
:
return
true
;
case
ssl_calg_aes_gcm
:
return
true
;
case
ssl_calg_chacha20
:
return
true
;
default:
return
true
;
}
}
static
bool
we_like_ssl_kea
(
SSLKEAType
kt
)
{
switch
(
kt
)
{
case
ssl_kea_null
:
return
false
;
case
ssl_kea_rsa
:
return
false
;
/* ??? */
case
ssl_kea_fortezza
:
return
false
;
case
ssl_kea_ecdh_psk
:
return
false
;
case
ssl_kea_dh_psk
:
return
false
;
case
ssl_kea_dh
:
return
true
;
case
ssl_kea_ecdh
:
return
true
;
case
ssl_kea_tls13_any
:
return
true
;
case
ssl_kea_size
:
return
true
;
/* prevent a warning. */
default:
return
true
;
}
}
static
bool
we_like_mac_algorithm
(
SSLMACAlgorithm
ma
)
{
switch
(
ma
)
{
case
ssl_mac_null
:
return
false
;
case
ssl_mac_md5
:
return
false
;
case
ssl_hmac_md5
:
return
false
;
case
ssl_mac_sha
:
return
true
;
case
ssl_hmac_sha
:
return
true
;
case
ssl_hmac_sha256
:
return
true
;
case
ssl_mac_aead
:
return
true
;
case
ssl_hmac_sha384
:
return
true
;
default:
return
true
;
}
}
static
bool
we_like_auth_type
(
SSLAuthType
at
)
{
switch
(
at
)
{
case
ssl_auth_null
:
return
false
;
case
ssl_auth_rsa_decrypt
:
return
false
;
case
ssl_auth_dsa
:
return
false
;
case
ssl_auth_kea
:
return
false
;
case
ssl_auth_ecdsa
:
return
true
;
case
ssl_auth_ecdh_rsa
:
return
true
;
case
ssl_auth_ecdh_ecdsa
:
return
true
;
case
ssl_auth_rsa_sign
:
return
true
;
case
ssl_auth_rsa_pss
:
return
true
;
case
ssl_auth_psk
:
return
true
;
case
ssl_auth_tls13_any
:
return
true
;
case
ssl_auth_size
:
return
true
;
/* prevent a warning. */
default:
return
true
;
}
}
tor_tls_context_t
*
tor_tls_context_new
(
crypto_pk_t
*
identity
,
unsigned
int
key_lifetime
,
unsigned
flags
,
int
is_client
)
{
SECStatus
s
;
tor_assert
(
identity
);
tor_tls_context_t
*
ctx
=
tor_malloc_zero
(
sizeof
(
tor_tls_context_t
));
...
...
@@ -77,7 +166,128 @@ tor_tls_context_new(crypto_pk_t *identity,
}
}
// XXXX write the main body.
{
/* Create the "model" PRFileDesc that we will use to base others on. */
PRFileDesc
*
tcp
=
PR_NewTCPSocket
();
if
(
!
tcp
)
goto
err
;
ctx
->
ctx
=
SSL_ImportFD
(
NULL
,
tcp
);
if
(
!
ctx
->
ctx
)
{
PR_Close
(
tcp
);
goto
err
;
}
}
// Configure the certificate.
if
(
!
is_client
)
{
s
=
SSL_ConfigServerCert
(
ctx
->
ctx
,
ctx
->
my_link_cert
->
cert
,
(
SECKEYPrivateKey
*
)
crypto_pk_get_nss_privkey
(
ctx
->
link_key
),
NULL
,
/* ExtraServerCertData */
0
/* DataLen */
);
if
(
s
!=
SECSuccess
)
goto
err
;
}
// We need a certificate from the other side.
if
(
is_client
)
{
// XXXX does this do anything?
s
=
SSL_OptionSet
(
ctx
->
ctx
,
SSL_REQUIRE_CERTIFICATE
,
PR_TRUE
);
if
(
s
!=
SECSuccess
)
goto
err
;
}
// Always accept other side's cert; we'll check it ourselves in goofy
// tor ways.
s
=
SSL_AuthCertificateHook
(
ctx
->
ctx
,
always_accept_cert_cb
,
NULL
);
// We allow simultaneous read and write.
s
=
SSL_OptionSet
(
ctx
->
ctx
,
SSL_ENABLE_FDX
,
PR_TRUE
);
if
(
s
!=
SECSuccess
)
goto
err
;
// XXXX SSL_ROLLBACK_DETECTION??
// XXXX SSL_ENABLE_ALPN??
// Force client-mode or server_mode.
s
=
SSL_OptionSet
(
ctx
->
ctx
,
is_client
?
SSL_HANDSHAKE_AS_CLIENT
:
SSL_HANDSHAKE_AS_SERVER
,
PR_TRUE
);
if
(
s
!=
SECSuccess
)
goto
err
;
// Disable everything before TLS 1.0; support everything else.
{
SSLVersionRange
vrange
;
memset
(
&
vrange
,
0
,
sizeof
(
vrange
));
s
=
SSL_VersionRangeGetSupported
(
ssl_variant_stream
,
&
vrange
);
if
(
s
!=
SECSuccess
)
goto
err
;
if
(
vrange
.
min
<
SSL_LIBRARY_VERSION_TLS_1_0
)
vrange
.
min
=
SSL_LIBRARY_VERSION_TLS_1_0
;
s
=
SSL_VersionRangeSet
(
ctx
->
ctx
,
&
vrange
);
if
(
s
!=
SECSuccess
)
goto
err
;
}
// Only support strong ciphers.
{
const
PRUint16
*
ciphers
=
SSL_GetImplementedCiphers
();
const
PRUint16
n_ciphers
=
SSL_GetNumImplementedCiphers
();
PRUint16
i
;
for
(
i
=
0
;
i
<
n_ciphers
;
++
i
)
{
SSLCipherSuiteInfo
info
;
memset
(
&
info
,
0
,
sizeof
(
info
));
s
=
SSL_GetCipherSuiteInfo
(
ciphers
[
i
],
&
info
,
sizeof
(
info
));
if
(
s
!=
SECSuccess
)
goto
err
;
if
(
BUG
(
info
.
cipherSuite
!=
ciphers
[
i
]))
goto
err
;
int
disable
=
info
.
effectiveKeyBits
<
128
||
info
.
macBits
<
128
||
!
we_like_ssl_cipher
(
info
.
symCipher
)
||
!
we_like_ssl_kea
(
info
.
keaType
)
||
!
we_like_mac_algorithm
(
info
.
macAlgorithm
)
||
!
we_like_auth_type
(
info
.
authType
)
/* Requires NSS 3.24 */
;
s
=
SSL_CipherPrefSet
(
ctx
->
ctx
,
ciphers
[
i
],
disable
?
PR_FALSE
:
PR_TRUE
);
if
(
s
!=
SECSuccess
)
goto
err
;
}
}
// Only use DH and ECDH keys once.
s
=
SSL_OptionSet
(
ctx
->
ctx
,
SSL_REUSE_SERVER_ECDHE_KEY
,
PR_FALSE
);
if
(
s
!=
SECSuccess
)
goto
err
;
// don't cache sessions.
s
=
SSL_OptionSet
(
ctx
->
ctx
,
SSL_NO_CACHE
,
PR_TRUE
);
if
(
s
!=
SECSuccess
)
goto
err
;
// Enable DH.
s
=
SSL_OptionSet
(
ctx
->
ctx
,
SSL_ENABLE_SERVER_DHE
,
PR_TRUE
);
if
(
s
!=
SECSuccess
)
goto
err
;
// Set DH and ECDH groups.
SSLNamedGroup
groups
[]
=
{
ssl_grp_ec_curve25519
,
ssl_grp_ec_secp256r1
,
ssl_grp_ec_secp224r1
,
ssl_grp_ffdhe_2048
,
};
s
=
SSL_NamedGroupConfig
(
ctx
->
ctx
,
groups
,
ARRAY_LENGTH
(
groups
));
if
(
s
!=
SECSuccess
)
goto
err
;
// These features are off by default, so we don't need to disable them:
// Session tickets
// Renegotiation
// Compression
goto
done
;
err:
...
...
@@ -88,11 +298,9 @@ tor_tls_context_new(crypto_pk_t *identity,
}
void
tor_tls_context_impl_free
(
struct
ssl_ctx_s
t
*
ctx
)
tor_tls_context_impl_free
(
tor_tls_context_impl_
t
*
ctx
)
{
(
void
)
ctx
;
// XXXX
// XXXX openssl type.
PR_Close
(
ctx
);
}
void
...
...
@@ -101,33 +309,82 @@ tor_tls_get_state_description(tor_tls_t *tls, char *buf, size_t sz)
(
void
)
tls
;
(
void
)
buf
;
(
void
)
sz
;
// XXXX
// AFAICT, NSS doesn't expose its internal state.
buf
[
0
]
=
0
;
}
void
tor_tls_init
(
void
)
{
/
/ XXXX
/
* We don't have any global setup to do yet, but that will change */
}
void
tls_log_errors
(
tor_tls_t
*
tls
,
int
severity
,
int
domain
,
const
char
*
doing
)
{
/* XXXX This implementation isn't right for NSS -- it logs the last error
whether anything actually failed or not. */
(
void
)
tls
;
(
void
)
severity
;
(
void
)
domain
;
(
void
)
doing
;
// XXXX
PRErrorCode
code
=
PORT_GetError
();
const
char
*
string
=
PORT_ErrorToString
(
code
);
const
char
*
name
=
PORT_ErrorToName
(
code
);
char
buf
[
16
];
if
(
!
string
)
string
=
"<unrecognized>"
;
if
(
!
name
)
{
tor_snprintf
(
buf
,
sizeof
(
buf
),
"%d"
,
code
);
name
=
buf
;
}
if
(
doing
)
{
log_fn
(
severity
,
domain
,
"TLS error %s while %s: %s"
,
name
,
doing
,
string
);
}
else
{
log_fn
(
severity
,
domain
,
"TLS error %s: %s"
,
name
,
string
);
}
}
tor_tls_t
*
tor_tls_new
(
in
t
sock
,
int
is_server
)
tor_tls_new
(
tor_socket_
t
sock
,
int
is_server
)
{
(
void
)
sock
;
(
void
)
is_server
;
// XXXX
return
NULL
;
tor_tls_context_t
*
ctx
=
tor_tls_context_get
(
is_server
);
PRFileDesc
*
tcp
=
PR_ImportTCPSocket
(
sock
);
if
(
!
tcp
)
return
NULL
;
PRFileDesc
*
ssl
=
SSL_ImportFD
(
ctx
->
ctx
,
tcp
);
if
(
!
ssl
)
{
PR_Close
(
tcp
);
return
NULL
;
}
tor_tls_t
*
tls
=
tor_malloc_zero
(
sizeof
(
tor_tls_t
));
tls
->
magic
=
TOR_TLS_MAGIC
;
tls
->
context
=
ctx
;
tor_tls_context_incref
(
ctx
);
tls
->
ssl
=
ssl
;
tls
->
socket
=
sock
;
tls
->
state
=
TOR_TLS_ST_HANDSHAKE
;
tls
->
isServer
=
!!
is_server
;
if
(
!
is_server
)
{
/* Set a random SNI */
char
*
fake_hostname
=
crypto_random_hostname
(
4
,
25
,
"www."
,
".com"
);
SSL_SetURL
(
tls
->
ssl
,
fake_hostname
);
tor_free
(
fake_hostname
);
}
SECStatus
s
=
SSL_ResetHandshake
(
ssl
,
is_server
?
PR_TRUE
:
PR_FALSE
);
if
(
s
!=
SECSuccess
)
{
crypto_nss_log_errors
(
LOG_WARN
,
"resetting handshake state"
);
}
return
tls
;
}
void
tor_tls_set_renegotiate_callback
(
tor_tls_t
*