tag:blogger.com,1999:blog-16256735758211566892024-03-17T08:55:39.083+01:00nmav's BlogNikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.comBlogger35125tag:blogger.com,1999:blog-1625673575821156689.post-18059863350543656752018-05-04T10:29:00.000+02:002019-05-25T22:36:53.363+02:00GnuTLS and TLS 1.3<span style="font-size: xx-small;">[last update 2019-05-25]</span> <br />
<br />
GnuTLS already contains support for the <strike>latest TLS 1.3 draft (draft-ietf-tls-tls13-26) on its master git branch</strike> TLS 1.3 RFC in its 3.6.5 release. One of our major challenges related to TLS 1.3 protocol, was making its support transparent for existing applications; that is, without any code changes or the need for re-compilation. We believe we have sufficiently addressed that challenge, while at the same time made available several new features introduced by the protocol. This post will go through the new features of TLS 1.3, and discuss how one can take advantage of them with GnuTLS. We will also discuss potential pain points during the migration. More information will be provided in the <a href="https://www.gnutls.org/manual/html_node/Upgrading-from-previous-versions.html">'upgrade section' of the manual after the release</a>.<br />
<br />
<h2>
New features under TLS 1.3</h2>
Unlike its predecessors which were consisting of incremental updates, TLS 1.3 is a clean slate re-write of the TLS 1.2 protocol. In brief, on the algorithmic level the changes are quite minimal, with the support for RSA-PSS signatures being the most significant change, and the elimination of all ciphers which had known issues. On the protocol level, the changes span many aspects, mainly changes to reduce the message roundtrips during handshake, several security related fixes and protocol simplifications. These changes include the complete elimination of the convoluted re-handshake process, and replace it by the simpler re-key and re-authentication processes. They also include the defense against passive eavesdroppers for the certificates sent during handshake, the introduction of a foundation for message length hiding, and the ability to attach OCSP staples to all certificates sent during handshake.<br />
<br />
<h4>
Testing TLS 1.3</h4>
In GnuTLS 3.6.5, TLS 1.3 is enabled by default. <br />
<br />
<h4>
Single roundtrip handshake</h4>
In contrast with TLS 1.2 which had a handshake message round-trip of 2, the TLS 1.3 handshake process typically takes a single round-trip. The idea behind that optimization is that the client sends its key shares for the key exchange speculatively, by guessing the Diffie-Hellman group(s) the server supports. If that speculation fails, the handshake falls backs to a more verbose mode which includes two additional messages (Hello-Retry-Request and ClientHello) to negotiate the commonly supported groups.<br />
<br />
In GnuTLS the client sends by default the key share of the two distinct group types which have the highest priority; currently that is the elliptic curve groups SECP256R1 and X25519. The reason key shares from these two groups were selected is because they are widely available, and require little resources from a CPU-time perspective, while minimizing the risk of fall-back to the more verbose handshake. In order to modify that behavior, applications can re-order the preferred group list via priority strings, and/or provide a special flag to gnutls_init() which switches the behavior. The flag <i>GNUTLS_KEY_SHARE_TOP</i> instructs GnuTLS to send a single key share, <i>GNUTLS_KEY_SHARE_TOP3</i> to send the top 3 distinct group key shares (e.g., SECP256R1, X25519 and FFDHE2048).<br />
<br />
Note however, that the round-trips achieved by TLS 1.3 do not translate to network roundtrip when operating under TCP. That is because TCP introduces an additional round-trip due to the SYN-ACK TCP exchange. To eliminate the additional round-trip, the same tricks apply as with TLS 1.2; one needs <a href="https://www.gnutls.org/manual/html_node/Reducing-round_002dtrips.html">to rely on the TCP fast open</a>.<br />
<br />
<br />
<h4>
New ciphersuites and key exchange changes</h4>
TLS 1.3 replaces all the ciphersuites available
under TLS 1.2 and earlier with a new set of five ciphersuites. The
ciphersuite meaning is also changed from expressing the key
exchange, authentication method and cipher/MAC, to define the cipher and MAC algorithms only. The reason for that change is that in TLS 1.3 there are
only two authentication methods defined; the certificate and the pre-shared key
(PSK) which are negotiated separately using extensions. Similarly, the key exchange methods, expanded in scope since TLS1.2, and from the being part of the ciphersuite, as elliptic curve Diffie-Hellman (ECDHE) or finite field Diffie-Hellman (DHE), they are now fine-tuned to the actual group in use. That is SECP256R1 for the NIST P256R1 elliptic curve group, or X25519, or FFDHE-2048 for the RFC7919 Diffie-Hellman group and so on. The groups are negotiated via the supported groups TLS extension, and are set in GnuTLS via the priority strings. <br />
<br />
The following new ciphersuites are introduced in TLS 1.3:<br />
<ul>
<li>AES-256-GCM</li>
<li>CHACHA20-POLY1305 </li>
<li>AES-128-GCM</li>
<li>AES-128-CCM</li>
<li>AES-128-CCM-8</li>
</ul>
They are all supported by GnuTLS, though AES-128-CCM-8, which
has a truncated tag, is not enabled by default. Furthermore, the fact that TLS 1.3 limited all the available ciphers to this small set, prompted us for a cleanup of our default settings for TLS 1.2 and earlier. We saw no reason to provide different cipher choices depending on the negotiated protocol. As a result we kept that base of ciphers, disabling the Camellia and 3DES ciphersuites across all protocol versions.<br />
<br />
Note that existing applications need no changes to take advantage of the new ciphers. The existing priority
strings were sufficiently flexible to support them.<br />
<br />
<h4>
Post handshake authentication</h4>
TLS 1.2 provided a combined re-authentication and re-key mechanism under the re-handshake umbrella. In TLS 1.3 these two mechanisms are disassociated, and replaced by the re-key (to be discussed later) and the post-handshake authentication mechanism. The latter, is a mechanism that can be triggered only by the server, and requests the client to present a certificate. In GnuTLS the implementation relies on a new non-fatal error code
which must be handled by the client application. To avoid unintentional side-effects to existing software, this mechanism must be explicitly enabled
by the client and the server. That enablement is done by specifying
GNUTLS_POST_HANDSHAKE_AUTH as a gnutls_init() flag in both client and server. Once that done, a
server can request post-handshake authentication from the client by
calling the new API, gnutls_reauth(), and the client should re-act to the
GNUTLS_E_REAUTH_REQUEST error code, by calling the same function.<br />
<br />
<h4>
Re-keying</h4>
Under TLS 1.3 applications can re-key with a very simple mechanism which involves the transmission of a single message. Furthermore, GnuTLS handles re-key transparently and every GnuTLS client and server will automatically re-key after 2^24 messages are exchanged, unless the GNUTLS_NO_AUTO_REKEY flag is specified in gnutls_init(), or the cipher's security properties requires no re-keying as in the CHACHA20-POLY1305 cipher.<br />
<br />
To accomodate for well-written applications which were using the re-handshake mechanism of TLS 1.2 to perform re-key, the gnutls_rehandshake() and gnutls_handshake() calls under TLS 1.3 perform a re-key on server and client side respectively.<br />
<br />
Server applications which were relying on the re-handshake process to re-authenticate the client must be modified to take advantage of post-handshake authentication under TLS 1.3.<br />
<br />
<br />
<h4>
Message length hiding</h4>
In TLS 1.3 it is possible to hide the length of
the transmitted data on the wire by introducing padding bytes. To take
advantage of that, we enhanced the gnutls_record_send_range()
and related APIs, and after realizing their complexity when performing certain length hiding tasks, we decided to introduce a
new and simple API for adding padding data. That is, the gnutls_record_send2()
API. The new API allows sending an arbitrary amount of data, together with an
arbitrary amount of padding limited only by the record constraints.<br />
<br />
<h4>
Attaching multiple OCSP staples</h4>
Under TLS 1.3, servers and clients can attach OCSP responses for more than a single certificate in their certificate chain. That is, they can provide fresh responses for their certificate authority, or other intermediate authorities, making the task of certificate validation easier for the peer, without involving the OCSP server during the handshake.<br />
<br />
The addition of that functionality resulted to enhancements in the ocsptool utility, in order to be able to export and import OCSP responses in PEM format, something that allows them to be combined with the already PEM-encoded certificate chains. Applications could then use the APIs gnutls_certificate_set_ocsp_status_request_mem() or gnutls_certificate_set_ocsp_status_request_file2() to specify OCSP responses which correspond to their certificates.<br />
<br />
<br />
<h4>
RSA-PSS certificates and TLS 1.3 deployment</h4>
When we introduced support for RSA-PSS keys and certificates in GnuTLS 3.6.0, we saw them at the time as necessary for TLS 1.3 negotiation, and as a potential to increase the overall protocol security. However, that never happened through the TLS 1.3 drafts, possibly due to striking a balance to the need for security against cross-protocol attacks and compatibility with existing keys and practices. Furthermore, RSA-PSS keys and certificates are quite new, not being universally supported by CAs or by hardware security modules and smart cards.<br />
<br />
As such, although RSA-PSS certificates are allowed by the protocol and supported by GnuTLS, the expected method to obtain an RSA-PSS signature in TLS 1.3, is by utilizing a "legacy" RSA PKCS#1 1.5 certificate associated with a multi-purpose RSA key. That is, a legacy RSA key is expected to be used for RSA-PSS, PKCS#1 1.5 signatures and PKCS#1 1.5 decryption. That, to a cryptographer, voids any security proofs available to RSA-PSS algorithm, since such proofs assume a key which is used for a single purpose.<br />
<br />
That, although it may have failed to provide a bump in the overall Internet security, had quite
good usability reasons to back it up. We are far from having a universal support of RSA-PSS certificates in existing software or hardware, and the ability to re-use the exact same setup and keys as a TLS 1.2 server was seen as of paramount importance in the TLS working group. The protocol designers recognized, however, the security issues and have documented the best
practices sufficient to defend against the worst offender in RSA key attacks. That is, against the RSA PKCS#1 (decryption) ciphersuites, which have been the
root of every new clone of Bleichenbacher's attack. Their recommendation is <a href="https://tools.ietf.org/html/draft-ietf-tls-tls13-28#appendix-E.7">to disable the static RSA ciphersuites</a> on TLS 1.3 servers. That is not done (at least for now) by GnuTLS by default, though, it can be achieved with a priority string which disables static RSA, e.g., "NORMAL:-RSA". The reason of not disabling these ciphersuites by default is to allow connections by legacy software and embedded software which often rely on the static RSA due to its simplicity.<br />
<br />
<h4>
RSA client certificates on smart cards and TLS 1.3 deployment</h4>
Under TLS 1.3 it is no longer possible to negotiate the older RSA signing standard, and thus existing smart cards containing RSA keys but not supporting the RSA-PSS mechanism, cannot be used under TLS1.3. There is no easy solution to that issue. Possible options could be (a) re-deploying all the smart cards with new which support RSA-PSS, or cars with the ECDSA algorithm, (b) disabling TLS 1.3 support on client or server side. At GnuTLS 3.6.8 we make sure that GnuTLS servers or clients when presented with such limited hardware, disable support for TLS1.3 transparently for applications instead of failing.<br />
<br />
<h4>
</h4>
<h4>
Key derivation</h4>
Although key derivation under TLS 1.3 uses
different algorithms under the hood, the standard interfaces from
RFC5705, continue to be functional for key derivation. As such the
interface <a href="https://www.gnutls.org/manual/html_node/Deriving-keys-for-other-applications_002fprotocols.html">gnutls_prf_rfc5705()</a>
must be used for key derivation by applications; older interfaces like
gnutls_prf_raw() or gnutls_prf() return an error code when used under TLS 1.3.<br />
<br />
<h4>
Session Resumption</h4>
Session resumption in the previous versions of
TLS consisted of exporting the serialized session data as negotiated by TLS the handshake to use them in a future
handshake. TLS 1.3 disassociates session resumption from
session parameters, and session resumption is an optional server
feature, advertised by the server in the form of a resumption ticket
which can be sent at any time after the handshake is complete, and can
be used only once to connect to the server. Merging the previous
resumption semantics with the new, was quite a challenge, though it was possible. A difference with TLS 1.2 semantics is that a call to gnutls_session_get_data2() could wait to receive data from the network, for a maximum of 50 milliseconds.<br />
<br />
<h2>
What about applications not utilizing certificates?</h2>
This short section provides information for existing applications which rely on the SRP, Anonymous or PSK key exchanges which were available under TLS 1.2.<br />
<br />
<h4>
SRP / RSA-PSK key exchange</h4>
SRP and RSA-PSK key exchanges are not supported in TLS 1.3, so when these key exchanges are present in a priority string, TLS 1.3 is disabled.<br />
<br />
<h4>
Anonymous key exchange</h4>
There is no anonymous key exchange supported under TLS 1.3, so if an anonymous key exchange method is set in a priority string, and no certificate credentials are set in the client or server TLS 1.3 will not be negotiated. That approach allows for TLS 1.3 to be negotiated when a server or client supports both anonymous and certificate key exchange, i.e., when supporting an opportunistic-encryption negotiation scenario.<br />
<br />
<h4>
PSK key exchange</h4>
The pre-shared key exchange is supported in TLS 1.3, thus any existing setup with pre-shared key is unaffected by the upgrade to TLS 1.3. Both the Diffie-Hellman and "pure" PSK are supported under the new protocol, however in the priority strings the 'ECDHE-PSK' and 'DHE-PSK' options are handled as synonyms and they indicate the intent to support an ephemeral key exchange with the pre-shared key; the parameters of the key exchange, e.g., elliptic curves vs finite field, are negotiated with the supported groups specified in the priority string.<br />
<br />
A thing to note is that although certificates are protected against passive eavesdroppers in TLS 1.3, PSK usernames are still sent in the clear, as in TLS 1.2.<br />
<br />
<h4>
Authentication-only ciphersuites</h4>
Ciphersuites with the NULL cipher (i.e., authentication-only) are not supported in TLS 1.3, so when
they are specified in a priority string, TLS 1.3 is
disabled.<br />
<br />
<h2>
Deprecated features</h2>
During the GnuTLS 3.6.x releases there was a significant effort to eliminate obscure options and code which could prove a liability in the future. As part of that, support for compression, OpenPGP authentication and SHA2-224 signatures in TLS key exchange was removed, along with their corresponding code. Furthermore, the DSA signature algorithm and the Camellia and 3DES ciphers were disabled by default for TLS sessions, while SHA1 was marked as insecure for certificate signatures.<br />
<br />
<h2>
What's next?</h2>
<br />
Although, a functional part of the TLS 1.3 protocol is implemented in GnuTLS, there are few items which are still missing and are marked with <a href="https://gitlab.com/gnutls/gnutls/issues?label_name%5B%5D=tls1.3+additional+features">this label</a>. Furthermore, we would like to extend our existing test suite for TLS 1.3 which consists of unit and interoperability tests, with the <a href="https://github.com/tomato42/tlsfuzzer">tlsfuzzer</a> TLS 1.3 test suite once that is made available. The advantage of the tlsfuzzer test suite, is its design with an attacker mindset and helps uncover issues in corner and rare cases. The inclusion of this test suite will be a prerequisite for the 3.6.x branch being marked as the stable branch [update in 2019-5-25: this branch is already marked as stable and the tlsfuzzer test suite is incorporated]. <br />
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
</style>
Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com0tag:blogger.com,1999:blog-1625673575821156689.post-19389320334472518092017-08-21T08:42:00.000+02:002017-11-01T15:56:29.338+01:00An overview of GnuTLS 3.6.0The new 3.6.0 GnuTLS release contains several new features, back-end changes and clean ups. This is a release which re-spins the so-called 'stable-next' branch, meaning that once considered stable enough, this branch will replace the current stable branch. The main target of this release was to have a library ready to incorporate new protocol additions such as TLS 1.3, which is currently in draft specification and is expected to be finalized in the coming months. That "preparation", spans from introducing new functionality needed for the new protocol features, improving the testing and fuzzying infrastructure of the library to reduce regressions and non-standards compliant behavior, to the removal of features and components which are no longer relevant in today's Internet Public Key Infrastructure.<br />
<br />
In short, this release introduces a new lock-free random generator and adds new TLS extensions shared by both TLS 1.2 and 1.3, such as Finite Field Diffie Hellman negotiation, Ed25519 and RSA-PSS signatures. These additions modernize the current TLS 1.2 support and pave the way for TLS 1.3 support in the library. Furthermore, <a href="https://github.com/tomato42/tlsfuzzer">tlsfuzzer</a> is introduced in our continuous integration test suite. <a href="https://github.com/tomato42/tlsfuzzer">Tlsfuzzer, is a meticulous TLS test suite</a>, which tests the behavior of the implementation on
various corner (and not) cases, and acts complementary to the internal GnuTLS test suite and its unit testing. This release, also eliminates a lot of legacy code, in order to reduce complexity and improve the manageability of the library, preventing legacy code to be used as a potential attack vector.<br />
<br />
Further changes to support TLS 1.3 will be included on this release branch.<br />
<br />
The following paragraphs go through the
most significant changes of the 3.6.0 release.<br />
<br />
<h3>
Testing and Fuzzying</h3>
<ul>
</ul>
<h4>
<b>Fuzzying infrastructure</b></h4>
Fuzzying in the sense of trying arbitrary input to the library and testing its behavior under invalid and valid but rare inputs is not something new. However, in GnuTLS previously, fuzzying of various components of the library was done in a non-systematic way, usually by 3rd parties who then reported any issues found. That as you can imagine is an unreliable process. Without common fuzzying infrastructure, there is no fuzzying code or infrastructure re-use, forcing each and every person attempting to fuzz GnuTLS functionality to re-invent the wheel. Driven by the availability of <a href="https://testing.googleblog.com/2016/12/announcing-oss-fuzz-continuous-fuzzing.html">Google's OSS-Fuzz project</a>, and with the contributions of <a href="https://lists.gnupg.org/pipermail/gnutls-devel/2017-May/008418.html">Alex Gaynor</a>, Tim Ruehsen and yours truly, there is now a <a href="https://gitlab.com/gnutls/gnutls/tree/master/fuzz">common fuzzying base</a> testing several aspects of the library. That fuzzying test suite is run automatically under OSS-Fuzz, uncovering issues, and filling bugs against the library (and that's the part where automation stops).<br />
<br />
<ul>
</ul>
<h4>
<b>tlsfuzzer</b></h4>
<a href="https://github.com/tomato42/tlsfuzzer">TLS fuzzer</a> is TLS server implementation testing tool used at Red Hat for testing the quality of TLS implementations. It checks the behavior of an implementation on various corner (and not) cases, providing a tool not only for testing correctness of an implementation but for ensuring that no behavioral regressions are introduced undetected. With this release GnuTLS incorporates this testing tool on its continuous integration infrastructure, ensuring behavioral stability and thorough testing of existing and new functionality. Since the library is now modified for TLS 1.3, tlsfuzzer's use is invaluable as it allows detecting major or minor behavioral changes in the old protocol support, early.<br />
<br />
<ul>
</ul>
<h4>
CII best practices</h4>
The Core Infrastructure Initiative (CII) of Linux Foundation provides <a href="https://bestpractices.coreinfrastructure.org/">a best practices badge</a>, as a way for Free software to demonstrate they follow best software engineering practices. The practices include change control, quality, static analysis, security, even bug reporting. Although several of these practices were already in use in the project, the process of going through that manual inspection of processes, uncovered several weaknesses and omissions which are now resolved. Taking the time to go through the manual inspection was the most difficult part, as there is always something more important to address; however, I believe that the time spent on it was worthwhile. My impression is that there has been quality work behind the formulation of these practices, and I'd recommend any free software project to seriously consider following them. You can view <a href="https://bestpractices.coreinfrastructure.org/projects/330">the result of GnuTLS' inspection here</a>.<br />
<h3>
</h3>
<h3>
Random Number Generation</h3>
<ul>
</ul>
<h4>
<b>A new lock-free random generator</b></h4>
Versions of GnuTLS 3.3 and later rely on two random generators. The
default is based on a combination of Salsa20/12 stream cipher for nonces, and Yarrow/AES for everything else. The other generator is the AES-CTR-DRBG, which is an AES-based deterministric random bit
generator and is used <i>optionally</i> when the library is compiled with FIPS140-2 support and the system is in FIPS140-2 mode. Both of these
generators operate under a global lock, making them a performance
bottleneck for multi-threaded applications. Having such bottleneck in single-CPU systems or even 2-4 CPU systems in the past may have been an acceptable cost; today however as the number of CPUs in a single system increase past these numbers, such global locks severely harm performance. To address that, in GnuTLS 3.6.0 the random
generator component was essentially re-written to address the bottleneck
issue, simplify entropy gathering, as well as fix other issues found over the years. The end result, is a separate random generator per-thread, and there is a single default generator, based on the stream cipher CHACHA. The optional generator AES-CTR-DRBG remains the same. I'll
not go further in the design of the new random generator, though you
can find a detailed description of the changes <a href="http://nmav.gnutls.org/2017/03/improving-by-simplifying-gnutls-prng.html">on this post</a>.<br />
<ul>
</ul>
<h3>
</h3>
<h3>
</h3>
<h3>
TLS Features </h3>
<ul>
</ul>
<h4>
<b>Finite Field Diffie-Hellman parameter negotiation (RFC7919)</b></h4>
If you have setup any TLS server, or have developed an application which uses TLS, most likely you would have seen references to Diffie-Hellman parameter files and their generation. In the early versions of GnuTLS I recommended generating them daily or weekly, provided certtool options to generate them by following specific security levels, and so on. The truth is that there were no available best practices that protocol designers, or implementers could refer to on how these parameters should be used correctly. As it always happens in these cases the burden is pushed to the application writers, and I guess the application writers push that further to the application users. Fortunately, with the publication of RFC7919, the DH parameter handling becomes the responsibility of the TLS protocol itself, and they are now negotiated without any input from the application (maybe except the desired security parameter/level). GnuTLS 3.6.0 implements that feature removing the need for server applications to specify Diffie-Hellman parameters, but in a backwards compatible way. Applications which already specify explicitly the DH parameters, will still function by overriding that negotiation.<br />
<br />
In practice this feature introduces the notion of groups, that replace the previous notion of curves. Applications which were setting support for explicit curves via priority strings like "NORMAL:+CURVE-X25519", could now use "NORMAL:+GROUP-X25519" with identical functionality. The groups act as a superset of the curves, and contain the finite field groups for Diffie-Hellman, such as GROUP-FFDHE2048, GROUP-FFDHE3072, etc.<b> </b><br />
<br />
<h4>
<b>Digital signatures with Ed25519</b></h4>
Although curve <a href="http://nmav.gnutls.org/2016/05/gnutls-3-5-0.html">x25519 was already supported for TLS ephemeral key exchange</a>, there was no way to utilize certificates and private keys with the Ed25519 signature algorithm. This is now supported both for certificate signing and verification, as well as for TLS key exchange (following <a href="https://tools.ietf.org/html/draft-ietf-tls-rfc4492bis-17">draft-ietf-tls-rfc4492bis-17</a>). In contrast with RSA or even ECDSA, these keys offer an impressive performance, and are notoriously small, even in their PKCS#8 container. That is easily demonstrated with the certtool output below. The key consists of three lines, two of which are the PEM boilerplate. <br />
<pre>certtool --generate-privkey --key-type ed25519
...
-----BEGIN PRIVATE KEY-----
MC4CAQAwBQYDK2VwBCIEIKVpRaegFppd3pDQ3wpHd4+wBV3gSjhKadEy8S1J4gEd
-----END PRIVATE KEY-----
</pre>
<br />
Given the expected switch to post-quantum resistant algorithms in the not-so-far away future, that may be the last chance to utilize algorithms with such a small key size.<br />
<br />
<h4>
<b>Digital signatures with RSA-PSS</b></h4>
That was the change that required by far the largest amount of code changes in GnuTLS 3.6.0; it required changes both in GnuTLS and nettle, so I'll dedicate few more lines to it. The feature was contributed mainly by Daiki Ueno, and was further extended by me. If you are not aware of the spicy details of cryptographic protocols today, RSA signing today is universally being used with a construction called PKCS#1 v1.5, as a tribute to the document that it was described at. Even though no attacks are known for the PKCS#1 v1.5 signing algorithm, the very similar PKCS#1 RSA decryption construction was successfully attacked in 1996 by Bleichenbacher, generating doubt on its cryptographic properties.<br />
<br />
In order to prevent similar issues in the future, another RSA signing construction was defined in a later revision (v2) of the PKCS#1 document, named RSASSA-PSS (referred to as RSA-PSS from now on). That method, involves hash functions, and a salt, in order to provide a primitive with a security proof. The proof guarantees that the longer the salt, the stronger the security properties, with stronger being, unfortunately, undefined in any tangible terms. The best current practice followed by the <a href="https://tools.ietf.org/html/rfc8017">PKCS#1 2.2</a> document is to tie the salt size with the size of the hash function involved, and thus associate directly the key security parameter with the hash function used in RSA-PSS signatures.<br />
<br />
As mentioned above, RSA-PSS introduces optional parameters to a key or certificate. The parameters help the operator of the key (e.g., the software) sign using the desired security level. These parameters include the following information.<br />
<br />
<pre> RSASSA-PSS-params ::= SEQUENCE {
hashAlgorithm [0] HashAlgorithm,
maskGenAlgorithm [1] MaskGenAlgorithm,
saltLength [2] INTEGER,
trailerField [3] TrailerField
}
</pre>
That is, a key is associated with two different hashes (hashAlgorithm and maskGenAlgorithm), a variable salt size, and an unused for Internet PKI trailerField. To simplify generation and usage of such keys, GnuTLS 3.6.0 generates keys by default with no parameters, that is, keys that can be used with any hash or salt size (except SHA1 which is intentionally not supported). That form of keys is most suitable for servers which typically sign using any algorithm supported by the connected client. For CA keys and keys which require a consistent security level to be used, these parameters can be set, though GnuTLS will require the hash
algorithms in hashAlgorithm and maskGenAlgorithm to match. Keys with non-matching algorithms, e.g., a key using SHA256 for hashAlgorithm and SHA512 for maskGenAlgorithm, are rejected as invalid.<br />
<br />
To generate an RSA key for use only with RSA-PSS signatures, use the following command.<br />
<pre>certtool --generate-privkey --key-type rsa-pss
</pre>
<br />
To generate a key for RSA-PSS with a specific hash algorithm (the salt size will be obtained from it), use the following command:<br />
<pre>certtool --generate-privkey --key-type rsa-pss --hash sha384</pre>
<br />
Note however, that very few applications accept keys intended only for RSA-PSS signatures. A more
compatible approach is to generate an RSA key (which works for any
purpose), and utilize that one to sign with the RSA-PSS signature
algorithm. When that key is used in the context of TLS, it will be used for both RSA-PSS and plain PKCS#1 v1.5 signatures. As any cryptographer would tell you, that usage invalidates the RSA-PSS security proof, and underlines the need to utilize separate keys for the different algorithms.<br />
<br />
As such, it is possible with GnuTLS to use separate
keys for RSA PKCS#1 v1.5, and RSA-PSS, in order to reduce any risk due to the
interaction between these two algorithms. When a GnuTLS server
is provided with two keys, RSA and RSA-PSS, the latter
will be used for RSA-PSS operations, and the former for the legacy PKCS#1 v1.5 operations.<br />
<br />
<h3>
Removed/Disabled functionality</h3>
<ul>
</ul>
<h4>
<b>3DES cipher is no longer enabled by default for TLS</b></h4>
Although the 3DES cipher is the mandatory option for TLS 1.0 and TLS 1.1, the cipher is unfortunately a relic of a different era. It is a 64-bit block cipher, which limits the amount of data ut can safely operate on, it is based on cipher with a 56-bit key size, and operates in encryption-decryption-encryption (EDE) mode to overcome the previous limitation. As such, that cipher provides a performance unacceptable for today and is only being used to interoperate with legacy hardware and software. As such, this cipher will no longer be enabled by default, but applications requiring should provide the end-user the necessary knobs to enable it (e.g., a priority string which includes "+3DES-CBC").<br />
<br />
<ul>
</ul>
<h4>
SHA1 is no longer acceptable for certificate signing</h4>
SHA1 used to be the de facto algorithm in X.509 certificates, or any other digital signature standards. Given the collision attacks on SHA1 and <a href="https://blog.mozilla.org/security/2016/10/18/phasing-out-sha-1-on-the-public-web/">the fact that it has been phased out from the public web</a>, GnuTLS will not accept SHA1 signatures on certificates as trusted by default. SHA1 will remain acceptable for other types of signatures as it is still widely used. Note, however, that the existing collision attacks do not translate directly to an attack on digital signatures with SHA1. The removal is a precaution and preparation for its complete phasing out. The reason is, that even though direct attacks are not applicable on SHA1-based digital signatures, the experience with the attacks on MD5 the previous decade, shows that there can be clever ways to take advantage of collision attacks in order to forge certificates.<br />
<ul>
</ul>
<h4>
OpenPGP functionality was removed</h4>
When I originally started working on GnuTLS I was envisioning a future where OpenPGP certificates will be used instead of X.509. My driver was the <i>perceived</i> simplicity of OpenPGP certificate format, and the fact that obtaining a certificate at the time required the intervention of costly CA, in contrast with OpenPGP where one had to generate a key and manage its web of trust. That never took off as a deployment nor idea, and today none of the original driving factors are valid. OpenPGP certificates are not significantly simpler to parse than X.509, the web-of-trust proved to be a more difficult problem than Internet PKI, and the costly CAs verification issue is no longer relevant after <a href="http://letsencrypt.org/">letsencrypt.org</a>.<br />
<ul>
</ul>
<h4>
<b>IDNA2003 is no longer supported</b></h4>
IETF has switched to IDNA2008 for internationalized domain names since long time and as such GnuTLS will no longer provide compatibility code for the older standard. Internationalized domain names may not be widely known in the english speaking world, however, their use varies around the world. Hence, supporting them is necessary in order to be able to properly handle of PKIX (X.509) certificates and verification, with internationalized domain names. See my previous post for <a href="http://nmav.gnutls.org/2017/04/the-mess-with-internationalized-domain.html">a more detailed description of IDNA today</a>.<br />
<ul>
</ul>
<h4>
<b>TLS compression functionality was removed</b></h4>
Compression prior to encryption was always considered a good thing, not because it eliminates correlations in plaintext due to language or file format in use, but also because it reduces the size of the transmitted data, and the latter is a significant performance benefit in restricted by bandwidth lines. Why did we remove it then? The reason is that after compression the ciphertext length, which in TLS 1.2 is in clear, may reveal more information about the data, and that, becomes a confidentiality breach issue when data are partially under the control of the attacker. This property has been exploited in attacks like the <a href="https://en.wikipedia.org/wiki/CRIME">fancy-named CRIME</a> attack.<br />
<br />
Given the above, the currently held belief in protocol design is to delegate compression to application protocols, e.g., TLS 1.3 will not include support for compression, and for that we believe that there are more benefits in removing that feature completely, reducing the attack surface of the library, rather than keeping it as a legacy feature.<br />
<ul>
</ul>
<br />
<h3>
Concluding remarks</h3>
<br />
I'd like to sincerely thank everyone who has contributed for the GnuTLS 3.6.0 release to be possible. The git shortlog follows; happy hacking!<br />
<br />
<br />
<pre>Alex Gaynor (12):
Migrated fuzzers from the oss-repo to here.
Added a server fuzzer
Move to the devel dir
Describe the integration
Added a parser for PKCS7 importing and printing
Added a fuzzer for OpenPGP cert parsing
Do not infinite loop if an EOF occurs while skipping a PGP packet
Attempt to fix a leak in OpenPGP cert parsing.
Corrected a leak in OpenPGP sub-packet parsing.
Enforce the max packet length for OpenPGP subpackets as well
Do not attempt to parse a 32-bit integer if a packet is not 4 bytes.
Do not attempt to parse a 32-bit integer if a packet is not 4 bytes.
Alexander Kanavin (1):
Do not add cli-args.h to cli-args.stamp Makefile target
Alon Bar-Lev (19):
tests: suite: pkcs11: skip if no softhsm
tests: cert-tests: pkcs12 drop builddir usage
tests: skip tests that requires tools if tools are disabled
gitignore: sort()
gitignore: update [ci skip]
tests: skip tests that requires tools if tools are disabled
tests: suite: chain: support separate builddir
tests: remove bash usage
tests: skip tests that requires tools if tools are disabled
configure: remove void statement
valgrind: support separate builddir for suppressions.valgrind
.gitlab-ci.yml: add Fedora/x86_64/no-tools
build: doc: install images also into htmldir
tests: scripts: suppress which errors
tests: remove unused suppressions.valgrind
tests: suppressions.valgrind: supress fillin_rpath
tests: cert-tests: openpgp-certs: align test redirection
build: tests: resolve as-needed issue with seccomp
build: disable valgrind tests by default
Andreas Metzler (3):
Use NORMAL priority for SSLv23_*_method.
gnutls-cli: Use CRLF with --starttls-proto=smtp.
Fix autoconf progress message concerning heartbeat [ci skip]
Daiki Ueno (3):
build: import files from Nettle for RSA-PSS
x509: implement RSA-PSS signature scheme
nettle: ported fix for assertion failure in pss_verify_mgf1
Daniel Kahn Gillmor (1):
clarify documentation and arguments for psktool
David Caldwell (2):
Rename uint64 to gnutls_uint64 to avoid conflict with macOS
gnutls_x509_trust_list_add_system_trust: Add macOS keychain support
Dmitry Eremin-Solenikov (13):
configure.ac: remove autogen'erated files only if necessary
Add special MD5+SHA1 digest to simplify TLS signature code
Rewrite SSL/TLS signing code to use combined MD5+SHA1 digest
Rewrite SSL/TLS signature verification to use combined MD5+SHA1 digest
Use MAC_MD5_SHA1 instead of MAC_UNKNOWN to specify TLS 1.0 PRF
Cache MAC algorithm used for PRF function
Rework setting next cipher suite
Rework setting next compression method
Drop _gnutls_epoch_get_compression
Don't let GnuTLS headers in NETTLE_CFLAGS override local headers
Fix two memory leaks in debug output of gnutls tools
gnutls-serv: allow user to specify multiple x509certile/x509keyfile
Rework KX -> PK mappings
Karl Tarbe (2):
certtool: allow multiple certificates in --p7-sign
tests: add test for signing with certificate list
Marcin Cieślak (1):
<alloca .h=""> only if HAVE_ALLOCA_H
Martin Storsjo (2):
Fix a typo in a variable name in an m4 script
Avoid deprecation warnings when including gnutls/abstract.h
Matt Turner (1):
tests: Copy template out of ${srcdir}
Nicolas Dufresne (1):
rsa-psk: Use the correct username datum
Nikos Mavrogiannopoulos (1148):
...
Rical Jasan (1):
tests: Improve port-checking infrastructure.
Robert Scheck (1):
Add LMTP, POP3, NNTP, Sieve and PostgreSQL support to gnutls-cli
Tim Rühsen (11):
Add support for libidn2 (IDNA 2008 + TR46)
lib/system/fastopen: Add TCP Fast Open for OSX
Fix memleak in gnutls_x509_crl_list_import()
Fix memleaks in gnutls_x509_trust_list_add_crls()
fuzzer: Initial check in for improved fuzzing
fuzzer: Suppress unsigned integer overflow in rnd-fuzzer.c
fuzzer: Suppress leak in libgmp <= 6.1.2
fuzzer: Move regression corpora from tests/ to fuzz/
fuzzer: Add 'make -C fuzz coverage' [ci skip]
fuzzer: Fix include path in run-clang.sh [skip ci]
fuzzer: Update base64 fuzzers + corpora
</alloca></pre>
Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com0tag:blogger.com,1999:blog-1625673575821156689.post-38430916821199316272017-04-03T22:46:00.000+02:002017-09-30T14:57:52.745+02:00The mess with internationalized domain names<h1 id="the-mess-with-internationalized-domain-names">
</h1>
While internationalized domain names (DNS names) are not common in the English speaking world, they exist and their use was standardized by IETF's IDNA standards. I first found out the existence of that possibility while reading the IETF's <a href="https://tools.ietf.org/html/rfc6125">best practices for domain name verification</a>. As english is not my mother tongue I was particularly interested on the topic, and wanted to make sure that GnuTLS would handle such domains correctly both for storing such domains, and verifying them. That proved not to be an easy task. The following text summarizes my brief understanding of the issues in the field (disclaimer: I am far from an expert in software internationalization topics).<br />
<br />
<h2 id="how-does-idna-work">
How does IDNA work?</h2>
To make a long story short, the IDNA protocols are based on a simple principle. They translate domain names typed with unicode characters (UTF-8 or otherwise), to a US-ASCII (English text) representation which becomes the actual domain name. For example the greek name "ένα.gr" would translate to "xn--ixai9a.gr". On Linux systems one can find Simon Josefsson's idn and idn2 tools (more on that below), which can be used to translate from an internationalized string to IDNA format. For example:<br />
<br />
<pre><code> $ echo "ενα.gr"|idn
xn--mxahy.gr</code></pre>
<h2 id="what-are-the-issues-with-idna">
</h2>
<h2 id="what-are-the-issues-with-idna">
What are the issues with IDNA?</h2>
Although there are simple to use libraries (see <a href="https://www.gnu.org/software/libidn/">Libidn</a>) to access IDNA functionality, there is a catch. In 2010, IETF updated the IDNA standards with <a href="https://tools.ietf.org/html/rfc5890">a new set of standards called IDNA2008</a>, which were "mostly compatible" with the original standard (called IDNA2003). Mostly compatible meant that the majority of strings mapped to the same US-ASCII equivalent, though some didn't. They mapped to a different string. That affected many languages, including the Greek language mappins, and the following table displays the IDNA2003 and IDNA2008 mappings of few "problematic" Greek domain names.<br />
<br />
<table>
<thead>
<tr class="header">
<th align="center">non-English string</th>
<th align="center">IDNA2003</th>
<th align="center">IDNA2008</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td align="center">νίκος.gr</td>
<td align="center">xn--kxawhku.gr</td>
<td align="center">xn--kxawhkp.gr</td>
</tr>
<tr class="even">
<td align="center">νίκοσ.gr</td>
<td align="center">xn--kxawhku.gr</td>
<td align="center">xn--kxawhku.gr</td>
</tr>
<tr class="odd">
<td align="center">NΊΚΟΣ.gr</td>
<td align="center">xn--kxawhku.gr</td>
<td align="center">(undefined)</td>
</tr>
</tbody>
</table>
<br />
In the above table, we can see the differences in mappings for three strings. All of the above strings can be considered to be equal in the greek language, as the third is the capitalized version of the first, and the second is the "dumb" lower case equivalent of the last.<br />
<br />
The problematic character is 'σ' which in Modern Greek is switched with 'ς' when it is present at the end of word. As both characters are considered to be identical in the language, they are both capitalized to the same character 'Σ' (Sigma).<br />
<br />
There are two changes in IDNA2008 standard which affect the examples above. The first, is the treatment of the 'ς' and 'σ' characters as different, causing the discrepancy between the mappings in the first and second examples. The second is that IDNA2008 is defined only for a specific set of characters, and there is no pre-processing phase, which causes the undefined state of the third string, that contains capital letters. These changes, create a discrepancy between expectations formed by observing the behavior of domains consisting of US-ASCII strings and the actual reality with Internationalized scripts. Similar cases exist in other languages (e.g., with the treatment of the 'ß' character in German).<br />
<br />
Even though some work-arounds of the protocol may seem obvious or intuitive to implement, such as lower-casing characters prior to converting to IDNA format, lower-casing doesn't make sense in all languages. This is the reason that the capitalized version (NΊΚΟΣ.gr) of the first string on the table, is undefined in IDNA2008.<br />
<br />
You can verify the mappings I presented above with the idn2 application, which is IDNA2008-compliant. For example:<br />
<br />
<pre><code> echo "NΊΚΟΣ.gr"|idn2
idn2: lookup: string contains a disallowed character</code></pre>
<h2 id="is-there-any-solution">
</h2>
<h2 id="is-there-any-solution">
Is there any solution?</h2>
To address these issues, a different standards body --the Unicode consortium-- addressed the issue with the <a href="http://unicode.org/reports/tr46/#Mapping">Unicode Technical Standard #46</a> (UTS#46 or TR#46). That standard was published in 2016 to clarify few aspects of IDNA2008 and propose a compatible with IDNA2003 behavior.<br />
<br />
UTS#46 proposes two modes of IDNA2008, the transitional, which results to problematic characters being mapped to their IDNA2003 equivalents and the non-transitional mode, which is identical to the original IDNA2008 standard. In addition it requires the internationalized input to be pre-processed with the CaseFold algorithm which allows handling upper-case domain names such as "ΝΊΚΟΣ.gr" under IDNA2008.<br />
<h2 id="switching-to-idna2008">
</h2>
<h2 id="switching-to-idna2008">
Switching to IDNA2008</h2>
Unfortunately even with UTS#46, we are left with two IDNA2008 variants. The transitional which is IDNA2003 compatible and the non-transitional which is IDNA2008 incompatible. Some NICs and registrars have already switched to IDNA2008 non-transitional, but not all software has followed up.<br />
<br />
A problem is, that UTS#46 does not define a period for the use of transitional encodings, something that makes their intended use questionable. Nevertheless, as the end-goal is to switch to the non-transitional IDNA2008, it still makes it practical to switch to it, by clarifying several undefined parts of the original protocol (e.g., adds a pre-processing phase). As a result, few browsers (e.g., Firefox) have already switched to it. It is also possible for software based on libidn, which only supports IDNA2003, to switch. <a href="https://gitlab.com/libidn/libidn2/tags/libidn2-2.0.0">The libidn2 2.0.0 release</a> includes a <a href="https://libidn.gitlab.io/libidn2/manual/libidn2.html#Converting-from-libidn">libidn compatible APIs making it possible to switch to IDNA2008 (transitional or not)</a>.<br />
<h2 id="should-i-do-the-switch">
</h2>
<h2 id="should-i-do-the-switch">
Should I do the switch?</h2>
There are few important aspects of the IDNA2008 (non-transitional) domain names, which have to be taken into account prior to switching. As we saw above, the semantics of entering a domain in upper case, and expecting it to be translated to the proper web-site address wouldn't work for internationalized domain names. If one enters the domain "ΝΊΚΟΣ.gr", it would translate to the domain xn--kxawhku.gr (i.e., "νίκοσ.gr"), which is a misspelled version of the correct in Greek language "νίκος.gr".<br />
<br />
Moreover, as few software has switched to IDNA2008 non-transitional processing of domain names, there is always the discrepancy between the IDNA2003 mapping and the IDNA2008 mapping. That is, a domain owner would have to be prepared to register both the IDNA2003 version of the name and the IDNA2008 version of it, to ensure all users are properly redirected to his intended site. This is apparent on the following real domains.<br />
<ul>
<li>http://fass.de</li>
<li>http://faß.de</li>
</ul>
If you are a German speaker you most likely consider them equivalent, as the 'ß' character is often expanded to 'ss'. That is how IDNA2003 treated that character, however, that's not how IDNA2008 treats it. If you use the Chrome browser which at the moment uses IDNA2003 (or more precisely IDNA2008 transitional), both of these URIs you will be re-directed to the same web-site, fass.de. However, if you use Firefox, which uses IDNA2008, you will be re-directed to two different web sites. The first being the fass.de and the second the xn--fa-hia.de.<br />
<br />
That discrepancy was treated as a security issue <a href="https://curl.haxx.se/docs/adv_20161102K.html">by the curl and wget projects and was assigned CVE-2016-8625.</a> Both projects switched to non-transitional IDNA2008. <br />
<h2 id="what-about-certificates-can-they-address-the-issue-above">
</h2>
<h2 id="what-about-certificates-can-they-address-the-issue-above">
What about certificates, can they address the issue above?</h2>
Unfortunately the above situation, cannot be fixed with X.509 certificates and in fact such a situation undermines the trust in them. The operation of X.509 certificates for web site authentication, is based on the uniqueness of domain names. In english language we can be sure that a domain name, whether entered in upper or lower case will be mapped to unique web-site. With internationalized names that's no longer the case.<br />
<br />
What is unique in internationalized names is the final output domain, e.g., xn--kxawhku.gr, which for authentication purposes is meaningless as it is, so we have to rely on software to do the reverse mapping for us, on the right place. If the software we use uses different mapping rules than the rules applied by the registrar of the domain, users are left helpless as in the case above.<br />
<h2 id="what-to-do-now">
</h2>
<h2 id="what-to-do-now">
What to do now?</h2>
Although at this point, we know that IDNA2008 has quite some peculiarities which will be problematic in the future, we have no better option available. IDNA2003 cannot support new unicode standards and is already obsolete, so biting the bullet, and moving to non-transitional IDNA2008 seems like the right way to go. It is better to have a single and a little problematic standard, rather than have two active standards for domain name mapping.Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com0tag:blogger.com,1999:blog-1625673575821156689.post-81929114973343157292017-03-21T08:53:00.001+01:002017-03-24T10:33:35.541+01:00Improving by simplifying the GnuTLS PRNGOne of the most unwanted baggages for crypto implementations written prior to this decade is the (pseudo-)random generator, or simply PRNG. Speaking for GnuTLS, the random generator was written at a time where devices like <i>/dev/urandom</i> did not come by default on widely used operating systems, and even if they did, they were not universally available, e.g., devices would not be present, the <a href="http://egd.sourceforge.net/">Entropy Gathering Daemon</a> (EGD) was something that was actually used in practice, and was common for software libraries like libgcrypt to include code <a href="https://git.gnupg.org/cgi-bin/gitweb.cgi?p=libgcrypt.git;a=blob;f=random/rndunix.c;h=e7238f49f5e9c41b91a287615e4f2591fa5e0279;hb=refs/heads/master">to gather entropy on a system by running arbitrary command line tools</a>.<br />
<br />
That resulted in an internal random generator which had to rely on whatever was provided by the operating system and the administrator, and that, in several cases was insufficient to seed a cryptographic PRNG. As such, an advanced PRNG was selected, based on Yarrow, which kept a global per-process state, and was aggressively gathering information, including high precision timestamps and process/thread statistics, to enhance a potentially untrusted pool formed from the system random generator or EGD. That, also meant locks for multi-threaded processes to access the global state, and thus a performance bottleneck, since a call to the PRNG is required even for the simplest of crypto operations.<br />
<br />
Today, however, things have changed in operating systems. While Linux used to be a pioneer with <i>/dev/urandom</i>, now all operating systems provide a reliable PRNG, even though there are still no standardized APIs.<br />
<ul>
<li><b>Linux</b> provides <i>/dev/urandom</i>, <i>getrandom</i>(), <i>getentropy</i>()</li>
<li><b>Windows</b> provides CryptGenRandom()</li>
<li>*<b>BSD</b> provides /<i>dev/urandom, getentropy</i>()</li>
<li><b>MacOSX</b> provides <i>/dev/urandom, getentropy</i>()</li>
<li><b>Solaris</b>: <i>/dev/urandom, <a href="https://blogs.oracle.com/darren/entry/solaris_new_system_calls_getentropy">getentropy(), getrandom()</a>.</i></li>
</ul>
<span style="font-size: x-small;">On the list above, I ignore the /dev/random interface which has concerning properties, such as indefinite response time (see my previous post <a href="http://nmav.gnutls.org/2016/10/random-generator-linux.html">for limitations on the Linux interfaces</a>).</span><br />
<br />
Some of the interfaces above are provided as system calls, some others as libc calls, and others as file system devices, but for the application writer, that shouldn't make significant difference. These devices or system calls, provide access to a system PRNG, which is in short doing what was GnuTLS doing manually previously, mixing various inputs from the system, in a level and way that a userspace library like GnuTLS could never do, as the kernel has direct access to available hardware and interrupts.<br />
<br />
Given the above, a question that I've been asking myself lately, is whether there is any reason to continue shipping something advanced such as a Yarrow-based PRNG in GnuTLS? Why not switch to simple PRNG, seeded only by the system device? That would not only provide simplicity in the implementation, but also reduce the performance and memory cost of complex constructions like Yarrow. In turn, switching to something simple with low memory requirements would allow having a separate PRNG per-thread, further eliminating the bottleneck of a global per-process PRNG.<br />
<br />
<h4>
The current PRNG</h4>
<br />
To provide some context on GnuTLS' PRNG, it is made available through the following function all:<br />
<blockquote class="tr_bq">
<i>int </i><b>gnutls_rnd</b><i>(gnutls_rnd_level_t level, void *data, size_t len);</i></blockquote>
That takes as input an indicative level, which can be NONCE for generating nonces, RANDOM for session keys, or KEY for long term keys. The function outputs random data in the provided buffer.<br />
<br />
There was (a partial) attempt in GnuTLS 3.3.0 to improve performance, by introducing a Salsa20-based PRNG for generating nonces, while keeping Yarrow for generating keys. This change, although it provided the expected performance improvement for the generation of nonces, it still kept global state, and thus still imposed a bottleneck for multi-threaded processes. At the same time, it offered no improvement on the memory consumption (in fact it was increased slightly by a Salsa20 instance - around 64 bytes).<br />
<br />
For the yet-unreleased 3.6.0, we took that enhancement several steps further, ensuing the elimination of the locking bottleneck for multi-threaded processes. It was a result of a relatively large patch set, improving the state of the internal PRNG, and rewriting it, to the following layout.<br />
<br />
<h3>
The new PRNG</h3>
<br />
The Yarrow and Salsa20 PRNGs were replaced by two independent PRNGs based on the CHACHA stream cipher. One PRNG is intended to be used for the NONCE level (which we'll refer to it as the nonce PRNG) and the other for KEY and RANDOM levels (the key PRNG). That reduces the memory requirements by eliminating the heavyweight Yarrow, and at the same time allows better use of the CPU caches, by employing a cipher that is potentially utilized by the TLS protocol, due to the CHACHA-POLY1305 ciphersuite.<br />
<br />
To make the state lock-free, these two generators keep their state per thread by taking advantage of thread local data. That imposes a small memory penalty per-thread --two instances of CHACHA occupy roughly 128-bytes--, albeit, it eliminates the bottleneck of locks to access the random generator in a process. <br />
<br />
<h4>
Seeding the PRNG</h4>
The PRNGs used by GnuTLS are created and seeded on the first call to gnutls_rnd(). This behavior is a side-effect of <a href="https://gitlab.com/gnutls/gnutls/merge_requests/111">a fix for getrandom() blocking in early boot in Linux</a>, but it fits well with the new PRNG design. Only threads which utilize the PRNG calls will allocate memory for it, and carry out any seeding.<br />
<br />
For threads that utilize the generator, the initial seeding involves calling the system PRNG, i.e., getrandom() in Linux kernel, to initialize the CHACHA instances. The PRNG is later re-seeded; the time of the re-seed depends both on time elapsed and the amount of bytes generated. At the moment of writing, the nonce PRNG will be re-seeded when 16MB of is generated, or 4 hours of operation, whichever is first. The key PRNG will re-seed using the operating system's PRNG, after 2MB of data are generated, or after 2 hours of operation.<br />
<br />
As a side note, that re-seed based on time was initially a major concern of mine, as it was crucial for a call to random generator to be efficient, without utilizing system calls, i.e., imposing a switch to kernel mode. However, in glibc calls like time() and gettimeofday() <a href="http://man7.org/linux/man-pages/man7/vdso.7.html">are implemented with vdso</a> something that transforms a system call like time(), to a memory access, hence do not introduce any significant performance penalty.<br />
<br />
The data limits imposed to PRNG outputs are not entirely arbitrary. They allow several thousands of TLS sessions, prior to re-seeding, to avoid re-introducing a bottleneck on busy servers, this time being the system calls to operating system's PRNG.<br />
<br />
<h4>
Defense against common PRNG attacks</h4>
There are multiple attacks against a PRNG, which typically require a powerful adversary with access to the process state (i.e., memory). There are also attacks on which the adversary controls part of the input/seed to PRNG, but we axiomatically assume a trusted Operating System, trusted not only in the sense of not being backdoored, but also in the sense of doing its PRNG job well. <br />
<br />
I'll not go through all the details of attacks (see <a href="https://gitlab.com/gnutls/gnutls/blob/master/doc/cha-internals.texi#L522">here for a more detailed description</a>), but the most prominent of these attacks and applicable to our PRNG are state-compromise attacks. That is, the attacker obtains somehow the state of the PRNG --think of a heartbleed-type of attack which results to the PRNG state being exposed--, and uses that exposed state to figure out past, and predict future outputs. <a href="https://imgs.xkcd.com/comics/security.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="195" src="https://imgs.xkcd.com/comics/security.png" width="320" /></a><br />
Given the amount of damage a heartbleed-type of attack can do, protecting against the PRNG state compromise attacks remind this <a href="https://xkcd.com/538/">pertinent XKCD strip</a>. Nevertheless, there is merit to protecting against these attacks, as it is no longer unimaginable to have scenarios where the memory of the PRNG is exposed. <br />
<h4>
</h4>
<h4>
Preventing backtracking</h4>
This attack assumes that the attacker obtained access to the PRNG state at a given time, and would need to recover a number of bytes generated in the <b>past.</b> In this construct, both the nonce and key PRNGs re-seed based on time, and data, after which recovery is not possible. As such an attacker is constrained to access data within the time or data window of the applicable generator.<br />
<br />
Furthermore, generation of long-term keys (that is, the generator under the KEY level), ensures that such backtracking is impossible. That is, in addition to any re-seed previously described, the key generator will re-key itself with a fresh key generated from its own stream after each operation.<br />
<br />
<h4>
Preventing permanent compromise</h4>
That, is in a way the opposite of the previous attack. The attacker, still obtains access to the PRNG state at a given
time, and would like to recover to recover <b>all</b> data generated in the future. In a design like this, we would like to limit the number of <b>future</b> bytes that can be
recovered.<br />
<br />
Again, the time and data windows of the PRNGs restrict the adversary's access within them. An attacker will have to obtain constant or periodic access to the PRNG state, to be able to efficiently attack the system.<br />
<br />
<br />
<h3>
Final remarks</h3>
<h4>
<span style="font-weight: normal;">The design of the new GnuTLS PRNG is quite similar to the arc4random implementation on the OpenBSD system. The latter despite its name, is also based on the CHACHA cipher. Few details differ, however. The GnuTLS PRNG enforces a refresh of the PRNG based on elapsed time, in addition to output data, does re-key only for when a requests for data at the KEY level, and strives for low memory footprint as it utilizes a separate generator per process thread.</span></h4>
<h4>
<span style="font-weight: normal;"> </span></h4>
<h4>
<span style="font-weight: normal;">Another thing to note, is that the fact that the <b>gnutls_rnd</b>() call allows for an advisory level to be specified, provides the internal implementation quite some flexibility. That is, the given level, although advisory, allows for optimizations to be enabled for levels that are not intended for secrecy. That is, apply different data and time limits on nonce and key generator, and thus increasing performance when possible. The cost of such a compromise for performance, is a larger window of exposure when the PRNG's state is compromised.</span></h4>
<h4>
<span style="font-weight: normal;"><br /></span></h4>
<h4>
<span style="font-weight: normal;">The generator described, will be made available in the next major release of GnuTLS, although the details may change.</span></h4>
<h4>
<span style="font-weight: normal;"><br /></span></h4>
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
</style>
Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com0tag:blogger.com,1999:blog-1625673575821156689.post-9862387578075563222016-11-13T15:39:00.000+01:002016-11-13T15:40:14.159+01:00Using the Nitrokey HSM with GnuTLS applicationsThe <a href="https://shop.nitrokey.com/shop">Nitrokey HSM</a> is an open hardware security module, in the form of a smart card token, which is used to isolate a server's private key from the application. That is, if you have an HTTPS server, such a hardware security module will prevent an attacker which temporarily obtained privileged access on the server (e.g., via an exploit like heartbleed), from copying the server's private key, allowing for impersonating it. See my <a href="http://nmav.gnutls.org/2014/04/software-has-bugs-now-what.html">previous post for a more elaborate discussion</a> on that defense mechanism.<br />
<br />
The rest of this post will explain how you can initialize this token and utilize it from GnuTLS applications, and in the process explain more about smart card and HSM usage in applications. For the official (and more advanced) Nitrokey setup instructions and tips you can see <a href="https://github.com/OpenSC/OpenSC/wiki/SmartCardHSM">this OpenSC page</a>, another interesting guide <a href="https://raymii.org/s/articles/Get_Started_With_The_Nitrokey_HSM.html">is here</a>.<br />
<br />
<h2>
HSMs and smart cards</h2>
<h3>
</h3>
Nitrokey HSM is something between a smart card and an HSM. However, there is no real distinction between smart cards and Hardware Security Module from a software perspective. Hardware-wise one expects better (in terms of cost to defeat) tamper-resistance on HSMs, and at the same time sufficient performance for server loads. An HSM module is typically installed on PCI slots, USB, while smart cards are mainly USB or via a card reader.<br />
<br />
On the software-side both smart cards and HSMs are accessed the same way, over the PKCS#11 API. That is an API which abstracts keys from operations, i.e., the API doesn't require direct access to the private key data to complete the operation. Most crypto libraries today support this API directly as GnuTLS and NSS do, or via an external module like OpenSSL (i.e., via <a href="https://github.com/OpenSC/libp11">engine_pkcs11</a>).<br />
<br />
Each HSM or smart card, comes with a "driver", i.e., a PKCS#11 module, which one had to specify on legacy applications. On modern systems, which have p11-kit, the available drivers are registered with p11-kit and applications can obtain and utilize them on run-time (see below for more information). For Nitrokey the <a href="https://github.com/OpenSC/OpenSC">OpenSC driver</a> is being used, a driver for almost every other smart card that is supported on Linux.<br />
<br />
If you are familiar with old applications, you would have noticed that objects were referred to as "slot1_1", which meant the first object on the first slot of the driver, or "1:1", and several other obscure methods depending on the application. The "slots" notion is an internal to PKCS#11, which is inherently unstable (re-inserting may change the slot number assignment), thus these methods to refer to objects cannot accommodate easily for multiple cards, or for referring to an object within a specific card if multiple are present, nor to easily utilize cards which are under the different drivers. More recent applications support <a href="https://tools.ietf.org/html/rfc7512">PKCS#11 URIs</a>, a method to identify tokens, and objects within the token which is unique system-wide; the URI looks like:<br />
<br />
<pre>pkcs11:token=SmartCard-HSM;object=my-ecc-key;type=private
</pre>
For GnuTLS applications, only PKCS#11 URIs can be used to refer to objects.<br />
<br />
<br />
<h2>
Driver setup and token discovery</h2>
<h3>
</h3>
On a typical Linux system which runs the pcscd server, and has opensc and p11-kit properly installed the following
command should list the nitrokey token once inserted.<br />
<pre> $ p11tool --list-tokens
</pre>
<br />
One of the entries printed should be something like the following.<br />
<pre>Token 5:
URL: pkcs11:model=PKCS%2315%20emulated;manufacturer=www.CardContact.de;serial=DENK0100424;token=SmartCard-HSM20%28UserPIN%29
Type: Hardware token
Manufacturer: www.CardContact.de
Model: PKCS#15 emulated
Serial: DENK0100424
Module: /usr/lib64/pkcs11/pkcs11/opensc-pkcs11.so
</pre>
<br />
The above information contains the identifying PKCS#11 URI of the token as well as information about the manufacturer and the driver library used. The PKCS#11 URI is a standardized unique identifier of tokens and objects stored within a token. If you do not see that information, verify that you have all of pcsc-lite, pcsc-lite-ccid, opensc, gnutls and p11-kit installed. If that's the case, you will need to register the opensc token to make it known to p11-kit manually (modern distributions take care of this step). This can be done with the following commands as administrator.<br />
<pre> # mkdir -p /etc/pkcs11/modules
# echo "module: /usr/lib64/pkcs11/opensc-pkcs11.so" >/etc/pkcs11/modules/opensc.conf
</pre>
<br />
It is implied that the your system's libdir for PKCS#11 drivers should be used instead of the "/usr/lib64/pkcs11" path used above. Alternatively, one could append the --provider parameter on the p11tool command, to explicitly specify the driver, as in the following example. For the rest of this text we assume a properly configured p11-kit and omit the --provider parameter.<br />
<pre> $ p11tool --provider /usr/lib64/pkcs11/opensc-pkcs11.so --list-tokens
</pre>
<br />
<h2>
Token initialization</h2>
<h3>
</h3>
An HSM token prior to usage needs to be initialized, and be provided two PINs. One PIN is for operations requiring administrative (security officer in PKCS#11 jargon) access, and the second (the user PIN ) is for normal token usage. To initialize use the following command, with the PKCS#11 URL listed by the 'p11tool --list-tokens' command; in the following text we will use $URL to refer to that.<br />
<pre> $ p11tool --initialize "$URL"
</pre>
<br />
Alternatively, when the driver supplied supports a single card, the URL can be specified as "<i>pkcs11:</i>" as shown below.<br />
<pre> $ p11tool --provider /usr/lib64/pkcs11/opensc-pkcs11.so --initialize "pkcs11:"
</pre>
<br />
The initialization commands above will ask to setup the security officer's PIN, which for nitrokey HSM is by default "<i>3537363231383830</i>"<code></code>. At the initialization process, the user PIN will also be asked. The user PIN is PIN which must be provided by applications and users, in order to use the card. Note that the command above (prior to GnuTLS 3.5.6) will ask for the administrator's PIN twice, once for initialization and once for setting the user PIN.<br />
<br />
<h2>
Key and certificate generation</h2>
<br />
It is possible to either copy an existing key on the card, or generate a key in it, a key which cannot be extracted. To generate an elliptic curve (ECDSA) key use the following command.<br />
<pre> $ p11tool --label "my-key" --login --generate-ecc "pkcs11:token=SmartCard-HSM20%28UserPIN%29"
</pre>
<br />
The above command will generate an ECDSA key which will be identified by the name set by the label. That key can be then by fully identified by the PKCS#11 URL "<i>pkcs11:token=SmartCard-HSM20%28UserPIN%29;object=my-key;type=private</i>". If the command was successful, the command above will list two objects, the private key and the public key.
<br />
<pre> $ p11tool --login --list-all "pkcs11:token=SmartCard-HSM20%28UserPIN%29"
</pre>
<br />
Note that both objects share the same ID but have different type. As this key cannot be extracted from the token, we need to utilize the following commands to generate a Certificate Signing Request (CSR).<br />
<br />
<pre> $ certtool --generate-request --load-privkey "pkcs11:token=SmartCard-HSM20%28UserPIN%29;object=my-key;type=private" --outfile cert.csr
</pre>
After providing the required information to certtool, it will generate a certificate request on cert.csr file. Alternatively, to generate a self-signed certificate, one can replace the '--generate-request' parameter with the '--generate-self-signed'.<br />
<br />
The above generated certificate signining request, will allow to get a real certificate to use for the key stored in the token. That can be generated either with <a href="https://letsencrypt.org/getting-started/">letsencrypt</a> or a local PKI. As the details vary, I'm skipping this step, and I'm assuming a certificate is generated somehow.<br />
<br />
After the certificate is made available, one can write it in the token. That step is not strictly required, but in several scenarios it simplifies key/cert management by storing them at the same token. One can store the certificate, using the following command.<br />
<pre> $ p11tool --login --write --load-certificate cert.pem --label my-cert --id "PUBKEY-ID" "pkcs11:token=SmartCard-HSM20%28UserPIN%29"
</pre>
Note that specifying the PUBKEY-ID is not required, but it is generally recommended for certificate objects to match the ID of the public key object listed previously with the --list-all command. If the IDs do not match some (non-GnuTLS) applications may fail to utilize the key. The certificate stored in the token will have the PKCS#11 URL "<i>pkcs11:token=SmartCard-HSM20%28UserPIN%29;object=my-cert;type=cert</i>".<br />
<br />
<br />
<h2>
Testing the generated keys</h2>
<br />
Now that both the key and the certificate are present in the token, one can utilize their PKCS#11 URL in any GnuTLS application in place of filenames. That is if the application is asking for a certificate file, enter "<i>pkcs11:token=SmartCard-HSM20%28UserPIN%29;object=my-cert;type=cert</i>", and for private key "<i>pkcs11:token=SmartCard-HSM20%28UserPIN%29;object=my-key;type=private</i>".<br />
<br />
The following example will run a test HTTPS server using the keys above.<br />
<br />
<pre> $ gnutls-serv --port 4443 --http --x509certfile "pkcs11:token=SmartCard-HSM20%28UserPIN%29;object=my-cert;type=cert" --x509keyfile "pkcs11:token=SmartCard-HSM20%28UserPIN%29;object=my-key;type=private;pin-value=1234"
</pre>
That will setup a server which answers on port 4443 and will utilize the certificate and key on the token to perform TLS authentication. Note that the command above, demonstrates the use of the "pin-value" URI element. That element, specifies the object PIN on command line allowing for non-interactive token access.<br />
<br />
<h2>
Applicability and performance</h2>
<br />
While the performance of this HSM will most likely not allow you to utilize it in busy servers, it may be a sufficient solution for a private server, VPN, a testing environment or demo. On client side, it can certainly provide a sufficient solution to protect the client assigned private keys. The advantage a smart card provides to OTP, is the fact that it is simpler to provision remotely, with the certificate request method shown above. That can be automated, at least in theory, when a protocol implementation of <a href="https://tools.ietf.org/html/draft-gutmann-scep-04">SCEP</a> is around. In practice, SCEP is well established in the proprietary world, but it is hard to find free software applications taking advantage of it.<br />
<h2>
</h2>
<h2>
Converting your application to use PKCS#11</h2>
<br />
A typical application written to use GnuTLS as TLS back-end library should be able to use smart cards and HSM tokens out of the box. The only requirement is for the applications to use the high-level file loading functions, which can load files or PKCS#11 URIs when provided. The only new requirement is for the application to obtain the PIN required for accessing the token, that can be done interactively using the PIN callbacks, or via the PKCS#11 URI "pin-value" element. For source examples, I'll refer you to GnuTLS documentation.<br />
<ul>
<li><a href="https://www.gnutls.org/manual/html_node/Client-using-a-smart-card-with-TLS.html">Client example utilizing PIN callbacks</a></li>
<li><a href="https://www.gnutls.org/manual/html_node/Echo-server-with-X_002e509-authentication.html">Server example which loads PKCS#11 URIs</a></li>
</ul>
Some indicative applications which I'm aware they can use tokens via PKCS#11 URIs transparently, and can be used for testing, are <a href="https://mod.gnutls.org/">mod_gnutls</a>, <a href="https://redmine.lighttpd.net/projects/lighttpd2/wiki">lighttpd2</a>, and <a href="http://www.infradead.org/openconnect/">openconnect.</a><br />
<br />
<br />
<br />
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
</style>
Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com0tag:blogger.com,1999:blog-1625673575821156689.post-14039610698705361142016-10-25T08:20:00.002+02:002016-10-25T08:20:50.092+02:00A brief look at the Linux-kernel random generator interfacesMost modern operating systems provide a cryptographic pseudo-random number generator (CPRNG), as part of their OS kernel, intended to be used by applications involving cryptographic operations. Linux is no exception in that, and in fact it was <a href="https://en.wikipedia.org/wiki//dev/random#Linux">the first operating system that actually introduced a CPRNG into the kernel</a>. However, there is much mystery around these interfaces. The <a href="https://linux.die.net/man/4/urandom">manual page</a> is quite unclear on its suggestions, while there is a <a href="http://www.2uo.de/myths-about-urandom/">web-site dedicated to debunking myths</a> about these interfaces, which on a first read contradicts the manual page.<br />
<br />
In this post, triggered by my recent attempt to understand the situation and <a href="http://marc.info/?l=linux-man&m=147695265313299&w=2">update the Linux manual page</a>, I'll make a brief overview of these interfaces. Note that, this post will not get into the insights of a cryptographic pseudo-random generator (CPRNG); for that, <a href="https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator">consider reading this article</a>. I will go through these interfaces, intentionally staying on the high-level, without considering internal details, and discuss their usefulness for an application or library that requires access to such a CPRNG.<br />
<br />
<ul>
<li><b>/dev/random</b>: a file which if read from, will output data from the kernel CPRNG. Reading from this file blocks once the kernel (using some a little arbitrary metric) believes not enough random events have been accumulated since the last use (I know that this is not entirely accurate, but the description is sufficient for this post).</li>
<li><b>/dev/urandom</b>: a file which if read from, will provide data from the kernel CPRNG. Reading from /dev/urandom will never block.</li>
<li><b>getrandom()</b>: A system call which provides random data from the kernel CPRNG. It will block only when the CPRNG is not yet initialized.</li>
</ul>
<br />
A software engineer who would like to seed a PRNG or generate random encryption keys, and reads the <a href="https://linux.die.net/man/4/urandom">manual page random(4)</a> carefully, he will most likely be tempted to use /dev/random, as it is described as "<i>suitable for uses that need very high quality randomness such as ... key generation</i>". In practice <b>/dev/random</b> cannot be relied on, because it requires large amounts of random events to be accumulated in order to provide few bytes of random data to running processes. Using it for key generation (e.g, for ssh keys during first boot) is most likely going to convert the first boot process to a coin flip; heads and system is up, tails and the system is left hanging waiting for random events. <a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=285371">This (old) issue</a> with a mail service process hanging for more than 20 minutes prior to doing any action, illustrates the impact of this device to real-world applications which need to generate fresh keys on startup.<br />
<br />
On the other hand, the device <b>/dev/urandom</b> provides access to the same random generator, but will never block, nor apply any restrictions to the amount of new random events that must be read in order to provide any output. That is quite natural given that modern random generators when initially seeded can provide enormous amounts of output prior to being considered broken (in an informational-theory sense). So should we use only <b>/dev/urandom</b> today?<br />
<br />
There is a catch. Unfortunately <b>/dev/urandom </b>has a quite serious flaw. If used early on the boot process when the random number generator of the kernel is not fully initialized, it will still output data. How random are the output data is system-specific, and in modern platforms, <a href="https://software.intel.com/en-us/blogs/2012/11/17/the-difference-between-rdrand-and-rdseed">which provide specialized CPU instructions to provide random data</a>, that is less of an issue. However, the situation where ssh keys are generated prior to the kernel pool being initialized, can be observed in virtual machines which have not been given access to the host's random generator.<br />
<br />
Another, though not as significant, issue is the fact that both of these interfaces require a file descriptor to operate. That, on a first view, may not seem like a flaw. In that case consider the following scenarios:<br />
<ul>
<li>The application calls chroot() prior to initializing the crypto library; the chroot environment doesn't contain any of /dev/*random.</li>
<li>To avoid the issue above, the crypto library opens /dev/urandom on an library constructor and stores the descriptor for later use. The application closes all open file descriptors on startup.</li>
</ul>
Both are real-world scenarios observed over the years of developing the GnuTLS library. The latter scenario is of particular concern since, if the application opens few files, the crypto library may never realize that the <b>/dev/urandom</b> file descriptor has been closed and replaced by another file. That may result to reading from an arbitrary file to obtain randomness. Even though one can introduce <a href="https://gitlab.com/gnutls/gnutls/blob/master/lib/nettle/rnd-linux.c#L150">checks to detect</a> such case, that is a particularly hard issue to spot, and requires inefficient and complex code to address.<br />
<br />
That's where the system call <b>getrandom()</b> fits. Its operation is very similar to /dev/urandom, that is, it provides non-blocking access to kernel CPRNG. In addition, it requires no file descriptor, and will also block prior to the kernel random generator being initialized. Given that it addresses, the issues of /dev/urandom identified above, that seems indeed like the interface that should be used by modern libraries and applications. In fact, if you use new versions of libgcrypt and GnuTLS today, they take advantage of this API (though that change <a href="https://gitlab.com/gnutls/gnutls/merge_requests/111">wasn't exactly a walk in the park</a>).<br />
<br />
On the other hand, <b>getrandom()</b> is still a low-level interface, and may not be suitable to be used directly by applications expecting a safe high-level interface. If one carefully <a href="http://man7.org/linux/man-pages/man2/getrandom.2.html">reads its manual page</a>, he will notice that the API may return less data than the requested (if interrupted by signal), and today this system call is not even wrapped by glibc. That means that can be used only via the syscall() interface. An illustration of (safe) usage of this system call, is given below.<br />
<br />
<pre>#include <sys/syscall.h>
#include <errno.h>
#define getrandom(dst,s,flags) syscall(SYS_getrandom, (void*)dst, (size_t)s, (unsigned int)flags)
static int safe_getrandom(void *buf, size_t buflen, unsigned int flags)
{
ssize_t left = buflen;
ssize_t ret;
uint8_t *p = buf;
while (left > 0) {
ret = getrandom(p, left, flags);
if (ret == -1) {
if (errno != EINTR)
return ret;
}
if (ret > 0) {
left -= ret;
p += ret;
}
}
return buflen;
}
</pre>
<br />
The previous example code assumes that the Linux kernel supports this system call. For portable code which may run on kernels without it, a fallback to /dev/urandom should also be included.<br />
<br />
From the above, it is apparent that using the Linux-kernel provided interfaces to access the kernel CPRNG, is not easy. The old (/dev/*random) interfaces APIs are difficult to use correctly, and while the <b>getrandom</b>() call eliminates several of their issues, it is not straightforward to use, and is not available in Linux kernels prior to 3.17. Hence, if applications require access to a CPRNG, my recommendation would be to avoid using the kernel interfaces directly, and use any APIs provided by their crypto library of choice. That way the complexity of system-discovery and any other peculiarities of these interfaces will be hidden. Some hints and tips are shown in <a href="https://docs.fedoraproject.org/en-US/Fedora_Security_Team/1/html/Defensive_Coding/ch14s02.html">the Fedora defensive coding guide</a> (which may be a bit out-of-date but still a good source of information).<br />
<br />Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com1tag:blogger.com,1999:blog-1625673575821156689.post-52517399120411828832016-06-02T21:50:00.000+02:002016-06-02T21:50:44.292+02:00Restricting the scope of CA certificatesThe granting of an intermediate CA certificate to a surveillance firm generated <a href="http://motherboard.vice.com/read/a-controversial-surveillance-firm-was-granted-a-powerful-encryption-certifica">quite some fuss</a>. Setting theories aside, the main reason behind that outcry, is the fact that any intermediate CA certificate trusted by the browsers has unlimited powers to certify any web site on the Internet. Servers can protect themselves against an arbitrary CA generating a valid certificate for their web site, <a href="https://tools.ietf.org/html/rfc7469">using certificate pinning</a>, but there is very little end-users can do. In practice, end-users either trust the whole bundled CA list in their browser/system or not.<br />
<br />
An option for end-users is to <a href="http://nmav.gnutls.org/2012/02/need-for-ssh-like-authentication-in-tls.html">utilize trust on first use</a>, but that is not a widespread practice, and few software, besides for SSH, support it. A way for me as a user to defend against a believed to be rogue CA, is by disabling or removing that CA from my trusted bundle. But what if I trust that CA for a particular web site or domain, but not for the whole Internet? <br />
<br />
On this post I'll try to provide more information on some lesser
documented aspects of p11-kit, which provide additional control over the
CA certificate bundle in a system. That is, I'll explain how we can do better than disabling CAs, and how we can restrict CAs to particular domains. The following instructions are limited to Fedora 22+ which has deployed a <a href="https://fedoraproject.org/wiki/Features/SharedSystemCertificates">shared trust database</a> for certificates based on p11-kit. This database, is not only an archive of trusted certificates, but also provides the option to attach additional attributes to CA certificates in the form of PKIX extensions. These extensions are called stapled extensions in p11-kit jargon and they override any extensions available in the trust certificates. That, allows to enforce additional restrictions to the purpose and scope of a certificate.<br />
<br />
I'll attempt to demonstrate this feature using an example. Let's consider the case where your employer's IT department provided you with a CA certificate to trust for communications within the company. Let's also assume that the company's internal domain is called "<i>example.com</i>". In that scenario as a user I'd like to restrict the provided CA certificate to <i>example.com</i> domain to prevent anyone with access to the corporate private key from being able to hijack any connection outside the company scope. This is not only out of paranoia against a potential corporate big-brother but also to keep a good security practice and avoid having master keys. A stolen corporate CA key which is trusted for everything under the sun provides a potential attacker not only with access to company's internal communication, but also with access to Internet communication of any corporate user.<br />
<br />
How would we install such certificate in a way that it is restricted only to <i>example.com</i>? Assuming that the CA certificate is provided at the <i>example.com-root.pem</i> file<i>,</i> the following command will add the company's certificate to the trusted list.<br />
<pre>$ sudo trust anchor example.com-root.pem
</pre>
<br />
That will create a file in /etc/pki/ca-trust/source containing the CA certificate (for more information on adding and removing CA certificates in Fedora see the update-ca-trust manpage).<br />
<br />
If we edit this file we will see something like the following.<br />
<pre>[p11-kit-object-v1]
trusted: true
x-distrusted: false
private: false
certificate-category: authority
-----BEGIN CERTIFICATE-----
MIIDsDCCAxmgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCVVMx
...
-----END CERTIFICATE-----
</pre>
<br />
This contains the certificate of the CA as well as various basic flags set to it.<br />
How can we now attach a stapled extension to it?<br />
<br />
We need to add another object in that database containing the extension. But let's see the process step by step. First we need to extract the certificate's public key because that's how p11-kit identifies existing objects. A command to achieve that is the following:<br />
<pre>$ certool --pubkey-info --infile example.com-root.pem --outfile example.com-pubkey.pem
</pre>
<br />
The output file will contain a public key in PEM format (identifiable by the "-----BEGIN PUBLIC KEY-----" header). We now edit the p11-kit file in /etc/pki/ca-trust/source containing our certificate and append the following.<br />
<pre>[p11-kit-object-v1]
class: x-certificate-extension
label: "Example.com CA restriction"
object-id: 2.5.29.30
value: "%30%1a%06%03%55%1d%1e%04%13%30%11%a0%0f%30%0d%82%0b%65%78%61%6d%70%6c%65%2e%63%6f%6d"
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
</pre>
<br />
Where the public key part is copied from the <i>example.com-pubkey.pem</i> file.<br />
<br />
This added object, is a stapled extension containing a <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.10">PKIX name constraints</a> extension which allows this CA to be used for certificates under the "<i>example.com</i>" domain. If you attempt to connect to a host with a certificate of this CA you will get the following error:<br />
<pre>$ gnutls-cli www.no-example.com
...
Status: The certificate is NOT trusted. The certificate chain violates the signer's constraints.
*** PKI verification of server certificate failed...
</pre>
<br />
Note that, although NSS and openssl applications check some extensions (such as key purpose) from this trust database, they do not consider the name constraints extension. This may change in the future, but currently only GnuTLS applications under Fedora will honor this extension. The reason it works under Fedora distribution is because GnuTLS is compiled using the <i>--with-default-trust-store-pkcs11="pkcs11:"</i> configuration option which makes it use the p11-kit trust DB directly.<br />
<br />
A question at this point, after seeing the p11-kit object format, is how can we generate the "value" listed above containing the desired constraints? The value contains a DER encoded certificate extension which corresponds to the object identifier "object-id" field. In this case the object-id field contains the object identifier for NameConstraints extension (2.5.29.30).<br />
<br />
Unfortunately there are no available tools to generate this value, that I'm aware of. I created a sample application which will generate a valid name constraints value to be set above. The tool can be found at <a href="https://github.com/nmav/nconstraints">this github repository</a>.<br />
<br />
After you compile, run:
<br />
<pre>$ ./nconstraints mydomain.com myotherdomain.com
%30%30%06%03%55%1d%1e%04%29%30%27%a0%25%30%0e%82%0c%6d%79%64%6f%6d%61%69%6e%2e%63%6f%6d%30%13%82%11%6d%79%6f%74%68%65%72%64%6f%6d%61%69%6e%2e%63%6f%6d
</pre>
<br />
and as you see, this command will provide the required string.<br />
<br />
Happy hacking!<br />
<br />
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
</style>
Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com1tag:blogger.com,1999:blog-1625673575821156689.post-80419972281519474982016-05-09T10:34:00.002+02:002016-06-14T19:35:05.304+02:00An overview of the new features in GnuTLS 3.5.0Few minutes ago I've released GnuTLS 3.5.0. This is the stable-next branch of GnuTLS which will replace the stable GnuTLS 3.4.x branch within a year. It is fully backwards compatible and comes with several new features, the most prominent I'll summarize later on this post.<br />
<br />
However, before going on the features let me describe the current trends in the applied cryptography field, to provide an idea of the issues considered during development, and to give context for the included changes. For the really impatient to see the features, jump to last section.<br />
<br />
<h3>
Non-NIST algorithms</h3>
After the <a href="https://en.wikipedia.org/wiki/Dual_EC_DRBG">dual EC-DRBG NIST fiasco,</a> requests to avoid relying blindly on NIST approved/standardized algorithms for the Internet infrastructure, became louder and louder (for the new in the crypto field NIST is USA's National Institute of Standards and Technology). Even though NIST with its standardizations has certainly aided the Internet security technologies, <a href="https://en.wikipedia.org/wiki/Dual_EC_DRBG">the Snowden revelations</a> that NSA via NIST had pushed for the backdoor-able by design EC-DRBG random generator (RNG), and required standard compliant applications to include the backdoor, made a general distrust apparent in organizations like IETF or IRTF. Furthermore, more public scrutiny of NSA's contributions followed. You can see a nice example on <a href="https://projectbullrun.org/dual-ec/ext-rand.html">the reactions</a> to NSA's attempt to <a href="https://tools.ietf.org/html/draft-rescorla-tls-extended-random-02">standardize extensions to the TLS</a> protocol which will expose more state of the generator; an improvement which would have enabled the EC-DRBG backdoor to operate in a more efficient way under TLS.<br />
<br />
Given the above, several proposals were made to no longer rely on NIST's recommendations for elliptic curve cryptography or otherwise. That is, both their elliptic curve parameters as well as their standardized random generators, etc. The first to propose alternative curves to IETF was the German BSI <a href="https://tools.ietf.org/html/rfc5639">which proposed the brainpool curves</a>. Despite their more open design, they didn't receive much attention by implementers. The most current proposal to replace the NIST curves comes from the <a href="https://irtf.org/cfrg">Crypto Forum Research Group (CFRG)</a> and proposes two curves, <a href="https://tools.ietf.org/html/rfc7748">curve25519 and curve448</a>. These, in addition to being not-proposed-by-NIST, can have a very fast implementation in modern systems and can be implemented to operate in constant time, something that is of significant value for digital signatures generated by servers. These curves are being considered for addition in the next iteration of <a href="https://tools.ietf.org/html/draft-ietf-tls-rfc4492bis-07">the TLS elliptic curve document</a> for key exchange, and there is also a proposal to use them <a href="https://tools.ietf.org/html/draft-ietf-curdle-pkix-00">for PKIX/X.509 certificate digital signatures</a> under the EdDSA signature scheme.<br />
<br />
For the non-NIST symmetric cipher replacements the story is a bit different. The NIST-standardized AES algorithm is still believed to be a very strong cipher, and will stay with us for quite long time especially since it is already part of the x86-64 CPU instruction set. However, for CPUs that do not have that instruction set, encryption performance is not particularly impressing. That, when combined with the common in TLS GCM authenticated-encryption construction which cannot be easily optimized without a specific (e.g., PCLMUL) instruction set being present, put certain systems on a disadvantage. Prior to RC4 being known to be completely broken, this was the cipher to switch your TLS connection to, for such systems. However, after <a href="https://tools.ietf.org/html/rfc7465">RC4 became a cipher to display on a museum</a>, a new choice was needed. <a href="http://nmav.gnutls.org/2013/05/salsa20-and-umac-in-tls.html">I have written about the need for it back in 2013</a>, and it seems today we are very close to having <a href="https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305-04">Chacha20 with Poly1305 as authenticator</a> being standardized for use in the TLS protocol. That is an authenticated-encryption construction <a href="https://tools.ietf.org/html/rfc7539">defined in RFC7539</a>, a construction that can outperform both RC4 and AES on hardware without any cipher-specific acceleration.<br />
<br />
<br />
Note that in non-NIST reliance trend, in GnuTLS we attempt to stay neutral and decide our next steps on case by case basis. Not everything coming or being standardized from NIST is bad, and algorithms that are not standardized by NIST do not become automatically more secure. Things like EC-DRBG for example were never part of GnuTLS not because we disliked NIST, but because this design didn't make sense for a random generator at all.<br />
<br />
<h3>
No more CBC</h3>
TLS from <a href="https://tools.ietf.org/html/rfc6101">its first incarnation</a> used a flawed CBC construction which led to several flaws over its years, the most prominent being <a href="http://nmav.gnutls.org/2013/02/time-is-money-for-cbc-ciphersuites.html">the Lucky13 attack</a>. The protocol in its subsequent updates (TLS 1.1 or 1.2) never fixed these flaws, and instead required the implementers to have a constant time TLS CBC pad decoding, a task <a href="https://blog.cloudflare.com/yet-another-padding-oracle-in-openssl-cbc-ciphersuites/">which proved to be notoriously hard</a>, as indicated by the latest OpenSSL issue. While there have been claims that some implementations are better than others, this is not the case here. The simple task of reading the CBC padding bytes, which would have been 2-3 lines of code normally, requires tens of lines of code (if not more), and even more extensive testing for correctness/time invariance. The more code a protocol requires, the more mistakes (remember that better engineers make less mistakes, but they still make mistakes). The protocol is at fault, and the path taken in the next revision of TLS, being 1.3, is to completely drop the CBC mode. In RFC7366 there is a <a href="https://tools.ietf.org/html/rfc7366">proposal to continue using the CBC ciphersuites in a correct way</a> which would pose no future issues, but the TLS 1.3 revision team though it is better to move away completely from something that has caused so many issues historically.<br />
<br />
In addition to that, it seems that all the CBC ciphersuites were <a href="https://tools.ietf.org/html/rfc7540">banned from being used under HTTP/2.0</a> even when used under TLS 1.2. That would mean that applications talking HTTP/2.0 would have to disable such ciphersuites or they may fail to interoperate. This move effectively obsoletes the RFC7366 fix for CBC (already implemented in GnuTLS).<br />
<br />
<br />
Cryptographically-speaking the CBC mode is a perfectly valid mode when used as prescribed. Unfortunately when TLS 1.0 was being designed, the prescription was not widely available or known, and as such it got into to protocol following the "wrong" prescription. As it is now and with all the bad PR around it, it seems we are going to say goodbye to it quite soon.<br />
<br />
For the emotionally tied with CBC mode like me (after all it's a nice mode to implement), I'd like to note that it will still live with us <a href="https://tools.ietf.org/html/rfc6655">under the CCM ciphersuites</a> but on a different role. It now serves as a MAC algorithm. For the non-crypto geeks, CCM is an authenticated encryption mode using counter mode for encryption and CBC-MAC for authentication; it is widely used in the IoT, an acronym for the 'Internet of Things' buzzwords, which typically refers to small embedded devices.<br />
<br />
<br />
<br />
<br />
<h3>
Latency reduction</h3>
<br />
One of the <a href="https://datatracker.ietf.org/wg/tls/charter/">TLS 1.3 design goals</a>, according to its charter, is to "<i>reduce handshake latency, ..., aiming for one roundtrip </i><i>for a full handshake and one or zero roundtrip for repeated handshakes". </i>That effort was initiated and tested widely by Google and the <a href="https://tools.ietf.org/html/draft-ietf-tls-falsestart-01">TLS false start</a> protocol, which reduced the handshake latency to a single roundtrip, and further demonstrated its benefits <a href="https://en.wikipedia.org/wiki/QUIC">with the QUIC protocol</a>. The latter is an attempt to provide multiple connections over a stream into userspace, avoiding any kernel interaction for de-multiplexing or congestion avoidance into user-space. It comes with its own <a href="https://docs.google.com/document/d/1g5nIXAIkN_Y-7XJW5K45IblHd_L2f5LTaDUDwvZ5L6g/edit">secure communications protocol</a>, which integrates security into the transport layer, as opposed to running a generic secure communications protocol over a transport layer. That's a certainly interesting approach and it remains to be seen whether we will be hearing more of it.<br />
<br />
While I was initially a skeptic for modifications to existing cryptographic protocols to achieve low latency, after all such modifications reduce the security guarantees (<a href="https://securewww.esat.kuleuven.be/cosic/publications/article-2216.pdf">see this paper for a theoretical attack which can benefit from false-start</a>), the requirement for secure communications with low latency is there to stay. Even though the strive to reduce latency for HTTP communication may not be convincing for everyone, one cannot but imagine a future where high latency scenarios <a href="http://ipnsig.org/">like this</a> are the norm, and low-roundtrip secure communications protocols are required.<br />
<br />
<h3>
Post-quantum cryptography</h3>
Since several years it is <a href="https://en.wikipedia.org/wiki/Shor's_algorithm">known that a potential quantum computer can break cryptographic algorithms</a> like RSA or Diffie Hellman as well as the elliptic curve cryptosystems. It was unknown whether a quantum computer at the size where it could break existing cryptosystems could ever exist, however research conducted the last few years provides indications that this is a possibility. NIST hosted a conference on the topic last year, where <a href="https://www.schneier.com/blog/archives/2015/08/nsa_plans_for_a.html">NSA expressed their plan to prepare for a post-quantum computer future</a>. That is, they no longer believe that elliptic curve cryptography, i.e., their SuiteB profile, is a solution which will be applicable long-term. That is, because due to their use of short keys, the elliptic curve algorithms require a smaller quantum computer to be broken, rather than their finite field counterparts (RSA and Diffie-Hellman). Ironically, it is easier to protect the classical finite field algorithms from quantum computers by increasing the key size (e.g., to 8k or 16k keys) than their more modern counterparts based on elliptic curves.<br />
<br />
Other than the approach of increasing the key sizes, today we don't have much tools (i.e., algorithms) to protect key exchanges or digital signatures against a quantum computer future. By the time a quantum computer of <strike>256-qubits or larger</strike> roughly 384 qubits is available all today's communication which is based on elliptic curves will be potentially be made available to the owner of such a system. Note, that this future is not expected soon; however, no-one would dare to make a prediction for that. Note also, that the existing systems of D-WAVE are <a href="https://en.wikipedia.org/wiki/Shor's_algorithm">not known to be capable of breaking the current cryptosystems</a>.<br />
<br />
Neither IETF or any other standardizing body has any out of the box solution. The most recent development is <a href="http://csrc.nist.gov/groups/ST/post-quantum-crypto/documents/pqcrypto-2016-presentation.pdf">a NIST competition for quantum computer resistant algorithms</a>, which is certainly a good starting point. It is also a challenge for NIST as it will have to overcome the bad publicity due to the EC-DRBG issue and reclaim its position in technology standardization and driver. Whether they will be successful on that goal, or whether we are going to have new quantum-computer resistant algorithms at all, it remains to be seen.<br />
<br />
<br />
<br />
<h3>
Finally: the GnuTLS 3.5.0 new features</h3>
<h3>
</h3>
<span style="font-weight: normal;">In case you managed to read all of the above, only few paragraphs are left. Let me summarize the list of prominent changes.</span><br />
<br />
<ul>
<li><b>SHA3 as a certificate signature algorithm.</b> The SHA3 algorithm on all its variations (256-512) was standardized by FIPS 202 publication in August 2015. However, until very recently there were no code points (or more specifically object identifiers) for using it on certificates. <a href="http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html">Now that they are finally available</a>, we have modified GnuTLS to include support for generating, and verifying certificates with SHA3. For SHA3 support in the TLS protocol either as a signature algorithm or a MAC algorithm we will have to wait further for code points and ciphersuites being available and standardized. Note also, that since GnuTLS 3.5.0 is the first implementation supporting SHA3 on PKIX certificates there have not been any interoperability tests with the generated certificates.</li>
<li><b>X25519 (formerly curve25519) for ephemeral EC diffie-hellman key exchange. </b>One quite long-time expected feature we wanted to introduce in GnuTLS is <a href="https://gitlab.com/gnutls/gnutls/issues/20">support for alternative to the standardized by NIST</a> elliptic curves. We selected curve25519 originally described in <a href="https://tools.ietf.org/html/draft-ietf-tls-curve25519-01">draft-ietf-tls-curve25519-01</a> and currently in the document which revises the elliptic curve support in TLS <a href="https://tools.ietf.org/html/draft-ietf-tls-rfc4492bis-07">draft-ietf-tls-rfc4492bis-07</a>. The latter document --which most likely means the curve will be widely implemented in TLS-- and the advantages of X25519 in terms of performance are the main reasons of selecting it. Note however, that X25519 is a peculiar curve for implementations designed around the NIST curves. That curve cannot be used with ECDSA signatures, although it can be used with a similar algorithm called EdDSA. We don't include EdDSA support for certificates or for the TLS protocol in GnuTLS 3.5.0 as <a href="https://tools.ietf.org/html/draft-ietf-curdle-pkix-00">the specification for it</a> has not settled down. We plan to include it in a later 3.5.x release. For curve448 we would have to wait until its <a href="https://tools.ietf.org/html/draft-irtf-cfrg-eddsa-05">specification for digital signatures is settled</a> and is available in the nettle crypto library.</li>
<li><b>TLS false start.</b> The TLS 1.2 protocol as well as its earlier versions required a full round-trip time of 2 for its handshake process. Several applications require reduced latency on the first packet and so the <a href="https://tools.ietf.org/html/draft-ietf-tls-falsestart-01">False start modification of TLS was defined</a>. The modification allows the client to start transmitting at the time the encryption keys are known to him, but prior to verifying the keys with the server. That reduces the protocol to a single round-trip at the cost of putting the initially transmitted messages of the client at risk. The risk is that any modification of the handshake process by an active attacker will not be detected by the client, something that can lead the client to negotiate weaker security parameters than expected, and so lead to a possible decryption of the initial messages. To prevent that GnuTLS 3.5.0 will not enable false start even if requested when it detects a weak ciphersuite or weak Diffie-Hellman parameters. The false start functionality can be requested by applications using a flag to gnutls_init().</li>
<li><b>New APIs to access the Shawe-Taylor-based provable RSA and DSA parameter generation.</b> While enhancing GnuTLS 3.3.x for Red Hat in order to pass the FIPS140-2 certification, we introduced provable RSA and DSA key generation based on the Shawe-Taylor algorithm, following the FIPS 186-4 recommendations. That algorithm allows generating parameters for the RSA and DSA algorithms from a seed that are provably prime (i.e., no probabilistic primality tests are included). In practice this allows an auditor to verify that the keys and any parameters (e.g., DH) present on a system are generated using a predefined and repeatable process. This code was enabled only when GnuTLS was compiled to enable FIPS140-2 mode, and when the system was put in FIPS140-2 compliance mode. In GnuTLS 3.5.0 this functionality is made available unconditionally from the <i>certtool</i> utility, and a key or DH parameters will be generated using these algorithms when the --provable parameter is specified. That required to modify the storage format for RSA and DSA keys to include the seed, and thus for compatibility purposes this tool will output both old and new formats to allow the use of these parameters from earlier GnuTLS versions and other software.</li>
<li><b>Prevent the change of identity on rehandshakes by default.</b> The TLS rehandshake protocol is typically used for three reasons, (a) rekey on long standing connections, (b) re-authentication and (c) connection upgrade. The rekey use-case is self-explanatory so my focus will be on the latter two. Connection upgrade is when connecting with no client authentication and rehandshaking to provide a client certificate, while re-authentication is when connecting with an identity A, and switching to identity B mid-connection. With that change in GnuTLS the latter use case (re-authentication) is prohibited unless the application has explicitly requested it. The reason is that the majority of applications using GnuTLS are not prepared to handle a connection identity change in the middle of a connection something that depending on the application protocol may lead to issues. Imagine the case where a client authenticates to access a resource, but just before accessing it, the client switches to another identity by presenting another certificate. It is unknown whether applications using GnuTLS are prepared for such changes, and thus we considered important to protect applications by default by requiring applications that utilize re-authentication to explicitly specify it via a flag to gnutls_init(). This change does not affect applications using rehandshake for rekey or connection upgrade.</li>
</ul>
<br />
That concludes my list of the most notable changes, even though this release includes <a href="https://gitlab.com/gnutls/gnutls/blob/5e9cbaedbe157ba66801cf06b8730c69acb5a815/NEWS">several other ones</a>, including a stricter protocol adherence in corner cases and a significant enhancement of the included test suite. Even though I am the primary contributor, this is a release containing code contributed by more than 20 people which I'd like to personally thank for their contributions.<br />
<br />
If you are interested in following our development or helping out, I invite you on our mailing list as well as to <a href="https://gitlab.com/gnutls/gnutls">our gitlab pages</a>.<br />
<br />
<br />
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
</style>
Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com0tag:blogger.com,1999:blog-1625673575821156689.post-76446949618330995312016-02-08T20:45:00.002+01:002017-01-12T16:10:55.866+01:00Why do we need SSL VPNs today?One question that has been bothering me for quite a while, is why do we need SSL VPNs? There is an IETF standardized VPN type, IPSec, and given that, why do SSL VPNs still get deployed? Why not just switch everything to IPSec? Moreover, another important question is, since we have IPSec since around 1998, why IPSec hasn't took over the whole market of VPNs? <i>Note that, I'll be using the term SSL even though today it has been replaced by Transport Layer Security (TLS) because the former is widely used to describe this type of VPNs.</i><br />
<br />
These are valid questions, but depending on who you ask you are very likely to get a different answer. I'll try to answer from an SSL VPN developer standpoint.<br />
<br />
<br />
In the VPN world there are two main types of deployment, the <b>'site-to-site'</b> and the <b>'remote access'</b> types. To put it simply, the first is about securing lines between two offices, and the latter is about securing the connection between your remote users and the office. The former type may rely on some minimal PKI deployment or pre-shared keys, but the latter requires integration with some user database, credentials, as well as settings which may be applied individually for each user. In addition the 'remote access' type is often associated with accounting such as keeping track how long a user is connected, how much data has been transferred and so on. That may remind you the kind of accounting used in ppp and dial-up connections, and indeed the same radius-based accounting methods are being used for that purpose.<br />
<br />
Both of the 'site-to-site' and 'remote access' setups can be handled by either SSL or IPSec VPNs. However, there are some facts that make some VPNs more suitable for one purpose than the other. In particular, it is believed that SSL VPNs are more suitable for the 'remote access' type of VPNs, while IPSec is unquestionably the solution one would deploy on site-to-site connections. In the next paragraphs I focus on the SSL VPNs and try to list their competitive advantage for the purpose of 'remote access'. <br />
<ol>
<li><b>Application level.</b> In SSL VPNs the software is at the application level, and that means that it can provided by the software distributor, or even by the administrator of the server. These VPN applications can be customized for the particular service the user connects to (e.g., include logos, or adjust to the environment the user is used to, or even integrate VPN connectivity with an application). For example the <a href="https://12vpn.net/downloads/openconnect-windows/">12vpn.net VPN provider</a> customizes the <a href="https://github.com/openconnect/openconnect-gui/wiki">openconnect-gui</a> application (which is free software) to provide it with a pre-loaded list of the servers they offer to their customers. Several other proprietary solutions use a similar practice, and the server provides the software for the end users.</li>
<li><b>Custom interfaces for authentication.</b> The fact that (most) SSL VPNs run over HTTPS, it provides them with an inherent feature of having complete control over the authentication interface they can display to users. For example in <a href="https://github.com/openconnect/protocol/blob/master/draft-openconnect-01.txt#L177">Openconnect VPN</a> we provide the client with XML forms that the user is presented and must fill in, in order to authenticate. That usually covers typical password authentication, one time passwords, group selections, and so on. Other SSL VPN solutions use entirely free form HTML authentication and often only require a browser to log to the network. Others integrate certificate issuing on the first user connection <a href="https://tools.ietf.org/html/draft-gutmann-scep-01">using SCEP</a>, and so on. </li>
<li><b>Enforcing a security policy.</b> Another reason (which I don't quite like or endorse - but happens quite
often) is that the VPN client applications, enforce a particular
company-wide security policy; e.g., ensure that anti-virus software is
running and up to date, prior to connecting to the company LAN. This often is implemented with server provided executables being run by the clients, but that is also a double-edged sword as a VPN server compromise will allow for a compromise of <i>all</i> the clients. In fact the bypass of this "feature" was one of the driving reasons behind <a href="http://www.infradead.org/openconnect/">the openconnect client</a>.</li>
<li><b>Server side user restrictions.</b> On the server-side the available freedom is comparable with the client side. Because SSL VPNs are on the application layer protocol, they are more flexible in what
the connecting client can be restricted to. For example, in openconnect VPN server
invidual users, or groups of them can be set into a specific kernel
cgroup, i.e., limiting their available CPU time, or can be restricted
to a fixed bandwidth in a much more easy way than in any IPSec server.</li>
<li><b>Reliability, i.e., operation over any network.</b> In my opinion, the major reason of existance of SSL VPN
applications and servers is that they can operate under any environment.
You can be restricted by firewalls, broken networks which block ESP or
UDP packets and still be able to connect to your network. That is, because the HTTPS
protocol which they rely on, cannot be blocked without having a major part of the Internet go down.
That's not something to overlook; a VPN service which works most of
the times but not always because the user is within some misconfigured
network is unreliable. Reliability is something you need when you want
to communicate with colleagues when being on the field, and that's the <u>real problem</u> SSL VPN solve (and the main reason companies and IT administrators usually pay extra to have these features enabled). Furthermore, solutions like Openconnect VPN utilize a combination of HTTPS (TCP) and UDP when available to provide the best possible user experience. It utilizes Datagram TLS over UDP when it detects that this is allowed by network policy (and thus avoiding the TCP over TCP tunneling issues), and falls back to tunneling over HTTPS when the establishment of the DTLS channel is not possible.</li>
</ol>
<br />
That doesn't of course mean that IPSec VPNs are obsolete or not needed for remote access. We are far from that. IPSec VPNs are very well suited for site-to-site links --which are typically on networks under the full control of the deployer-- and are cross platform (if we ignore the IKEv1 vs IKEv2 issues), in the sense that you are very likely to find native servers and clients offered by the operating system. In addition, they possess a significant advantage; because they are integrated with the operating system's IP stack, they utilize the kernel for encryption which removes the need for userspace to kernel space switches. That allows them to serve high bandwidths and spend less CPU time. A kernel side TLS stack, would of course provide SSL VPNs a similar advantage but currently that is <a href="https://patchwork.ozlabs.org/patch/547695/">work in progress</a>.<br />
<br />
As a bottom line, you should chose the best tool for the job at hand based on your requirements and network limitations. I made the case for SSL VPNs, and provided the reasons of why I believe they are still widely deployed and why they'll continue to. If I have already convinced you for the need for SSL VPNs, and you are an administrator working with VPN deployments I'd like to refer you to my <a href="https://fosdem.org/2016/schedule/event/openconnect/">FOSDEM 2016 talk</a> about the OpenConnect (SSL) VPN server, on which I describe the reasons I believe it provides a significant advantage over any existing solutions in Linux systems.<br />
<br />
<br />
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
</style>
Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com0tag:blogger.com,1999:blog-1625673575821156689.post-42279579631697581462015-11-23T19:21:00.001+01:002015-11-23T19:23:00.454+01:00An overview of GnuTLS 3.4.xThis April GnuTLS 3.4.0 was released, as our stable-next branch, i.e., the branch to replace the current stable branch of GnuTLS (which as of today is the 3.3.x branch). During that time, we also moved our development infrastructure from gitorious to <a href="http://gitlab.com/gnutls/gnutls">gitlab.com</a>, a move that has improved the project management significantly. We now have automated builds (on servers running on an Openstack system supplied by Red Hat), continuous integration results integrated to the development pages, as well as simple to use milestone and issue trackers. For a project which as it stands is mostly managed by me, that move was godsend, as we can have several new development and management features with considerable less effort. That move unfortunately <a href="http://permalink.gmane.org/gmane.comp.encryption.gpg.gnutls.devel/8050">was not without opposition</a>, but at the end a decision had to be taken, which is driven by pragmatism.<br />
<br />
Assessing the last 12 months we had quite a productive year. <a href="https://www.openhub.net/p/gnutls/contributors?sort=latest_commit&time_span=12+months">Several people offered fixes</a> and enhancements, and I still remain the main contributor -though I would really like for that to change.<br />
<br />
Anyway, let me get to the overview of the GnuTLS 3.4.x feature set. For its development we started with a basic plan describing the desired features (it still be seen <a href="https://gitlab.com/gnutls/gnutls/wikis/Plan3_4">at this wiki page</a>), and we also allowed for features which did not threaten backwards compatibility to be included during in the first releases. These were tracked using the <a href="https://gitlab.com/gnutls/gnutls/milestones/2">milestone tracker</a>.<br />
<br />
As we are very close to tag the current release as stable, I'll attempt to summarize the new features and enhancements in the following paragraphs, and describe our vision for the future of the library.<br />
<ul>
<li><b> New features:</b></li>
<ul>
<li><b>Added a new and simple API for authenticated encryption. </b>The new API description can be seen <a href="http://www.gnutls.org/manual/html_node/Symmetric-algorithms.html#Symmetric-algorithms">in the manual</a>. The idea behind that change was to make programming errors in encryption / decryption routine usage as difficult as possible. That was done by combining encryption and tagging, as well as decryption and verification of the tag (MAC). That is of course taking advantage of the AEAD cipher constructions and currently can be used by the following AEAD ciphers: AES-GCM, AES-CCM, CAMELLIA-GCM, and CHACHA20-POLY1305.</li>
<li><b>Simplified the verification API.</b> One of the most common complains on TLS library APIs is their involved complexity to perform a simple connection. To our defense part of that complexity is due to specifications like PKIX which forwards the security decisions to application code, but partly also because the APIs provided are simply too complicated. In that particular case we needed to get rid the need for elaborate callbacks to perform certificate verification checks, and include the certificate verification in the handshake process. That means, to move the key purpose, and hostname verification to the handshake process. For that we simplified the current API by introducing gnutls_session_set_verify_cert() and gnutls_session_set_verify_cert2(), when a key purpose is required. The call of the former function instructs GnuTLS to verify the peer's certificate hostname as part of the handshake, hence eliminating the need for callbacks. An example of a session setup with the new API can be <a href="http://www.gnutls.org/manual/html_node/Simple-client-example-with-X_002e509-certificate-support.html#Simple-client-example-with-X_002e509-certificate-support">seen in the manual</a>. If we compare the old method and the new, we can see that it reduces the minimum client size by roughly 50 lines of code.</li>
<li><b>Added an API to access system keys.</b> Several operating systems provide a system key store where private keys and certificates may be present. The idea of this feature was to make these keys readily accessible to GnuTLS applications, by using a URL as a key identifiers (something like system:uuid=xxx). Currently we support the windows key store. More information can be seen at <a href="http://www.gnutls.org/manual/html_node/Application_002dspecific-keys.html#System_002dspecific-keys">the system keys manual section</a>.</li>
<li><b>Added an API for PKCS #7 structure generation and signing. </b>Given that PKCS #7 <a href="http://article.gmane.org/gmane.linux.kernel/2013347">seems to be the format of choice for signing kernel modules</a> and firmware it was deemed important to provide such an API. It is currently described in <a href="https://gitlab.com/gnutls/gnutls/blob/master/lib/includes/gnutls/pkcs7.h">gnutls/pkcs7.h</a> and can be seen in action in the <a href="https://gitlab.com/nmav/modsign">modsign tool</a>.</li>
<li><b>Added transparent support for internationalized DNS names.</b> Internationalized DNS names require some canonicalization prior to being compared or used. Previous versions of GnuTLS didn't support that, disallowing the comparison of such names, but this is the first version which adds support for the <a href="https://tools.ietf.org/html/rfc6125#section-6.4.2" rel="nofollow">RFC6125 recommendations</a>.</li>
</ul>
<li><b> TLS protocol updates:</b></li>
<ul>
<li><b>Added new AEAD cipher suites.</b> There are new ciphersuites being defined for the TLS protocol, some for the <a href="https://tools.ietf.org/html/rfc6655">Internet of Things profile</a> of TLS, and some which involve <a href="https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305-02">stream ciphers like Chacha20</a>. This version of TLS adds support for both of these ciphersuites, i.e., AES-CCM, AES-CCM-8, and CHACHA20-POLY1305.</li>
<li><b>Added support for Encrypt-then-authenticate mode for CBC.</b> During the last decade we have seen several attacks on the CBC mode, as used by the TLS ciphersuites. Each time there were mitigations for the issues at hand, but there was never a proper fix. This version of GnuTLS implements the "proper" fix as defined in <a href="https://tools.ietf.org/html/rfc7366">rfc7366</a>. That fix extends the lifetime of the CBC ciphersuites.</li>
<li><b>Included Fix for the triple-handshake attack. </b>An other attack on the TLS protocol which required a protocol fix is the triple handshake attack. This attack took advantage of clients not verifying the validity of the peer's certificate on a renegotiation. This release of GnuTLS implements the protocol fix which ensures that the applications which rely on renegotiation are not vulnerable to the attack.</li>
<li><b>Introduced support for fallback SCSV.</b> That is provide the signaling mechanism from <a href="https://tools.ietf.org/html/rfc7507">RFC7507</a> so that applications which are forced to use insecure negotiation can reasonably prevent downgrade attacks.</li>
<li><b>Disabled SSL 3.0 and RC4 in default settings. </b>Given the recent status on attacks on both the SSL 3.0 protocol, and the RC4 cipher, it was made apparent that these no longer are a reasonable choice for the default protocol and ciphersuite set. As such they have been disabled.</li>
</ul>
</ul>
<br />
That list summarizes the major enhancements in the 3.4.x branch. As you can see our focus was not to only add new security related features, but to also simplify the usage of the currently present features. The latter is very important, as we see in practice that TLS and its related technologies (like PKIX) are hard to use even by experts. That is partially due to the complexity of the protocols involved (like PKIX), but also due to very flexible APIs which strive to handle 99% of the possible options allowed by the protocols, ignoring the fact that 99% of the use cases found in the Internet utilize a single protocol option. That was our main mistake with the verification API, and I believe with the changes in 3.4.x we have finally addressed it.<br />
<br />
Furthermore, a long time concern of mine was that the stated protocol complexity for PKIX and TLS, translates to tens of thousands lines of code, hence to a considerable probability for the presence of a software error. We strive to reduce that probability, for example by using fuzzying or static analyzers like coverity and clang, and audit, but it cannot be eliminated. No matter how low the probability of an error per line of code is, it will become certainty in large code bases. Thus my recommendation for software which can trade performance for security, would be to consider designs where the TLS and PKIX protocols are confined in sandboxed environments like <a href="https://en.wikipedia.org/wiki/Seccomp">seccomp</a>. We have tested such a design on the <a href="http://www.infradead.org/ocserv/">openconnect VPN server project</a> and we have noticed no considerable obstacles or significant performance reduction. The main requirement in such an environment is IPC, and being able to pack structures in an efficient way (i.e., check protocol-buffers). For such environments, we have added a short <a href="http://www.gnutls.org/manual/html_node/Running-in-a-sandbox.html#Running-in-a-sandbox">text in our manual</a> describing the system calls used by GnuTLS, to assist with setting up filters, and we welcome comments for improving that text or the approach.<br />
<br />
In addition, to allow applications to offer, a multi-layer security, involving private key isolation, we continue to enhance, the strong point of GnuTLS 3.3.x. That is, the transparent support for PKCS #11. Whilst sometimes it overlooked as a security feature, PKCS #11 can provide an additional layer of security by allowing to separate private keys from the applications using them. When GnuTLS is combined with a Hardware Security Module (HSM), or a software security module like <a href="https://github.com/ANSSI-FR/caml-crush">caml-crush</a>, it will prevent the leak of the server's private key even if the presence of a catastrophic attack which reveals the server's memory (e.g., an attack like heartbleed).<br />
<br />
Hence, a summary of our vision for the future, would be to be able to operate under and contribute to multi-layer security designs. That is, designs where the TLS library isn't the Maginot line, after which there is no defense, but rather where the TLS library is considered to be one of the many defense layers.<br />
<br />
So, overall, with this release we add new features to simplify the library, modernize its protocol support but also enhance GnuTLS in a way to be useful in security designs where multiple layers of protection are implemented (seccomp, key isolation via PKCS #11). If that is something that you are interested at, we welcome you to join our <a href="https://lists.gnupg.org/mailman/listinfo/gnutls-devel">development mailing list</a>, visit our <a href="https://gitlab.com/gnutls/gnutls">development pages at gitlab</a>, and help us make GnuTLS better. <br />
<br />
<br />
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
</style>
Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com0tag:blogger.com,1999:blog-1625673575821156689.post-14835803122041963482015-06-15T15:49:00.000+02:002015-06-16T08:15:49.833+02:00Software Isolation in LinuxStarting from the assumption that software will always have bugs, we
need a way to isolate and neutralize the effects of the bugs. One
approach is by isolating components of the software such that a breach
in one component doesn't compromise another. That, in the software engineering field became popular with the principle of privilege separation used by the openssh server, and is the application of an old idea to a new field. Isolation for protection of assets is widespread in several other aspects of human activity; the most
prominent example throughout history is the process of quarantine which
isolates suspected carriers of epidemic diseases to protect the rest of
the population. In this post, we briefly overview the tools available in
the Linux kernel to offer isolation between software components. It is based on my FOSDEM 2015 <a href="https://github.com/security-devroom/fosdem-2015/tree/master/presentations/software-isolation-in-linux">presentation on software isolation</a> in security devroom, slightly enhanced.<br />
<br />
Note that this text is intended to developers and software engineers looking for methods to isolate components in their software. <br />
<br />
An
important aspect of such an analysis is to clarify the threats that it targets. In
this text I describe methods which protect against code injection attacks. Code injection provides the attacker a very strong tool to execute code, read arbitrary
memory, etc.<br />
<br />
In a typical Linux kernel based system, the available tools we can use for such protection, are the following.<br />
<ol>
<li>fork() + setuid() + exec()</li>
<li>chroot()</li>
<li>seccomp()</li>
<li>prctl()</li>
<li>SELinux</li>
<li>Namespaces</li>
</ol>
<br />
The first allows for memory isolation by
using different processes, ensuring that a forked process has no access
to parent's memory address space. The second allows a process to
restrict itself in a part of the file system available in the operating system. These two are available in almost all
POSIX systems, and are the oldest tools available dating to the first
UNIX releases. The focus of this post are the methods 3-6 which are
fairly recent and Linux kernel specific.<br />
<br />
Before proceeding, let's make a
brief overview of what is a process in an UNIX-like operating system. It is some code in memory which is scheduled to have a time slot in the CPU.
It can access the virtual memory assigned to it, make calculations using
the CPU user-mode instructions, and that's pretty
much all. To access anything else, e.g., get additional memory, access
files, read/write the memory of other processes, system calls from the
operating system have to be used.<br />
<br />
Let's now proceed and describe the available isolation methods.<br />
<br />
<h3>
Seccomp</h3>
After that introduction to processes, seccomp comes as
the natural method to list, since it is essentially a filter for the system
calls available in a process. For example, a process can install a filter
to allow read() and write() but nothing else. After such a filter applied, any code which is potentially injected to that process will not be able to execute any other
system calls, reducing the attack impact to the allowed calls. In our particular example with read() and write() only the data written and read by that process will be affected.<br />
<br />
The simplest way to access seccomp is via the <a href="https://github.com/seccomp/libseccomp">libseccomp library</a> which has a quite intuitive API. An example using that library, which creates a whitelist of three system calls is shown below.<br />
<br />
<pre><span style="font-size: x-small;">
#include <seccomp.h>
scmp_filter_ctx ctx;
ctx = seccomp_init(SCMP_ACT_ERRNO(EPERM))
assert(ctx == 0);
assert(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0) == 0);
assert(seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0) == 0);
assert (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, SCMP_A1(SCMP_CMP_EQ, (int)SIOCGIFMTU)) == 0);
assert (seccomp_load(ctx) == 0);</span></pre>
<br />
The example above installs a filter which allows the read(), write() and ioctl() system calls. The latter is only allowed if the second argument of ioctl() is SIOCGIFMTU. The first line of filter setup, instructs seccomp to return -1 and set errno to EPERM when an instruction outside this filter is called.<br />
<br />
The drawback of seccomp is the tedious process which
a developer has to go in order to figure out the used system calls in
his application. Manual inspection of the code is required to
discover the system calls, as well as inspection of run traces using the
'strace' tool. Manual inspection will allow a making a rough list which
will provide a starting point, but will not be entirely accurate. The issue is that calls
to libc functions may not correspond to the expected system call. For example, a call exit() often results to an exit_group() system call.<br />
<br />
The
trace obtained using 'strace' will help clarify, restrict or extend
the initial list. Note however, that using traces alone may prevent
getting the system calls used in error condition handling, and different
versions of libc may use different system calls for the same function.
For example, the libc call select() uses the system call select() in
x86-64 architecture, but the _newselect() in the x86. <br />
<br />
<pre></pre>
The performance cost of seccomp is the cost of executing the filter, and for most cases it is a fixed cost per system call. In the openconnect VPN server I estimated the impact of seccomp on a worker process to 2% slowdown in transfer speed (from 624 to 607Mbps). The measured server worker process is executing read/send and recv/write in a tight loop.<br />
<br />
<h3>
Prctl</h3>
The PR_SET_DUMPABLE flag of the prctl() system call
protects a process from other processes accessing its memory. That is, it
will prevent processes with the same privilege as the protected to read its memory it via ptrace(). A usage example is shown below.<br />
<br />
<pre><span style="font-size: x-small;"> #include <prctl.h>
prctl(PR_SET_DUMPABLE, 0);</span>
</pre>
<br />
While this approach doesn't protect against
code injection in general, it may prove a useful tool with low-performance cost in
several setups.<br />
<br />
<h3>
SELinux</h3>
SELinux is an operating system mechanism to prevent processes
from accessing various "objects" of the OS. The objects
can be files, other processes, pipes, network interfaces etc. It may be
used to enhance seccomp using more fine-grained access control. For
example one may setup a rule with seccomp to only allow read(), and
enhance the rule with SELinux for read() to only accept certain file
descriptors.<br />
<br />
On the other hand, a software engineer may not
be able to rely too much on SELinux to provide isolation, because it
is often not within the developer's control. It is typically used as an administrative tool, and the administrator may decide to
turn it off, set it to non-enforcing mode, etc. <br />
<br />
The way for a process to transition to a different SELinux ruleset is via exec() or via the setcon() call, and its cost is perceived to be high. However, I have no performance tests with software relying on it.<br />
<br />
The drawbacks of this approach are the centralized nature of the system policy, meaning that individual applications can only apply the existing system policy, not update it, the obscure language (m4) a system policy needs to be written at, and the fact that any policy written will not be portable across different Linux based systems.<br />
<h3>
Linux Namespaces</h3>
One of the most recent additions to the Linux
kernel are the Namespaces feature. These allow "virtualizing" certain
Linux kernel subsystems in processes, and the result is often referred to as containers. It is available via the clone()
and unshare() system calls. It is documented in the unshare(2) and clone(2) man pages, but let's see some examples of the subsystems
they can be restricted.<br />
<br />
<ul>
<li>NEWPID: Prevents processes to "see" and access process IDs (PIDs)
outside their namespace. That is the first isolated process will believe
it has PID 1 and see only the processes it has forked.</li>
<li>NEWIPC: Prevents processes to access the main IPC subsystem (shared
memory segments, messages queues etc.). The processes will have access
to their own IPC subsystem.</li>
<li>NEWNS: Provides filesystem isolation, in a way as a feature rich
chroot(). It allows for example to create isolated mount points which
exist only within a process.</li>
<li>NEWNET: Isolates processes from the main network subsystem. That is
it provides them with a separate networking stack, device interfaces,
routing tables etc.</li>
</ul>
Let's see an example of an isolated process being created on its own PID namespace. The following code operates as fork() would do.<br />
<br />
<pre><span style="font-size: x-small;"> #if defined(__i386__) || defined(__arm__) || defined(__x86_64__) || defined(__mips__)
long ret;
int flags = SIGCHLD|CLONE_NEWPID;
ret = syscall(SYS_clone, flags, 0, 0, 0);
if (ret == 0 && syscall(SYS_getpid) != 1)
return -1;
return ret;
#endif</span>
</pre>
<br />
This approach, of course has a performance penalty in the
time needed to create a new process. In my experiments with openconnect
VPN server the time to create a process with NEWPID, NEWNET and NEWIPC
flags increased the process creation time to 10 times more than a call to fork().<br />
<br />
Note however,
that the isolation subsystems available in clone() are by default reversible using the setns() system call. To ensure that these
subsystems remain isolated even after code injection seccomp must be
used to eliminate calls setns() (many thanks to the FOSDEM participant who
brought that to my attention).<br />
<br />
Furthermore, the approach
of Namespaces follows the principle of blacklisting, allowing a developer to isolate
from certain subsystems but not from every one available in the system. That is, one may
enable all the isolation subsystems available in the clone() call, but
then he may realize that the kernel <a href="http://www.projectatomic.io/blog/2014/09/yet-another-reason-containers-don-t-contain-kernel-keyrings/">keyring is still available to the isolated process</a>. That is because there is no implementation of such an
isolation mechanism for the kernel keyring so far.<br />
<br />
<h3>
Conclusions</h3>
<br />
In the following table I attempt to summarize the protection offerings of each of the described methods. <br />
<br />
<table class="tg">
<tbody>
<tr>
<th class="tg-031e"><br /></th>
<th class="tg-031e">Prevent killing<br />
other processes</th>
<th class="tg-031e">Prevent access to memory<br />
of other processes</th>
<th class="tg-031e">Prevent access to <br />
shared memory</th>
<th class="tg-031e">Prevent exploitation<br />
of an unused system call bug</th>
</tr>
<tr>
<td class="tg-031e">Seccomp</td>
<td class="tg-031e">True</td>
<td class="tg-031e">True</td>
<td class="tg-031e">True</td>
<td class="tg-031e">True</td>
</tr>
<tr>
<td class="tg-031e">prctl(SET_DUMPABLE)</td>
<td class="tg-031e">False</td>
<td class="tg-031e">True</td>
<td class="tg-031e">False</td>
<td class="tg-031e">False</td>
</tr>
<tr>
<td class="tg-031e">SELinux</td>
<td class="tg-031e">True</td>
<td class="tg-031e">True</td>
<td class="tg-031e">True</td>
<td class="tg-031e">False</td>
</tr>
<tr>
<td class="tg-031e">Namespaces</td>
<td class="tg-031e">True</td>
<td class="tg-031e">True</td>
<td class="tg-031e">True</td>
<td class="tg-031e">False</td>
</tr>
</tbody></table>
<br />
In my opinion, seccomp seems to be the best option to consider as an isolation mechanism when designing new software. Together with Linux Namespaces it can prevent access to other processes, shared memory and filesystem, but the main distinguisher I see, is the fact that it can restrict access to unused system calls.<br />
<br />
That is an important point, given the number of available system calls in a modern kernel. It is not only that it reduces the overall attack surface by limiting them, but it will also deny access to functionality that was not intended to --see setns() and the kernel keyring issue above.<br />
<br />
<style type="text/css">
.tg {border-collapse:collapse;border-spacing:0;}
.tg td{font-family:Arial, sans-serif;font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
.tg th{font-family:Arial, sans-serif;font-size:14px;font-weight:normal;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
</style>
Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com2tag:blogger.com,1999:blog-1625673575821156689.post-70385755242656549852014-12-03T16:21:00.000+01:002014-12-03T16:21:36.262+01:00A quick overview of GnuTLS development in 20142014 was a very interesting year in the development of GnuTLS. On the development side, this year we have incorporated patches with fixes or enhanced functionality from more than <a href="https://www.openhub.net/p/gnutls/contributors?query=&sort=commits_12_mo">25 people</a> according to openhub, and the main focus was moving GnuTLS 3.3.x from next to a stable release. That version had quite a number of new features, the most prominent being:<br />
<ul>
<li>Initialization on a library constructor,</li>
<li>The introduction of verification profiles, i.e., enforce rules not only on the session parameters such as ciphersuites and protocol version, but also on the peer's certificate (e.g., only accept a session which provides a 2048 bit certificate),</li>
<li>The addition of support for DNS name constraints in certificates, i.e., enforce rules that restrict an intermediate CA to issue certificates only for a specific DNS domain,</li>
<li>The addition of support for trust modules using PKCS #11<a href="https://www.blogger.com/null">,</a></li>
<li>Better integration with PKCS #11 smart cards, and Hardware Security Modules (HSMs); I believe we currently have one of the better, if not the best, support and integration with smart cards and HSMs among crypto libraries. That we mostly own to the support of <a href="https://tools.ietf.org/html/draft-pechanec-pkcs11uri-16">PKCS#11 URLs</a>, which allowed the conversion of high level APIs which accepted files, to API that would work with HSMs and smart cards, transparently, without changing it,</li>
<li>Support for the required by FIPS140-2 algorithms.</li>
</ul>
Most of these are described in the <a href="http://article.gmane.org/gmane.comp.encryption.gpg.gnutls.devel/7418">original announcement</a> mail, some others were completed and added gradually.<br />
<br />
A long-time requested feature that was implemented was the <a href="http://lists.gnutls.org/pipermail/gnutls-devel/2013-November/006602.html">removal of the need for explicit library initialization</a>. That relocated the previously explicit call of gnutls_global_init() to a library constructor, and eliminated a cumbersome requirement the previous versions of GnuTLS had. As a result it removed the need for locks and coordination in a large application which may use multiple libraries that depend on GnuTLS. However it had an unexpected side-effect. Because initialization was moved to a constructor, which is executed prior to an application entering main(), server applications which closed all the file descriptors on startup, did close the file descriptor that was held by GnuTLS for reading /dev/urandom. That's a pretty nasty bug, and was realized because <a href="https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=768841">in CUPS</a> the descriptor which replaced the /dev/urandom one, was a non-readable file descriptor. It was solved re-opening the descriptor on the first call of gnutls_global_init(), but that issue demonstrates the advantage and simplicity of the system call approach for the random generator, i.e., <a href="http://lwn.net/Articles/606141/">getentropy() or getrandom()</a>. In fact adding support for getentropy() reduced the complexity of the relevant code to 8 lines from 75 lines of code in the file-based approach.<br />
<br />
An other significant addition, at least for client-side, is the support for <a href="http://www.gnutls.org/manual/gnutls.html#Verification-using-PKCS11">trust modules, available using PKCS #11</a>. Trust modules, like p11-kit trust, allow clients to perform server certificate authentication using a method very similar to what the NSS library uses. That is, a system-wide database of certificates, such as the p11-kit trust module, can be used to query for the trusted CAs and intermediate anchors. These anchors may have private attached extensions, e.g., restrict the name constraints for a CA, or restrict the scope of a CA to code signing, etc., in addition to, or in place of the scope set by the CA itself. That has very important implications for system-wide CA management. CAs can be limited on scope, or per application, and can even be restricted to few DNS top-level domains using name constraints. Most importantly, the database can be shared across libraries (in fact in Fedora 21 the trust database is shared between GnuTLS and NSS), simplifying significantly administration, even though <a href="http://article.gmane.org/gmane.network.gnutls.general/3595">the tools to manage it are primitive for the moment</a>. That was a long time vision of Stef Walter, who develops p11-kit, and I'm pretty happy the GnuTLS part of it was completed, quite well.<br />
<br />
This was also the first year I attempted to document and publicize the goals for the next GnuTLS release which is 3.4.0 and will be released around next March. They can be <a href="https://www.gitorious.org/gnutls/pages/Plan3_4">seen in our gitorious wiki pages.</a> Hopefully, all the points will be delivered, although some of the few remaining points rely on a new release of the nettle crypto library, and on an update of <a href="https://github.com/bagder/c-ares/pull/20">c-ares to support DNSSEC</a>.<br />
<br />
Dependency-wise, GnuTLS is moving to a tighter integration with
nettle, which provides one of the fastest ECC implementations out there; I find unfortunate, though, that there seem to be no intention of
collaboration between the two GNU crypto libraries - nettle and
libgcrypt, meaning that optimizations in libgcrypt stay in libgcrypt and the same for nettle. GNU Libtasn1 is <a href="https://lists.gnu.org/archive/html/help-libtasn1/2014-01/msg00000.html">seeking for a co-maintainer</a> (or even better for someone to rethink and redesign the project I'd add), so feel free to step up if you're up to the job. As it is now, I'm taking care of any fixes needed for that project.<br />
<br />
On the other hand, we also had quite serious security vulnerabilities fixed that year. These varied from certificate verification issues to a heap overflow. A quick categorization of the serious issues fixed this year follows.<br />
<ul>
<li>Issues discovered with manual auditing (<a href="http://www.gnutls.org/security.html#GNUTLS-SA-2014-1">GNUTLS-SA-2014-1</a>, <a href="http://www.gnutls.org/security.html#GNUTLS-SA-2014-2">GNUTLS-SA-2014-2</a>). These were certificate verification issues and were discovered as part of manual auditing of the code. Thanks to Suman Jana, and also to Red Hat which provided me the time for the audit. </li>
<li>Issues discovered by Fuzzers (<a href="http://www.gnutls.org/security.html#GNUTLS-SA-2014-3">GNUTLS-SA-2014-3</a>, <a href="http://www.gnutls.org/security.html#GNUTLS-SA-2014-5">GNUTLS-SA-2014-5</a>):</li>
<ul>
<li>Codenomicon provided a few month valid copy of their test suite, and that helped to discover the first bug above,</li>
<li>Sean Buford of Google reported to me that using <a href="http://lcamtuf.coredump.cx/afl/">AFL</a> he identified a heap corruption issue in the encoding of ECC parameters; I have not used AFL but it seems quite an impressive piece of software,</li>
</ul>
<li>Other/Protocol issues (<a href="http://www.gnutls.org/security.html#GNUTLS-SA-2014-4">GNUTLS-SA-2014-4</a>), i.e., POODLE. Although, that is not really a GnuTLS or TLS protocol issue, POODLE takes advantage of the <a href="http://nmav.gnutls.org/2014/10/what-about-poodle.html">downgrade dance, used in several applications</a>.</li>
</ul>
Even though the sample is small, and only accounts for the issues with an immediate security impact, I believe that this view of the issues, shows the importance of fuzzers today. In a project of 180k lines of code, it is not feasible to fully rely on manual auditing, except for some crucial parts of it. While there are no security vulnerabilities discovered via static analysis tools like clang or coverity, we had quite a few other fixes because of these tools.<br />
<br />
So overall, 2014 was a quite productive year, both in the number of new features being added, and to the number of bugs fixed. New techniques were used to verify the source code, and new test cases were added in our test suite. What is encouraging is that more and more people test, report bugs and provide patches on GnuTLS. A big thank you to all of the people who contributed.Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com0tag:blogger.com,1999:blog-1625673575821156689.post-948720985658298082014-10-15T11:32:00.002+02:002014-10-20T16:41:00.486+02:00What about POODLE?Yesterday <a href="http://googleonlinesecurity.blogspot.cz/2014/10/this-poodle-bites-exploiting-ssl-30.html">POODLE</a> was announced, a fancy named new attack on the SSL 3.0 protocol, which relies on applications using a non-standard fallback mechanism, typically found in browsers. The attack takes advantage of<br />
<ul>
<li>a vulnerability in the CBC mode in SSL 3.0 which is known since a decade</li>
<li>a non-standard fallback mechanism (often called as downgrade dance)</li>
</ul>
So the novel and crucial part of the attack is the exploitation of the non-standard fallback mechanism.What is that, you may ask. I'll try to explain it in the next paragraph. Note that in the next paragraphs I'll use the term SSL protocol to cover TLS as well, since TLS is simply a newer version of SSL. <br />
<br />
The SSL protocol, has a protocol negotiation mechanism that wouldn't allow a fallback to SSL 3.0 from clients and servers that both support a newer variant (e.g, TLS 1.1). That detects modifications by man-in-the-middle attackers and the POODLE attack would have been <span data-dobid="hdw">thwarted</span>. However, a limited set of clients, perform a custom protocol fallback, the downgrade dance, which is straightforward but insecure. That set of clients seem to be most of the browsers; those in order to negotiate an acceptable TLS version follow something along the lines:<br />
<ol>
<li>Connect using the highest SSL version (e.g., TLS 1.2)</li>
<li>If that fails set the version to be TLS 1.1 and reconnect</li>
<li>...</li>
<li>until there are no options and SSL 3.0 is used.</li>
</ol>
That's a non-standard way to negotiate TLS and as the POODLE attack demonstrates, it is insecure. Any attacker can interrupt the first connection and make it seem like failure to force a fallback to a weaker protocol. The good news is, that mostly browsers use this construct, and few other applications should be affected.<br />
<br />
Why do browsers use this construct then? To their defence, there have been serious bugs in SSL and TLS standard protocol fallback implementation, in widespread software. For example, when TLS 1.2 was out, we realized that our TLS 1.2-enabled client in GnuTLS couldn't connect to a large part of the internet. Few large sites would refuse to talk to the GnuTLS client because it advertised TLS 1.2 as its highest supported protocol. The bug was on the server, that closed the connection when encountered with a newer protocol than its own, instead of negotiating its highest supported (in accordance with the TLS protocol). It took few years before TLS 1.2 was enabled by default in GnuTLS, and still then we had a hard time convincing our users that encountered connection failures, that it was a server bug. The truth is that users don't care who's bug it is, they will simply use software that just works.<br />
<br />
There has been long time since then (TLS 1.2 was published in 2008), and today almost all public servers follow the TLS protocol negotiation. So that may be the time for browsers to get rid of that relic of the past. Unfortunately, that isn't the case. The IETF TLS working group is now trying to <a href="https://tools.ietf.org/html/draft-ietf-tls-downgrade-scsv-00">standardize counter-measures</a> for the browser negotiation trickery. Even though I have become more pragmatist since 2008, I believe that forcing counter measures in every TLS implementation just because there used to (or may still be) be broken servers on the Internet, not only prolongs the life of an insecure out of protocol work-around, but creates a waste. That is, it creates a code dump called TLS protocol implementations which get filled with hacks and work-arounds, just because of few broken implementations. As <a href="https://www.ietf.org/mail-archive/web/tls/current/msg13871.html">Florian Weimer</a> puts it, all applications pay a tax of extra code, potentially introducing new bugs, and even more scary potentially introducing more compatibility issues, just because some servers on the Internet have chosen not to follow the protocol.<br />
<br />
Are there, however, any counter-measures that one can use to avoid the attack, without introducing an additional fallback signalling mechanism? As previously mentioned, if you are using the SSL protocol the recommended way, no work around is needed, you are safe. If for any reason you want to use the insecure non-standard protocol negotiation, make sure that no insecure protocols like SSL 3.0 are in the negotiated set or if disabling SSL 3.0 isn't an option, ensure that it is only allowed when negotiated as a fallback (e.g., offer TLS 1.0 + SSL 3.0, and only then accept SSL 3.0).<br />
<br />
In any case, that attack has provided the incentive to remove SSL 3.0 from public servers on the Internet. Given that, and its known vulnerabilities, it will no longer be included by default in the upcoming GnuTLS 3.4.0.<br />
<br />
[Last update 2014-10-20]<br />
<br />
PS. There are some recommendations to work around the issue by using RC4 instead of a block cipher in SSL 3.0. That would defeat the current attack and it closes a door, by opening another; RC4 is a broken cipher and there are <a href="http://www.isg.rhul.ac.uk/tls/">known attacks which recover plaintext</a> for it.Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com3tag:blogger.com,1999:blog-1625673575821156689.post-51388283074834001362014-04-17T16:21:00.000+02:002016-01-20T15:02:13.513+01:00software has bugs... now what?The recent bugs uncovered in TLS/SSL implementations, were received in the blogo-sphere with a quest for the perfectly secure implementations, that have no bugs. That is the modern quest for perpetual motion. Nevertheless, very few bothered by the fact that the application's only security defence line were few TLS/SSL implementations. We design software in a way that openssl or gnutls become the <a href="http://en.wikipedia.org/wiki/Maginot_Line">Maginot line</a> of security and when they fail they fail catastrophically.<br />
<br />
So the question that I find more interesting, is, can we live with libraries that have bugs? Can we design resilient software that will operate despite serious bugs, and will provide us with the necessary time for a fix? In other words could an application design have mitigated or neutralized the catastrophic bugs we saw? Let's see each case, separately.<br />
<br />
<br />
<div style="text-align: center;">
<b>Mitigating attacks that expose memory (heartbleed)</b></div>
<br />
The heartbleed attack allows an attacker to obtain a random portion of memory (there is a <a href="http://www.xkcd.com/1354/">nice illustration in xkcd</a>). In that attack all the data held within a server process are at risk, including user data and cryptographic keys. Could an attack of this scale be avoided?<br />
<br />
<a href="http://imgs.xkcd.com/comics/heartbleed_explanation.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://imgs.xkcd.com/comics/heartbleed_explanation.png" height="400" width="187" /></a>One approach is to avoid putting all of our eggs in one basket; that's a long-time human practice, which is also used in software design. <a href="http://www.citi.umich.edu/u/provos/papers/privsep.pdf%E2%80%8E">OpenSSH's privilege separation</a> and isolation of private keys using smart cards or software security modules are two prominent examples. The defence in that design is that the unprivileged process memory contains only data that are related the current user's session, but no privileged information such as passwords or the server's private key. Could we have a similar design for an SSL server? We already have a similar design for an SSL <a href="http://www.infradead.org/ocserv/">VPN server</a>, that revealing the worker processes' memory couldn't possibly reveal its private key. These designs come at a cost though; that is performance, as they need to rely on slow Inter-Process Communication (IPC) for basic functionality. Nevertheless, it is interesting to see whether we can re-use the good elements of these designs in existing servers.<br />
<br />
<br />
<br />
Few years ago in a joint effort of the Computer Security and Industrial Cryptography research group of KU Leuven, and Red Hat we produced a <a href="http://lwn.net/Articles/401548/">software security module (softhsm)</a> for the Linux-kernel, that had the purpose of preventing a server memory leak to an adversary from revealing its private keys. Unfortunately we failed to convince the kernel developers for its usefulness. That wasn't the first attempt for such a module. A user-space security module existed already and called <a href="http://www.clizio.com/lsmpkcs11.html">LSM-PKCS11</a>. Similarly to the one we proposed, that would provide access to the private key, but the operations will be performed on an isolated process (instead of the kernel). If such a module would be in place in popular TLS/SSL servers there would be no need to regenerate the server's certificates after a heartbleed-type of attack. So what can we do to use such a mechanism in existing software?<br />
<br />
The previous projects are dead since quite some time, but there are newer modules like <a href="http://www.opendnssec.org/softhsm/">opendns's softhsm</a> which are active. Unfortunately softhsm is not a module that enforces any type of isolation. Thus a wrapper PKCS #11 module over softhsm (or any other software HSM) that enforces process isolation between the keys and the application using it would be a good starting point. GnuTLS and NSS provide support for using PKCS #11 private keys, and adding support for this module in apache's mod_gnutls or mod_nss would be trivial. OpenSSL would still need some support for PKCS #11 modules to use it.<br />
<br />
Note however, that such an approach would take care of the leakage of the server's private key, but would not prevent any user data to be leaked (e.g., user passwords). That of course could be handled by a similar isolation approach on the web server, or even the same module (though not over the PKCS #11 API).<br />
<br />
So if the solution is that simple, why isn't it already deployed? Well, there is always a catch; and that catch as I mentioned before is performance. A simple PKCS #11 module that enforces process isolation would introduce overhead (due to IPC), and most certainly is going to become a bottleneck. That could be unacceptable for many high-load sites, but on the other hand that could be a good driver to optimize the IPC code paths.<br />
<br />
<br />
<div style="text-align: center;">
<b>Mitigating an authentication issue</b></div>
<br />
The question here is what could it be done for the bugs found in GnuTLS and Apple's SSL implementation, that allowed certain certificates to always succeed authentication. That's related to a PKI failure, and in fact the same defences required to mitigate a PKI failure, can be used. A PKI failure is typically a CA compromise (e.g., <a href="http://en.wikipedia.org/wiki/DigiNotar">the Diginotar issue</a>). <br />
<br />
One approach is again on the same lines as above, to avoid reliance on a single authentication method. That is, use two-factor authentication. Instead of relying only on PKI, combine password (or shared-key) authentication with PKI over TLS. Unfortunately, that's not as simple as a password key exchange over TLS, since that is vulnerable to eavesdropping once the PKI is compromised. To achieve two factor authentication with TLS, one can simply negotiate a session using TLS-PSK (or SRP), and renegotiate on top of it using its certificate and PKI. That way both factors are accounted, and the compromise of any of the two factors doesn't affect the other.<br />
<br />
Of course, the above is a quite over-engineered authentication scenario, requires significant changes to today's applications, and also imposes a significant penalty. That is a penalty in performance and network communication as twice the authentication now required twice the round-trips. However, a simpler approach is to rely on <a href="http://nmav.gnutls.org/2012/02/need-for-ssh-like-authentication-in-tls.html">trust on first use</a> or simply SSH authentication on top of PKI. That is, use PKI to verify new keys, but follow the SSH approach with previously known keys. That way, if the PKI verification is compromised at some point, it would affect only new sessions to unknown hosts. Moreover, for an attack to be undetected the adversary is forced to operate a man-in-the-middle attack indefinitely, or if we have been under attack, a discrepancy on the server key will be detected on the first connection to the real server.<br />
<br />
<br />
In conclusion, it seems that we can have resilient software to bugs, no matter how serious, but that software will come at a performance penalty, and would require more conservative designs. While there are applications that mainly target performance and could not always benefit from the above ideas, there are several applications that can sacrifice few extra milliseconds of processing for a more resilient to attacks design.<br />
<br />Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com0tag:blogger.com,1999:blog-1625673575821156689.post-56751651478556171922013-11-17T12:05:00.001+01:002017-06-17T16:19:02.494+02:00Inside an SSL VPN protocolSome time ago when trying to provide a way to interconnect the routers of the company I was working on, I attempted to evaluate the various secure VPN solutions available as free software. As I was already familiar with cryptography and secure communications protocols, I initially tried to review their design. To my surprise the most prominent secure VPN available at the time, had its source code as its documentation. My reverse engineering of the protocol showed that while SSL was claimed, it was only used as key exchange method. The actual protocol transferring packets was a custom one. This didn't align with my taste, but that was finally included in the routers as there were not many alternatives at the time.<br />
<br />
Years after that, I was contacted by David Woodhouse, proposing changes to GnuTLS in order to support an early draft version of Datagram TLS (DTLS). Since we already had support for the final version of DTLS (i.e, 1.0), I couldn't understand the request. As it seems David was working on <a href="http://www.infradead.org/openconnect/">openconnect</a>, a client for the CISCO AnyConnect SSL VPN protocol.<br />
<br />
That intrigued me, as it was the first SSL VPN solution I had heard of that used Datagram TLS to transfer data. My interest increased as I learned more about openconnect, so much that I even ended-up writing <a href="http://www.infradead.org/ocserv/">the server counterpart of openconnect</a>. Because the details of the protocol are still confined to David's head and mine, I'll attempt in this post to describe them on a higher level than source code.<br />
<br />
<h2>
</h2>
<h2>
<b><span style="font-weight: normal;">Key exchange & Authentication </span></b></h2>
The protocol is very simple in nature and is HTTP-based. Initially the client connects to the server over TLS (note that TLS runs only over TCP, something that I take as granted on the rest of this text). On that TLS session the server is authenticated using its certificate, and the client may optionally be authenticated using a certificate as well. After the TLS key exchange is complete, the client obtains an authentication page by issuing an HTTP "POST /" request containing the following.<br />
<br />
<code>
<config-auth client="vpn" type="init"></code><br />
<code></code><code><code> </code>
<version who="vpn">v5.01</version></code><br />
<code></code><code><code> </code>
<device-id>linux-64</device-id></code><br />
<code></code><code><code> </code>
<group-access>https://example.com</group-access></code><br />
<code>
</config-auth></code><br />
<code> </code>
<br />
If the client did not present a certificate, or if additional information is required (e.g., an one-time password), the following takes place.
The server replies with a request for the client's username that looks like:<br />
<br />
<code>
<auth id="main"></code><br />
<code></code><code><code> </code><message>Please enter your username</message></code><br />
<code></code><code><code> </code><form action="/auth" method="post"></code><br />
<code></code><code><code> </code></code><code><code><code> </code></code><input label="Username:" name="username" type="text" /></code><br />
<code><code> </code></form><br /></auth></code><br />
<br />
Which effectively contains the message to be printed to the user, as well the URL (/auth) where the string obtained by the user should be sent.
The client subsequently replies with a POST containing his username.<br />
<br />
<code>
<config-auth client="vpn" type="auth-reply"><br /> <version who="vpn">v5.01</version><br /> <device-id>linux-64</device-id><br /> <auth><username>test</username></auth><br /></config-auth></code><br />
<code> </code>
<br />
Once the username is received by the server, a similar conversation continues for the number of passwords that are required by the user. The message format remains essencially the same so we skip this part.<br />
<br />
<h2>
<span style="font-weight: normal;">VPN tunnel establishment</span> </h2>
When authenticated, the client issues an HTTP CONNECT request. That effectively terminates the HTTP session and initiates a VPN tunnel over the existing TLS session. In short the client issues:<br />
<br />
<pre>CONNECT /CSCOSSLC/tunnel HTTP/1.1</pre>
<pre>User-Agent: Open AnyConnect VPN Agent v5.01
X-CSTP-Version: 1
X-CSTP-MTU: 1280
X-CSTP-Address-Type: IPv6,IPv4
X-DTLS-Master-Secret: DAA8F66082E7661AE593 [truncated]
X-DTLS-CipherSuite: AES256-SHA:AES128-SHA:DES-CBC3-SHA
</pre>
<br />
and the server replies with something that looks like the following.<br />
<br />
<pre>HTTP/1.1 200 CONNECTED
X-CSTP-Version: 1
X-CSTP-DPD: 440
X-CSTP-Address: 192.168.1.191
X-CSTP-Netmask: 255.255.255.0
X-CSTP-DNS: 192.168.1.190
X-CSTP-Split-Include: 192.168.1.0/255.255.255.0
X-CSTP-Keepalive: 32400
X-CSTP-Rekey-Time: 115200
X-CSTP-Rekey-Method: new-tunnel
X-DTLS-Session-ID: 767a9ad8 [truncated]
X-DTLS-DPD: 440
X-DTLS-Port: 443
X-DTLS-Rekey-Time: 115200
X-DTLS-Keepalive: 32400
X-DTLS-CipherSuite: AES128-SHA
X-DTLS-MTU: 1214
X-CSTP-MTU: 1214
</pre>
<br />
This completes the HTTP authentication phase of the protocol. At this point a VPN tunnel is established over TLS, and the client obtains the IP address present in the "X-CSTP-Address" header, and adds the "X-CSTP-Split-Include" routes to its routing table. The IP packets read from the local TUN device are sent via the tunnel to the peer with an 8-byte prefix, that allows distinguishing IP data from various VPN packets such as keep-alive or dead-peer-detection.<br />
<br />
It is, however, well known that <a href="http://sites.inka.de/~W1011/devel/tcp-tcp.html">TCP over TCP is far from being optimal</a>, and for this reason the server provides the option to the client for an additional tunnel over UDP and DTLS.<br />
<br />
<br />
<h2>
<span style="font-weight: normal;">
VPN tunnel over UDP</span></h2>
To initiate the Datagram TLS over UDP session the client sends the "X-DTLS-Master-Secret" and "X-DTLS-CipherSuite" headers at its CONNECT request (see above). The former contains the key to be used as the pre-master key, in TLS terminology, and the latter contains a list of ciphersuites as read by OpenSSL. The server replies on these requests by accepting a ciphersuite and presenting it in its "X-DTLS-CipherSuite" header, adding the headers such as "X-DTLS-Port" and "X-DTLS-Session-ID" and others less relevant for this description.<br />
<br />
At the receipt of that information the client initiates a Datagram TLS session (using a draft version of DTLS 1.0) on the port indicated by the server. A good question at this point is how is the server
associating the new DTLS session request with this particular client. The hint here is that the client copies the value in the "X-DTLS-Session-ID" header to its Session ID field of the DTLS Client Hello. That session is in effect handled as a session resumption that uses the "X-DTLS-Master-Secret" as pre-master secret, the previous session ID and the ciphersuite negotiated in the "X-DTLS-CipherSuite" header (presumably that hackish approach exists because this solution pre-dates <a href="http://tools.ietf.org/html/rfc4279">TLS with preshared keys</a>).<br />
<br />
That completes the DTLS negotiation over UDP, and the establishment of the second VPN tunnel. From this point this tunnel is being used as primary, and if for some reason it goes down the traffic is redirected to the backup tunnel over TLS. A difference of the DTLS tunnel with the TLS one, is that the VPN packet header is a single byte instead of 8. The smaller header is an important save since DTLS packets are restricted by the link MTU which is further reduced by the headers of IP, UDP, and DTLS.<br />
<br />
<h2>
<span style="font-weight: normal;">Rekeying</span> </h2>
<h2>
</h2>
DTLS allows the transfer up to 2<sup>48</sup> packets (or 220 petabytes - assuming an average of 800 bytes per packet) in a single session. To allow for even larger transfers and to refresh the keys used the protocol enforces re-keying by time as indicated by the "X-DTLS-Rekey-Time". At the moment openconnect implements that by tearing up both the TLS and DTLS tunnels and reconnecting to the server.<br />
<br />
<h2>
<span style="font-weight: normal;">Reconnections</span> </h2>
<h2>
</h2>
Reconnections in this protocol, e.g., because of the client switching networks and changing IP, are handled on the HTTP level. That is the client accepts a cookie by the server and uses it on any subsequent connection. <br />
<br />
<h2>
<span style="font-weight: normal;">Data transfer</span></h2>
<br />
In the VPN tunnel establishment we show the negotiation of the ciphersuite used for the DTLS tunnel and actual data transfer. Due to the protocol's restriction to pre-DTLS 1.0 the available ciphersuite options are the following three:<br />
<ul>
<li>AES256-CBC-SHA</li>
<li>AES128-CBC-SHA</li>
<li>3DES-CBC-SHA</li>
</ul>
3DES-CBC is a performance nightmare, so for any practical purposes AES128-CBC and AES256-CBC are being used. However, all of these ciphersuites are vulnerable to the padding oracle attacks, and in have considerable header overhead (they require a full-block random IV per packet, padding and have a quite long MAC of 20 bytes). These inefficiencies were the main incentive for <a href="http://nmav.gnutls.org/2013/05/salsa20-and-umac-in-tls.html">the salsa20 proposal in TLS</a>.<br />
<br />
<h2>
<span style="font-weight: normal;">Overview</span></h2>
Overall the protocol looks hackish for someone reading it today on a high level. It is however, the closest to standard's based VPN protocol that is around. It has some weaknesses (vulnerable to padding oracle attacks) and limitations as well (for example it cannot easily use any other version than the pre-draft DTLS), and they can be easily be fixed, but let's leave that for a future post.<br />
<br />Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.comtag:blogger.com,1999:blog-1625673575821156689.post-78339275481425833632013-05-16T12:43:00.001+02:002013-08-05T18:16:17.607+02:00Salsa20 and UMAC in TLSLately while I was implementing and deploying <a href="http://www.infradead.org/ocserv/">an SSL VPN server</a>, I realized that even for a peer-to-peer connections the resources taken for encryption on the two ARM systems I used were quite excessive. These ARM processors do not have instructions to speed-up AES
and SHA1, and were spending most of their resources to encrypt and
authenticate the exchanged packets. <br />
<br />
What can be done in such a case? The SSL VPN server utilized DTLS which runs over UDP and restricts the packet size to the path MTU size (typically 1400 bytes if we want to avoid fragmentation and reassembly), thus wastes quite some resources on packetization of long data. Since the packet size cannot be modified we could possibly improve the encryption and authentication speed. Unfortunately using a more lightweight cipher available in TLS, such as RC4, is not an option as it is not available in DTLS (while TLS and DTLS mostly share the same set of ciphersuites, some ciphers like RC4 due to constraints cannot be used in DTLS). Overall, we cannot do much with the currently defined algorithms in DTLS, we need to move outside the TLS protocol box.<br />
<br />
Some time ago there was an <a href="http://www.ecrypt.eu.org/stream/">EU-sponsored competition</a> on stream ciphers (which are typically characterized by their performance) and <a href="http://www.ecrypt.eu.org/stream/e2-salsa20.html">Salsa20</a>, one of the winners, was recently added in <a href="http://www.lysator.liu.se/%7Enisse/nettle/">nettle</a> (the library GnuTLS uses) by Simon Josefsson who conceived the idea of such a fast stream cipher being added to TLS. While modifying GnuTLS to take advantage of Salsa20, I also considered moving away from HMAC (the slow message authentication mechanism TLS uses) and use the <a href="http://www.ietf.org/rfc/rfc4418.txt">UMAC</a> construction which provides a security proof and impressive performance. My initial attempt to port the UMAC reference code (which was not ideal code), motivated the author of nettle, Niels Moeller, to reimplement UMAC in a cleaner way. As such Salsa20 with UMAC is now included in nettle and are used by GnuTLS 3.2.0. The results are quite impressive. <br />
<br />
Salsa20 with UMAC96 ciphersuites were 2-3 times faster than any AES variant used in TLS, and outperformed even RC4-SHA1, the fastest ciphersuite defined in the TLS protocol. The results as seen on an Intel i3 are shown below (they are reproducible using gnutls-cli --benchmark-tls-ciphers). Note that SHA1 in the ciphersuite name means HMAC-SHA1 and Salsa20/12 is the variant of Salsa20 that was among the eStream competition winners.<br />
<br />
<center>
<table border="2" cellpadding="1" cellspacing="1" style="width: 100%px;">
<caption>Performance on 1400-byte packets</caption>
<tbody>
<tr><th>Ciphersuite</th><th>Mbyte/sec</th> </tr>
</tbody><tbody>
<tr> <td><b>SALSA20-UMAC96</b></td><td>107.82</td> </tr>
<tr> <td><b>SALSA20-SHA1</b></td><td>68.97</td> </tr>
<tr> <td><b>SALSA20/12-UMAC96</b></td><td>130.13</td> </tr>
<tr> <td><b>SALSA20/12-SHA1</b></td><td>77.01</td> </tr>
<tr> <td>AES-128-CBC-SHA1</td><td>44.70</td> </tr>
<tr> <td>AES-128-GCM</td><td>44.33</td> </tr>
<tr> <td>RC4-SHA1</td><td>61.14</td> </tr>
</tbody></table>
</center>
<br />
The results as seen on the openconnect VPN performance on two PCs, connected over a 100-Mbit ethernet, are as follows.<br />
<br />
<center>
<table border="2" cellpadding="1" cellspacing="1" style="width: 100%px;">
<caption>Performance of a VPN transfer over ethernet</caption>
<tbody>
<tr><th>Ciphersuite</th><th>Mbits/sec</th><th>CPU load (top)</th> </tr>
</tbody><tbody>
<tr> <td>None (plain transfer)</td><td>94</td><td>8%</td> </tr>
<tr> <td><b>SALSA20/12-UMAC96</b></td><td>89</td><td>57%</td> </tr>
<tr> <td>AES-128-CBC-SHA1</td><td>86</td><td>76%</td> </tr>
</tbody></table>
</center>
<br />
While the performance difference of SALSA20 and AES-128-CBC isn't impressive (AES was already not too low), the difference in the load of the server CPU is significant.<br />
<br />
Would such ciphersuites be also useful to a wider set of applications than VPN? I believe the answer is positive, and not only for performance reasons. This year new attacks were devised on AES-128-CBC-SHA1 and RC4-SHA1 ciphersuites in TLS that cannot be easily worked around. For AES-128-CBC-SHA1 there are some hacks that reduce the impact of the known attacks, but they are hacks not a solution. As such TLS will benefit from a new set of ciphersuites that replace the old ones with known issues. Moreover, even if we consider RC4 as a viable solution today (which is not), the DTLS protocol cannot take advantage of it, and datagram applications such as VPNs need to rely on the much slower AES-128-GCM.<br />
<br />
So we see several advantages in this new list of ciphersuites and for that, with Simon Josefsson and Joachim Strombergson we plan to propose to the IETF TLS Working Group the adoption of a set of <a href="http://tools.ietf.org/html/draft-josefsson-salsa20-tls-02">Salsa20-based ciphersuites</a>. We were asked by the WG chairs to present our work in the <a href="http://www.ietf.org/meeting/87/index.html">IETF 87 meeting</a> in Berlin. For that I plan to travel to the meeting in Berlin to present our current <a href="http://tools.ietf.org/html/draft-josefsson-salsa20-tls-02">Internet-Draft</a>.<br />
<br />
For that, if you support defining these ciphersuites in TLS, we need your help. If you are an IETF participant please join the TLS Working Group meeting and indicate your support. Also if you have any feedback on the approach or suggest another field of work that this could be useful please <a href="mailto:nmav@gnutls.org">drop me a mail</a> or leave a comment below mentioning your name and any association.<br />
<br />
<s>Moreover, as it is now, a lightning trip to Berlin on these dates would cost at minimum 800 euros including the IETF single day registration. As this is not part of our day job any contribution that would help to partially cover those expenses is welcome.</s>
<br />
<center>
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
<input name="cmd" type="hidden" value="_s-xclick" />
<input name="hosted_button_id" type="hidden" value="RR4KU5WCVPS2W" />
<input alt="PayPal - The safer, easier way to pay online!" border="0" name="submit" src="https://www.paypalobjects.com/en_US/BE/i/btn/btn_donateCC_LG.gif" type="image" />
<img alt="" border="0" height="1" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" />
</form>
</center>
<br />Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com0tag:blogger.com,1999:blog-1625673575821156689.post-57137644466320358722013-03-26T11:38:00.000+01:002014-09-29T20:52:50.320+02:00The perils of LGPLv3LGPLv3 is the latest version of the GNU Lesser General Public License. It follows the successful LGPLv2.1 license, and was released by Free Software Foundation as a counterpart to its GNU General Public License version 3.<br />
<br />
The goal of the GNU Lesser General Public Licenses is to provide software that can be used by both proprietary and free software. This goal has been successfully handled so far by LGPLv2.1, and there is a multitude of libraries using that license. Now we have LGPLv3 as the latest, and the question is how successful is LGPLv3 on this goal?<br />
<br />
In my opinion, very little. If we assume that its primary goal is to be used by free software, then it blatantly fails that. LGPLv3 has serious issues when used with free software, and especially with the GNU GPL version 2. Projects under the GPLv2 license violate its terms if they use an LGPLv3 library (because LGPLv3 adds additional restrictions).<br />
<br />
What does FSF suggest on that case? It <a href="http://gplv3.fsf.org/dd3-faq">suggests upgrading GPLv2 projects to GPLv3</a>. That's a viable solution, if you actually can and want to upgrade to GPLv3. At the GnuTLS project, after we switched to LGPLv3, we realized that in practice we forced all of our GPLv2 (or later) users to distribute their binaries under GPLv3. Moreover, we also realized that
several GPLv2-only projects (i.e., projects that did not have the GPLv2
or later clause in their license), could no longer use the library at all.<br />
<br />
The same incompatibility issue exists with LGPLv2.1 projects that want to use an LGPLv3 library. They <i>must</i> be upgraded to LGPLv3. <br />
<br />
In discussions within FSF, Stallman had suggested using the dual license LGPLv3 or GPLv2, in libraries to overcome these issues. That although it does not solve the issue with the LGPLv2.1 libraries, is not a bad suggestion, but it has a major drawback. The projects under the dual LGPLv3 or GPLv2 license, cannot re-use code from other LGPLv3 projects nor from GPLv2 projects, creating a rather awkward situation for the project.<br />
<br />
So it seems we have a "lesser" kind of license for use by libraries, that mandates free software project authors the license they should release their projects with. I find that unacceptable for such a license. <i>It seems to me that with this license, FSF just asks you not to use LGPLv3 for your libraries.</i><br />
<br />
So ok, LGPLv3 has issues with free software licenses... but how does it work with proprietary projects? Surprisingly it works better than with free software licenses; it doesn't require them to change their license.<br />
<br />
Nevertheless there is a catch. My understanding of LGPLv3 (it is one of the hardest licenses to read - as it requires you to read first the GPLv3 remove some of its clauses and then add some additional ones) is that it contains the anti-tivoization clause of GPLv3. That is, in a home appliance, if the creator of the appliance has an upgrade mechanism, he has to provide a way to upgrade the library. That doesn't really make sense to me, neither as a consumer, nor as someone who potentially creates software for appliances.<br />
<br />
As a consumer, why would I consider the ability to only upgrade the (say) libz library on my router a major advantage? You may say that I have additional privileges (more freedom) on my router. It could be, but my concern is that this option will hardly ever happen. Will an appliance creator chose a "lesser" GPL library when this clause is present? Will he spend the additional time to create a special upgrade mechanism for a <i>single library</i> to satisfy the LGPLv3 license, or will he chose a non-LGPLv3 license? (remember that the goal of the LGPL licenses according to FSF is to use them in software where proprietary, or free of charge alternatives exist)<br />
<br />
<br />
So overall, it seems to me that LGPLv3 has so many practical issues that actually make its advantages (e.g. patent clauses) seem irrelevant, and I don't plan to use it as a license of my libraries. I'm back to the good old LGPLv2.1. <br />
<br />Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com10tag:blogger.com,1999:blog-1625673575821156689.post-37471828294390619162013-02-05T11:55:00.000+01:002013-02-07T10:13:19.857+01:00Time is money (in CBC ciphersuites)While protocols are not always nicely written, deviating from them has a big disadvantage. You cannot blame someone else if there is a problem. It has a small advantage though, you avoid monoculture and an attack that is applicable to the protocol may not applicable to you. What happened in the following story is something in between.<br />
<br />
But let's start from the beginning. Few months ago I received <a href="http://www.isg.rhul.ac.uk/tls/">a paper from </a><a href="http://www.isg.rhul.ac.uk/tls/">Nadhem Alfardan and</a><a href="http://www.isg.rhul.ac.uk/tls/"> Kenny Paterson</a> about a new timing attack on TLS CBC ciphersuites. That paper got on my low priority queue since I'm not that impressed by timing attacks. They are nicely done on the lab, but fall short in the field. Nevertheless at some point this attack got my attention because it claimed it could recover few bits of the plaintext when using GnuTLS over ethernet.<br />
<br />
Let's see what is the actual scenario though. In order for the attack to work the client must operate as follows. It connects to a server, it sends some data (which will be encrypted), the attacker will intercept them, and terminate the client's connection abnormally. The client will then reconnect and resend the same data, again and again.<br />
<br />
That is not the typical scenario of TLS, but it is not so unrealistic either (think of a script that does that). The main idea of the attack is that the described attacker can distinguish between different padding values of TLS messages using the available timing information between receipt of a message and server reply (which may just be the TCP tear down messages).<br />
<br />
How is that done with GnuTLS? The attacker takes the input ciphertext and forms a message of 20 AES blocks. Then takes the part of the message he's interested at and copies the matching block and its predecessor as the last two encrypted blocks (which contain the MAC and padding).<br />
<br />
Then on every different user connection it XORs the last byte of the penultimate block with a byte (say Delta to be consistent with the paper) of his choice. On every client reconnection he repeats that using a different Delta and waits for the server response (a TLS server notifies the client of decryption failure).<br />
<br />
In the paper they plot a diagram that shows that certain values of Delta require different time to receive a reply. I re-implemented the attack for verification, and the measurements on the server can be seen in the following diagram. Note that the last plaintext byte is zero (also note that some attack results in the paper are due to a bug the authors discovered which is now fixed, the discussion here refers to the fixed version of GnuTLS).<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjdPLyDTtCpjqoMal8vZw5KGKQfVX5TGXGaXOHPHKOMB_xHQ487eXvxQ6JDoEQAe6SKBiHUbw0FOm0F5j7-j2XCCaVuh5o5uapvKdIaJU1k5jMq5U_3PqQC68CThbtMJN13z64XgkIIOYl/s1600/sha1-server-timings-med.png" style="margin-left: auto; margin-right: auto;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjdPLyDTtCpjqoMal8vZw5KGKQfVX5TGXGaXOHPHKOMB_xHQ487eXvxQ6JDoEQAe6SKBiHUbw0FOm0F5j7-j2XCCaVuh5o5uapvKdIaJU1k5jMq5U_3PqQC68CThbtMJN13z64XgkIIOYl/s400/sha1-server-timings-med.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Median server timings for AES-CBC-SHA1, for a varying Delta, on GnuTLS 3.1.6 or earlier (view on the server)</td></tr>
</tbody></table>
It is clear that different values of Delta cause different response time. What we see in these timing results is the differences due to the sizes of the data being applied to the hash algorithm. In GnuTLS the bigger the Delta, the larger the pad (remember that the last byte of plaintext was zero), and less time is spent in hashing data.<br />
<br />
The small increase in processing time seen on every block, is the correctness check of the pad (which takes more time as the pad increases). In that particular CPU I used, the differences per block seem to be around 200 nanoseconds, and the difference between the slower and the fastest block is around 1 microsecond.<br />
<br />
The question is, can an attacker notice such small differences over ethernet? In the paper the authors claim yes (and present some nice figures). I repeated the test, not over the ethernet, but over unix domain sockets, i.e., only delays due to kernel processing are added. Let's see the result.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgln1Qe0mf2ZVduF4wpBn7TciDFSoCdb35xRGrKFJ7AGkzngprQPGxlEaGL3vfs0SW5pv7gwuLIWYhEk6nGlPm4bklWGNKvYZfcwanbk5NssCPOS5UXdjanMhljtBHoz-PMP0FLvNTsjiQ8/s1600/sha1-timings-med.png" style="margin-left: auto; margin-right: auto;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgln1Qe0mf2ZVduF4wpBn7TciDFSoCdb35xRGrKFJ7AGkzngprQPGxlEaGL3vfs0SW5pv7gwuLIWYhEk6nGlPm4bklWGNKvYZfcwanbk5NssCPOS5UXdjanMhljtBHoz-PMP0FLvNTsjiQ8/s400/sha1-timings-med.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 2. Median server timings for AES-CBC-SHA1, for a varying Delta, on GnuTLS 3.1.6 or earlier (attacker view)</td></tr>
</tbody></table>
<br />
Although it is more noisy the pattern is still visible. Could we avoid that pattern from being visible? Let's first follow the RFC padding removal precisely and check again.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge5Q5ct28REDlzihcjqYuWb_26jqr3eX1haUv_2uVY21VlG3Sc8sR2ugrZQqlArOhReD9idy6JbTqVgWvNXHv8oABjQh4ZLqLKmM8sN6964JrABJhsBWfDuLt7sFlU91RIw_bNm-nfNIXB/s1600/sha1-server-timings-med.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge5Q5ct28REDlzihcjqYuWb_26jqr3eX1haUv_2uVY21VlG3Sc8sR2ugrZQqlArOhReD9idy6JbTqVgWvNXHv8oABjQh4ZLqLKmM8sN6964JrABJhsBWfDuLt7sFlU91RIw_bNm-nfNIXB/s400/sha1-server-timings-med.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 1. Median server timings for AES-CBC-SHA1, for a varying Delta, on GnuTLS 3.1.6 with TLS conformant padding check applied (view on the server)</td></tr>
</tbody></table>
<br />
That's much better. Obvious patterns disappeared. However, there is no happy end yet. In the same paper the authors present another attack on OpenSSL which uses the above padding method. Surprisingly that attack can recover more data than before (but at a slower pace). That's the Full Plaintext recovery attack on the paper and it uses the fact that TLS 1.2 suggests to assume 0 bytes of padding. Zero bytes of padding is an invalid value (padding in TLS is from 1 to 256 bytes) and thus cannot be set by a legitimate message.<br />
<br />
This can be exploited and then invalid padding can be distinguished from valid padding, by selecting message size in a way that if 0 is used as pad, the additional byte that
will be hashed will result to a full block processed by the hash
algorithm. That is we would expect that if a correct pad is guessed less processing would occur. Let's visualize it on an example.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCctXf2o5amB8ph_cqxCMK3ZPo_eTcYb-JJz8JAuJB0UVOb8O0nQFTsKGq6hQzJx6o_ZizEh21lsveDH7DyHdtFyTiaoyFqm3D8bMYUe75Owekgk8Ui6Fis-NebaFw1uBukr6F2a-_ZYq4/s1600/sha1-one-server-timings-med.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCctXf2o5amB8ph_cqxCMK3ZPo_eTcYb-JJz8JAuJB0UVOb8O0nQFTsKGq6hQzJx6o_ZizEh21lsveDH7DyHdtFyTiaoyFqm3D8bMYUe75Owekgk8Ui6Fis-NebaFw1uBukr6F2a-_ZYq4/s400/sha1-one-server-timings-med.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Median server timings for AES-CBC-SHA1, for a varying Delta, on a TLS compliant implementation</td></tr>
</tbody></table>
<br />
Notice at the lonely point on the bottom left. We can see that when Delta is zero the processing is 200ms faster. For the selected message, the zero Delta resulted to a correct pad. How to fix that? That is pretty tricky.<br />
<br />
In order to fix this pattern the code that is doing the CBC pad removal has to be aware of the internal block sizes in the hash, as well as any internal padding used by the hash. In a typical layered implementation (or at least in GnuTLS) that isn't easy. The internal hash block size wasn't available, because one shouldn't need to know that. The paper suggests a fix, that assumes a block size of 64, which is correct for all the HMAC algorithms in TLS, but that isn't future proof (e.g. SHA3 hasn't got the same block size).<br />
<br />
So what to do there? The fix for GnuTLS is now similar to the hack described in the paper. The hash block size and knowledge of the internal padding are taken into account to achieve a pretty uniform processing time (see below). Any differences are now into the level of 10's of nanoseconds.<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC4oH6w7hIU0AGu3KUeQubC-Jz9R68HYctMpJayk2Ridc9zJsNLPkNF9RlPytLUQrpALLkG6MEHb8FpEKQvVwRHT3C-6_tL8gL7Ir0IiZ7bJml2Jcs9h-WGD9kV05GzwE9Nw95xuB6z01P/s1600/sha1-one-server-timings-med.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhC4oH6w7hIU0AGu3KUeQubC-Jz9R68HYctMpJayk2Ridc9zJsNLPkNF9RlPytLUQrpALLkG6MEHb8FpEKQvVwRHT3C-6_tL8gL7Ir0IiZ7bJml2Jcs9h-WGD9kV05GzwE9Nw95xuB6z01P/s400/sha1-one-server-timings-med.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Figure 4. Median server timings for AES-CBC-SHA1, for a varying Delta, after work-around is applied </td></tr>
</tbody></table>
<br />
<br />
Now we're very close to a happy end. What is important though, is to prevent a similar attack from occurring next year. This isn't a new attack, even the TLS 1.1 protocol acknowledges that timing channel, but does nothing to solve it. TLS implementations now need to have 2-3 pages of code just to remove the CBC padding, and that makes clear that the TLS spec is broken and needs to be updated.<br />
<br />
Together with Alfredo Pironti we <strike>plan to propose</strike> <a href="http://tools.ietf.org/html/draft-pironti-tls-length-hiding-00">proposed a new padding mechanism</a> which one of its targets is to eliminate that CBC padding issue (the other target is to allow arbitrary padding to any ciphersuite). The way the timing channels in CBC padding are eliminated, is by considering pad as part of the transferred data (i.e., it is properly authenticated). As such the pad check code does not provide any side-channel information because it operates only after the MAC is verified.<br />
<br />
PS. Kudos go to Oscar Reparaz for long discussions on side channel attacks.<br />
<br />
PS2. I should note that Nadhem and Kenny were very kind to
notify me of the bugs and the attack. While this may seem like the
obvious thing to do, it is not that common with other academic authors (I'm very tempted to place a link here).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1UCQgLVnOyoHj6X24jZA8lt9-ns2ceqXuMFHWG1HeyBT_Kad7YyyMkcBVBGQhpHCYmCIM1PW8sti1ob2sJY0ByGCsH03gXdli0XxW2ZtpzVQ1zN5NjdlumX3XsIFJDetxooJwN_Y1qvFQ/s1600/tls-sha1.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><br /></a></div>
Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com0tag:blogger.com,1999:blog-1625673575821156689.post-2506002759855880932012-10-08T21:22:00.001+02:002013-05-22T12:46:30.948+02:00Some thoughts on the DANE protocolA while ago I was writing on <a href="http://nikmav.blogspot.be/2012/02/need-for-ssh-like-authentication-in-tls.html">why we need an alternative authentication method in TLS</a>. Then I described the SSH-style authentication and how it was implemented it GnuTLS. Another approach is the <a href="http://tools.ietf.org/html/rfc6698">DANE</a> protocol. It uses the hierarchic model of <a href="http://en.wikipedia.org/wiki/DNSSEC">DNSSEC</a> to provide an alternative authentication method in TLS.<br />
<br />
DNSSEC uses a hierarchical model similar to a single root CA that is delegating CA responsibilities to each individual domain holder for its domain. In DANE a DNSSEC-enabled domain may sign entries for each TLS server in the domain. The entries contain information, such as the hash, of the TLS server's certificate. That's a nice idea and can be used instead, or in addition to the existing commercial CA verification. Let's see two examples that demonstrate DANE. Let's suppose we have an HTTPS server called <i>www.example.com </i>and a CA.<br />
<br />
A typical web client after it successfully verifies <i>www.example.com</i>'s certificate using the CA's certificate, will check the DANE entries. If they match it's assured that a CA compromise does not affect its current connection. That is, in this scenario, an attacker needs not only to compromise the<i> example.com</i>'s CA, but also to compromise the server's DNS domain service.<br />
<br />
Another significant example is when there is no CA at all. The server<i> www.example.com</i> is a low-budget one and wants to avoid paying any commercial CA. If it has DNSSEC set up then it just advertises its key on the DNS and clients can verify its certificate using the DNSSEC signature. That is the trust is moved from the commercial CAs to the DNS administrators. Whether they can cope with that, will be seen in time.<br />
<br />
Even though the whole idea is attractive, the actual protocol is (IMO) quite bloated. On a recent post in the <a href="http://permalink.gmane.org/gmane.ietf.dane/206">DANE mailing list</a> I summarized several issues (note that I was wrong on the first). The most important I believe is the fact that DANE separates the certificates to CA signed certificates and to self-signed certificates. That is if you have a CA signed certificate you mark it in the DNS entry as 1, while if you have a self signed one you mark it as 3. The reasoning behind this is unclear but it's effect is that it is harder to move from the CA signed to non-CA signed world or vice-versa. That is if you have a CA signed certificate and it expires, the DANE entry automatically becomes invalid as well. This may be considered a good property for some (especially the CAs), but I see no much point in that. It is also impossible for the server administrator to know whether a client trusts its CA, thus this certificate distinction doesn't always make sense. A work-around is to always have your certificates marked as self-signed and CA signed in two different DNS entries.<br />
<br />
Despite this and few other shortcomings that I worry of, this is the best protocol we have so far to divide the trust for TLS certificates verification to more entities than the commercial CAs. For this reason, a companion library implementing DANE will be included in the upcoming GnuTLS 3.1.3 release.<br />
<br />Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com2tag:blogger.com,1999:blog-1625673575821156689.post-5566903962902270132012-08-16T19:34:00.000+02:002013-07-02T15:52:54.069+02:00Using the Trusted Platform Module to protect your keysThere was a big hype when the <a href="http://en.wikipedia.org/wiki/Trusted_Platform_Module">Trusted Platform Module (TPM)</a> was introduced into computers. Briefly it is a co-processor in your PC that allows it to perform calculations independently of the main processor. This has good and bad side-effects. In this post we focus on the good ones, which are the fact that you can use it to perform cryptographic operations the same way as in a smart-card. What does that mean? It simply means that you can have RSA keys in your TPM chip that you can use them to sign and/or decrypt but you cannot extract them. That way a compromised web server doesn't necessarily mean a compromised private key.<br />
<br />
GnuTLS 3.1.0 (when compiled with libtrousers) adds support for keys stored in the TPM chip. This support is transparent, and such keys can be used similarly to keys stored in files. What is required is that TPM keys are specified using a URI of the following forms.<br />
<br />
<pre>tpmkey:uuid=c0208efa-8fe3-431a-9e0b-b8923bb0cdc4;storage=system
tpmkey:file=/path/to/the/tpmkey</pre>
<pre></pre>
<br />
The first URI contains a UUID which is an identifier of the key, and the storage area of the chip (TPM allows for system and user keys). The latter URI is used for TPM keys that are stored outside the TPM storage area, i.e., in an (encrypted by the TPM) file.<br />
<br />
Let's see how we can generate a TPM key, and use it for TLS authentication. We'll need to generate a key and the corresponding certificate. The following command generates a key which will be stored in the TPM's user section.<br />
<br />
<pre>$ tpmtool --generate-rsa --bits 2048 --register --user</pre>
<pre></pre>
<br />
The output of the command is the key ID.
<br />
<br />
<pre>tpmkey:uuid=58ad734b-bde6-45c7-89d8-756a55ad1891;storage=user
</pre>
<br />
So now that we have the ID of the key, let's extract the public key from it.<br />
<br />
<pre>$ tpmtool --pubkey "tpmkey:uuid=58ad734b-bde6-45c7-89d8-756a55ad1891;storage=user" --outfile=pubkey.pem
</pre>
<br />
And given the public key we can easily generate a certificate using the following command.
<br />
<pre>$ certtool --generate-certificate --outfile cert.pem --load-privkey "tpmkey:uuid=58ad734b-bde6-45c7-89d8-756a55ad1891;storage=user" --load-pubkey pubkey.pem --load-ca-certificate ca-cert.pem --load-ca-privkey ca-key.pem
</pre>
<br />
The generated certificate can now be used with any program using the gnutls library, such as gnutls-cli to connect to a server. For example:<br />
<pre>$ gnutls-cli --x509keyfile "tpmkey:uuid=58ad734b-bde6-45c7-89d8-756a55ad1891;storage=user" --x509certfile cert.pem -p 443 my_host.name
</pre>
<br />
An easy to notice issue with TPM keys is that they are not mnemonic. There is only an UUID identifying the key, but no labels making the distinction of multiple keys a troublesome task. Nevertheless, TPM keys provide a cheap way to protect keys used in your system.<br />
<br />
<br />Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com4tag:blogger.com,1999:blog-1625673575821156689.post-38445877416308280492012-04-18T12:46:00.002+02:002016-01-11T11:16:37.683+01:00A flaw in the smart card Kerberos (PKINIT) protocolReading security protocols is not always fun nor easy. Protocols like public key Kerberos are hard to read because they just define the packet format and expect the reader to assume a correct message sequence. I read it, nevertheless, because I was interested on the protocol's interaction with smart cards. If you are not aware of the protocol, public key Kerberos or PKINIT is the protocol used in Microsoft Active Directory and described in <a href="http://www.ietf.org/rfc/rfc4556.txt">RFC4556</a>.<br />
<br />
The idea of the protocol is to extend the traditional Kerberos, that supports only symmetric ciphers, with digital signatures and public key encryption in order to support stock smart cards. A use-case is, for example, logging in a windows domain using the smart card. The protocol itself doesn't mention smart cards at all, probably because it was thought as a deployment issue. Nevertheless, it was believed to be a secure protocol and several published papers provided proofs of security for all operational modes of the protocol.<br />
<br />
However, the protocol has an important flaw. A flaw that makes it insecure if used with smart cards. I wrote a detailed <a href="http://www.cosic.esat.kuleuven.be/publications/article-2188.pdf">report on the flaw</a>, but the main idea is that if one has access for few minutes to your smart card he can login using your credentials at any time in the future. You may think that an attack like that can be prevented by never lending your smart card to anyone, but how can you prove that no-one borrowed it for a while? Or if you believe the smart card PIN would protect from theft, how could you know that the reader you are inserting your card isn't tampered? And in a protocol with smart cards you'd expect the tampered reader not to be able to use the card after you retrieve it. This is not the case, making the protocol unsuitable for smart cards, its primary use-case.<br />
<br />
<br />
What is the most interesting issue however, are the security proofs. The protocol was proven secure, but because the protocol never mentioned smart cards, researchers proved its security on a different setting than the actual use cases. So when reading a security proof, always check the assumptions, which are as important as the proof itself.<br />
<br />
Few things went bad with the design of this protocol, none of which is actually technical. The protocol is hard to read, and in order to get an overview of it, you have to read the whole RFC. This is just <b>bad</b>. If you check figure 1 in the <a href="http://www.ietf.org/rfc/rfc5246.txt">TLS RFC</a> you get an overview of the protocol immediately. You might not know the actual contents of the messages but the sequence is apparent. This is not possible in the Kerberos protocol, and that discourages anyone who might want to understand the protocol using a high level description of it. Another flaw, is that the protocol doesn't mention smart cards, its primary use-case. Smart cards were treated as a deployment issue and readers of the RFC, would never know about it. The latter issue is occurring in many of the IETF protocols and the readers are expected to know where and how this protocol is used. As it was demonstrated by the security proofs on a different setting, this is not the case.<br />
<br />
So, what can it be done to mitigate the flaw? Unfortunately without modifying the protocol, the only advice that can be given is something along the:<br />
<ul>
<li>make sure you <b>always</b> possess the card; </li>
<li>make sure you <b>never</b> use a tampered smart card reader.</li>
</ul>
Which may seem pretty useless in a typical working environment. What makes the attack nasty, is that if an adversary tampers your reader, and you use your card with it now, the adversary can perform a transaction a year later when you'll have no clue on what happened and might be no evidence of the tampered reader.<br />
<br />Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com0tag:blogger.com,1999:blog-1625673575821156689.post-85743944876588380272012-04-01T20:21:00.000+02:002012-12-05T11:48:09.568+01:00TLS in embedded systemsIn some embedded systems space may often be a serious constraint. However, there are many such systems that contain several megabytes of flash either as an SD memory card, or as raw NAND, having no real space constraint. For those systems using a TLS implementation such as GnuTLS or OpenSSL would provide performance gains that are not possible with the smaller implementations that target small size. That is because both of the above implementations, unlike the constraint ones, support <a href="http://home.gna.org/cryptodev-linux/">cryptodev-linux</a> to take advantage of cryptographic accelerators, widely present in several constraint CPUs, and support elliptic curves to optimize performance when perfect forward secrecy is required.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKaUsHMU7SFZijXaGnLVxIDXrnBNX38mymIHA3ryDBf7cTu5ltGvOPrELUN8VDz2oFRObarV0yOtNxydNpOkryc-N8VvQfvDE06ba7cDdRqzZk9e6HiyF8SwHmstxpVuaWScclgdt5O_gb/s1600/aes-cbc.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKaUsHMU7SFZijXaGnLVxIDXrnBNX38mymIHA3ryDBf7cTu5ltGvOPrELUN8VDz2oFRObarV0yOtNxydNpOkryc-N8VvQfvDE06ba7cDdRqzZk9e6HiyF8SwHmstxpVuaWScclgdt5O_gb/s320/aes-cbc.png" width="320" /></a>I happened to have an old geode (x86 compatible) CPU which contained an AES accelerator, so here are some benchmarks created using the <a href="https://bitbucket.org/yarosla/nxweb/wiki/Home">nxweb</a>/GnuTLS and <a href="http://nginx.org/">nginx</a>/OpenSSL web servers and the <a href="https://bitbucket.org/yarosla/httpress/wiki/Home">httpress</a> utility. The figure on the right shows the data transferred per second using AES in CBC mode, with the cryptographic accelerator compared to GnuTLS' and OpenSSL's software implementations. We can clearly see that download speed almost doubles on a big file transfer when using the accelerator.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJFHY6MZ10j5-FHQy2Md65Q-rURHe5JtAtUxERZdvSWUflW7jYvloafm-bZQQmy-wwIxgvHjoYhQubicGL06NMZqxxBGYfr2t7OapaaZRHYU-9v6uyvGWWxXtBoxsghhL1SHd0IW-JC8lJ/s1600/kx-1776.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJFHY6MZ10j5-FHQy2Md65Q-rURHe5JtAtUxERZdvSWUflW7jYvloafm-bZQQmy-wwIxgvHjoYhQubicGL06NMZqxxBGYfr2t7OapaaZRHYU-9v6uyvGWWxXtBoxsghhL1SHd0IW-JC8lJ/s320/kx-1776.png" width="320" /></a>The figure on the left shows a comparison of the various key exchange methods in this platform using GnuTLS and OpenSSL. The benchmark measures HTTPS transactions per second and the keys and parameters used are the same for both implementations. The key sizes are selected of equivalent security levels (1776 bits in RSA and DH are equivalent to 192 bits in ECDH according to ECRYPT II recommendations). We can see that the elliptic curve version of Diffie Hellman (ECDHE-RSA) allows 25% more transactions in both implementations comparing to the Diffie-Hellman on a prime field (DHE-RSA). The plain RSA key exchange remains the fastest, at the cost of sacrificing perfect forward secrecy.</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
As a side-note it is nice to see that at the security level of 192 bits GnuTLS outperforms OpenSSL on this processor. The trend continues on higher security levels for the RSA and DHE-RSA methods but the ECDHE-RSA method is interesting since even though OpenSSL has a more efficient elliptic curve implementation. GnuTLS' usage of <a href="http://www.lysator.liu.se/%7Enisse/nettle/">nettle</a> and <a href="http://gmplib.org/">GMP</a> (which provide a faster RSA implementation) compensates, and their performance is almost identical.<br />
<br />
Overall, in the few embedded systems that I've worked on, space was not a crucial limiting factor, and it was mainly this work that drove me into updating cryptodev for linux. In those systems the space cost occurred due to the usage of a larger library was compensated by (1) the off-loading to the crypto processor of operations that would otherwise load the CPU and (2) the reduce in processing time due to elliptic curves.<br />
However this balance is system specific and what was important for my needs would not cover everyone elses, so it is important to weigh the advantages and disadvantages of cryptographic implementations on your system alone.<br />
<br />Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com0tag:blogger.com,1999:blog-1625673575821156689.post-42303014142357236882012-03-18T20:00:00.003+01:002012-04-13T11:45:25.972+02:00Google summer of codeThis year GnuTLS participates in the Google summer of code under the GNU project umbrella. If you are a student willing to spend this summer coding, <a href="http://www.gnu.org/software/gnutls/soc.html">check our ideas</a>.<br />
<br />Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com0tag:blogger.com,1999:blog-1625673575821156689.post-40927099225385794352012-02-18T15:27:00.001+01:002015-12-05T23:08:02.404+01:00The need for SSH-like authentication in TLSAfter the <a href="http://en.wikipedia.org/wiki/DigiNotar">Diginotar CA compromise</a> it is apparent that verifying web sites using only a trusted certificate authority (CA) is not sufficient. Currently a web site's certificate is verified against the CA that issued it and checked for revocation using the OCSP server the CA set up. If the CA is trusted by the user, this process protects against man-in-the-middle attacks when visiting such a web-site, and also against leakage of the web-sites private key (e.g. via OCSP as long as the leakage is reported to the CA). This is an automatic process that does not require the user to be involved, but it comes at a cost. There is a single channel for verification, the CA.<br />
<br />
The certificate based web-site verification tries to convert the trust we have in a merchant to the digital world. That is currently done by having "few" authorities that provide certificates to the merchants and based on those certificates we should base our decisions. However, trust in trade requires more than that. For example wouldn't it raise suspicions, a laptop from a merchant who approached you in a parking lot and provided you with a legitimate looking brand card? Would his business or credentials card be the only thing to check? Those heuristics are unfortunately not currently available in the digital world.<br />
<br />
If it wasn't for the Chrome browser that implemented a preliminary version of <a href="http://tools.ietf.org/html/draft-ietf-websec-key-pinning-01">key pinning</a>, the Diginotar compromise might not have been uncovered. In the maliciously-issued certificates, the automatic verification procedure was not reporting any problems. It was the change in public key that triggered the key pinning warning and eventually to the Diginotar issue becoming public. Thus having an additional verification channel to standard PKI proved to be a success.<br />
<br />
Key pinning, as of the 01 draft, is mostly server driven. That is, the user has very little control on trusting a particular server key if the server operator doesn't ask to. Another approach is the SSH programs' typical authentication method. The trust on first use. That describes the concept where the public key of the peer is not verified, or verified out-of-bound, but subsequent connections to the same peer require the public key to remain the same. That approach has the advantage that doesn't depend on the server operator setting up anything, but also the disadvantage that the user will be bugged every time the server changes its public key.<br />
<br />
In any case having such methods to complement standard certificate verification and revocation checks, provides an additional layer of security. With such a layer, a CA compromise would not be enough for a large-scale man-in-the-middle attack since changes in the public keys would be detected and users would be warned. Such warnings might not be entirely successful in preventing all users from continuing but would raise suspicions for the legitimacy of the server, which might be enough.<br />
<br />
For that, we implemented in GnuTLS a framework to be used either by applications that want to use key pinning, or a trust on first use (TOFU) authentication. That consists of three helper functions that store and verify the public keys. They can be seen <a href="http://www.gnutls.org/manual/html_node/Verifying-a-certificate-using-trust-on-first-use-authentication.html#Verifying-a-certificate-using-trust-on-first-use-authentication">in the GnuTLS manual</a>. The included program gnutls-cli has also been modified to support a hybrid authentication that includes certificate authentication, TOFU and OCSP if the --tofu and --ocsp arguments are specified. The main idea of its operation is the idea discussed here and is shown in <a href="http://www.gnutls.org/manual/html_node/Simple-client-example-with-SSH_002dstyle-certificate-verification.html#Simple-client-example-with-SSH_002dstyle-certificate-verification">this example code at the manual</a>.<br />
<br />
<br />
<br />Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com4tag:blogger.com,1999:blog-1625673575821156689.post-16198018836582899742012-01-01T23:25:00.000+01:002013-12-31T09:44:27.226+01:00Do we need elliptic curve point compression?GnuTLS has recently added support for elliptic curves (ECDSA and Elliptic curve Diffie-Hellman). Elliptic curves are an improvement on public key technologies, mostly in efficiency because they require operations with much smaller integers for equivalent security parameters to RSA or DH. For example a 1248-bit RSA key corresponds to an 160-bit ECDSA key, saving both in space required to store parameters and in time spent for calculations.<br />
<br />
However elliptic curve technology is considered a patent minefield and quite some attempts have been made to clarify the status, e.g. IETF made an attempt with <a href="http://tools.ietf.org/html/rfc6090">RFC6090</a> to describe only the fundamental algorithms on which all patents are known to have expired. The GnuTLS implementation of ECC is based on this document.<br />
<br />
One of the interesting "improvements" that is not included in the fundamental algorithms, and is still patented is <i>point compression</i>. To describe it we need a small (but not detailed) introduction to elliptic curves. An elliptic curve (at least for the needs of TLS protocol) is a set of points (x,y) that satisfy the following relation modulo a large prime p.<br />
<div style="text-align: center;">
<div>
<br /></div>
</div>
<div style="text-align: center;">
y<sup>2</sup> = x<sup>3</sup> + ax + b</div>
<br />
This set of points has some properties, i.e., a group law allowing point addition, scalar multiplication etc. Without getting into details those points need to be exchanged during a protocol run and given that the points usually belong to a "large" prime field (e.g. 256-bits), reducing the exchanged bytes is an improvement. Point compression achieves that goal, so let's see how.<br />
<br />
Say we have a point (x<sub>0</sub>,y<sub>0</sub>) satisfying y<sub>0</sub><sup>2</sup> = x<sub>0</sub><sup>3</sup> + ax<sub>0</sub> + b. If x<sub>0</sub> is known, then the previous relation becomes a second degree polynomial, that has two solutions.<br />
<br />
<center>
<span style="font-size: larger; white-space: nowrap;"><br />
y<sub>1,2</sub> = ±√<span style="text-decoration: overline;"> x<sup>3</sup> + ax + b </span><br />
</span><br />
</center>
<br />
And surprisingly that's all about point compression. Instead of sending the tuple (x<sub>0</sub>,y<sub>0</sub>), only x<sub>0</sub> and a bit identifying the sign of y is sent. The receiver only needs to calculate y<sub>1,2</sub> and then select the appropriate using the sign bit. Of course calculating square roots modulo a prime isn't as simple as in our example, but the idea is similar.<br />
<br />
So is this worthwhile? Are implementations like GnuTLS that don't infringe this patent in a disadvantage? While it is a clever idea, it doesn't really add much value in real-world protocols. A 256-bit curve has points of around 32 bytes. Thus the bytes saved per TLS handshake are 64 bytes overall. Such handshake typically contains data of several kilobytes, and saving few bytes isn't going to make a dramatic difference. It wouldn't be a top priority addition even if it wasn't a patented method.Nikos Mavrogiannopouloshttp://www.blogger.com/profile/17554156755141404866noreply@blogger.com4