From 04d4055034bcf5be28bd0cdbb92b3bfbd808fd2d Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Tue, 2 Apr 2013 17:12:57 +0200 Subject: [PATCH] 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. --- defensive-coding/en-US/Features/TLS.xml | 33 +++++++++---------- .../snippets/TLS-Client-NSS-Connect.xml | 26 --------------- .../en-US/Features/snippets/TLS-NSS-Init.xml | 6 ++-- defensive-coding/src/TLS-Client-NSS.c | 32 ++---------------- 4 files changed, 21 insertions(+), 76 deletions(-) diff --git a/defensive-coding/en-US/Features/TLS.xml b/defensive-coding/en-US/Features/TLS.xml index a0432f5..753da69 100644 --- a/defensive-coding/en-US/Features/TLS.xml +++ b/defensive-coding/en-US/Features/TLS.xml @@ -768,8 +768,13 @@ Implementing TLS Clients With NSS 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. + + + Keep in mind that the error handling needs to be improved + before the code can be used in production. Using NSS needs several header files, as shown in @@ -781,17 +786,13 @@ xmlns:xi="http://www.w3.org/2001/XInclude" /> - Initializing the NSS library is a complex task (). It is not - thread-safe. By default, the library is in export mode, and - all strong ciphers are disabled. Therefore, after creating - the NSSInitCContext 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 - NSS_SetDomesticPolicy 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 . This + initialization procedure overrides global state. We only call + NSS_SetDomesticPolicy 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. 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 model descriptor, which is - configured with the desired set of protocols and ciphers. - (The good_ciphers variable is part of .) 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. diff --git a/defensive-coding/en-US/Features/snippets/TLS-Client-NSS-Connect.xml b/defensive-coding/en-US/Features/snippets/TLS-Client-NSS-Connect.xml index 692ad04..1a6821e 100644 --- a/defensive-coding/en-US/Features/snippets/TLS-Client-NSS-Connect.xml +++ b/defensive-coding/en-US/Features/snippets/TLS-Client-NSS-Connect.xml @@ -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(); diff --git a/defensive-coding/en-US/Features/snippets/TLS-NSS-Init.xml b/defensive-coding/en-US/Features/snippets/TLS-NSS-Init.xml index d56651b..6352282 100644 --- a/defensive-coding/en-US/Features/snippets/TLS-NSS-Init.xml +++ b/defensive-coding/en-US/Features/snippets/TLS-NSS-Init.xml @@ -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) { diff --git a/defensive-coding/src/TLS-Client-NSS.c b/defensive-coding/src/TLS-Client-NSS.c index de9e6db..3faac5c 100644 --- a/defensive-coding/src/TLS-Client-NSS.c +++ b/defensive-coding/src/TLS-Client-NSS.c @@ -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();