TLS Client NSS: Rely on NSS 3.14 cipher suite defaults
Older versions needed application code to actually enable strong ciphers, but this changed in version 3.14.
This commit is contained in:
parent
c861995515
commit
04d4055034
4 changed files with 21 additions and 76 deletions
|
@ -768,8 +768,13 @@
|
|||
<title>Implementing TLS Clients With NSS</title>
|
||||
<para>
|
||||
The following code shows how to implement a simple TLS client
|
||||
using NSS. Note that the error handling needs replacing
|
||||
before production use.
|
||||
using NSS. These instructions apply to NSS version 3.14 and
|
||||
later. Versions before 3.14 need different initialization
|
||||
code.
|
||||
</para>
|
||||
<para>
|
||||
Keep in mind that the error handling needs to be improved
|
||||
before the code can be used in production.
|
||||
</para>
|
||||
<para>
|
||||
Using NSS needs several header files, as shown in
|
||||
|
@ -781,17 +786,13 @@
|
|||
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
||||
</example>
|
||||
<para>
|
||||
Initializing the NSS library is a complex task (<xref
|
||||
linkend="ex-Defensive_Coding-TLS-NSS-Init"/>). It is not
|
||||
thread-safe. By default, the library is in export mode, and
|
||||
all strong ciphers are disabled. Therefore, after creating
|
||||
the <literal>NSSInitCContext</literal> object, we probe all
|
||||
the strong ciphers we want to use, and check if at least one
|
||||
of them is available. If not, we call
|
||||
<function>NSS_SetDomesticPolicy</function> to switch to
|
||||
unrestricted policy mode. This function replaces the existing
|
||||
global cipher suite policy, that is why we avoid calling it
|
||||
unless absolutely necessary.
|
||||
Initializing the NSS library is shown in <xref
|
||||
linkend="ex-Defensive_Coding-TLS-NSS-Init"/>. This
|
||||
initialization procedure overrides global state. We only call
|
||||
<function>NSS_SetDomesticPolicy</function> if there are no
|
||||
strong ciphers available, assuming that it has already been
|
||||
called otherwise. This avoids overriding the process-wide
|
||||
cipher suite policy unnecessarily.
|
||||
</para>
|
||||
<para>
|
||||
The simplest way to configured the trusted root certificates
|
||||
|
@ -825,11 +826,7 @@
|
|||
function is de-facto part of the NSS public ABI, so it will
|
||||
not go away.) Creating the TLS-capable file descriptor
|
||||
requires a <emphasis>model</emphasis> descriptor, which is
|
||||
configured with the desired set of protocols and ciphers.
|
||||
(The <literal>good_ciphers</literal> variable is part of <xref
|
||||
linkend="ex-Defensive_Coding-TLS-NSS-Init"/>.) We cannot
|
||||
resort to disabling ciphers not on a whitelist because by
|
||||
default, the AES cipher suites are disabled. The model
|
||||
configured with the desired set of protocols. The model
|
||||
descriptor is not needed anymore after TLS support has been
|
||||
activated for the existing connection descriptor.
|
||||
</para>
|
||||
|
|
|
@ -39,32 +39,6 @@ sockfd = -1; // Has been taken over by NSPR.
|
|||
exit(1);
|
||||
}
|
||||
|
||||
// Disable all ciphers (except RC4-based ciphers, for backwards
|
||||
// compatibility).
|
||||
const PRUint16 *const ciphers = SSL_GetImplementedCiphers();
|
||||
for (unsigned i = 0; i < SSL_GetNumImplementedCiphers(); i++) {
|
||||
if (ciphers[i] != SSL_RSA_WITH_RC4_128_SHA
|
||||
&& ciphers[i] != SSL_RSA_WITH_RC4_128_MD5) {
|
||||
if (SSL_CipherPrefSet(model, ciphers[i], PR_FALSE) != SECSuccess) {
|
||||
const PRErrorCode err = PR_GetError();
|
||||
fprintf(stderr, "error: disable cipher %u: error %d: %s\n",
|
||||
(unsigned)ciphers[i], err, PR_ErrorToName(err));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Enable the strong ciphers.
|
||||
for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL;
|
||||
++p) {
|
||||
if (SSL_CipherPrefSet(model, *p, PR_TRUE) != SECSuccess) {
|
||||
const PRErrorCode err = PR_GetError();
|
||||
fprintf(stderr, "error: enable cipher %u: error %d: %s\n",
|
||||
(unsigned)*p, err, PR_ErrorToName(err));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Allow overriding invalid certificate.
|
||||
if (SSL_BadCertHook(model, bad_certificate, (char *)host) != SECSuccess) {
|
||||
const PRErrorCode err = PR_GetError();
|
||||
|
|
|
@ -23,9 +23,9 @@ static const PRUint16 good_ciphers[] = {
|
|||
};
|
||||
|
||||
// Check if the current policy allows any strong ciphers. If it
|
||||
// doesn't, switch to the "domestic" (unrestricted) policy. This is
|
||||
// not thread-safe and has global impact. Consequently, we only do
|
||||
// it if absolutely necessary.
|
||||
// doesn't, set the cipher suite policy. This is not thread-safe
|
||||
// and has global impact. Consequently, we only do it if absolutely
|
||||
// necessary.
|
||||
int found_good_cipher = 0;
|
||||
for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL;
|
||||
++p) {
|
||||
|
|
|
@ -114,9 +114,9 @@ main(int argc, char **argv)
|
|||
};
|
||||
|
||||
// Check if the current policy allows any strong ciphers. If it
|
||||
// doesn't, switch to the "domestic" (unrestricted) policy. This is
|
||||
// not thread-safe and has global impact. Consequently, we only do
|
||||
// it if absolutely necessary.
|
||||
// doesn't, set the cipher suite policy. This is not thread-safe
|
||||
// and has global impact. Consequently, we only do it if absolutely
|
||||
// necessary.
|
||||
int found_good_cipher = 0;
|
||||
for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL;
|
||||
++p) {
|
||||
|
@ -190,32 +190,6 @@ main(int argc, char **argv)
|
|||
exit(1);
|
||||
}
|
||||
|
||||
// Disable all ciphers (except RC4-based ciphers, for backwards
|
||||
// compatibility).
|
||||
const PRUint16 *const ciphers = SSL_GetImplementedCiphers();
|
||||
for (unsigned i = 0; i < SSL_GetNumImplementedCiphers(); i++) {
|
||||
if (ciphers[i] != SSL_RSA_WITH_RC4_128_SHA
|
||||
&& ciphers[i] != SSL_RSA_WITH_RC4_128_MD5) {
|
||||
if (SSL_CipherPrefSet(model, ciphers[i], PR_FALSE) != SECSuccess) {
|
||||
const PRErrorCode err = PR_GetError();
|
||||
fprintf(stderr, "error: disable cipher %u: error %d: %s\n",
|
||||
(unsigned)ciphers[i], err, PR_ErrorToName(err));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Enable the strong ciphers.
|
||||
for (const PRUint16 *p = good_ciphers; *p != SSL_NULL_WITH_NULL_NULL;
|
||||
++p) {
|
||||
if (SSL_CipherPrefSet(model, *p, PR_TRUE) != SECSuccess) {
|
||||
const PRErrorCode err = PR_GetError();
|
||||
fprintf(stderr, "error: enable cipher %u: error %d: %s\n",
|
||||
(unsigned)*p, err, PR_ErrorToName(err));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Allow overriding invalid certificate.
|
||||
if (SSL_BadCertHook(model, bad_certificate, (char *)host) != SECSuccess) {
|
||||
const PRErrorCode err = PR_GetError();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue