1 diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c 2 --- a/nss/lib/ssl/ssl3con.c 2014-01-17 18:45:24.378132013 -0800 3 +++ b/nss/lib/ssl/ssl3con.c 2014-01-17 18:46:29.929216162 -0800 4 @@ -12540,6 +12540,46 @@ ssl3_CipherPrefGet(sslSocket *ss, ssl3Ci 5 return rv; 6 } 7 8 +SECStatus 9 +ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *ciphers, unsigned int len) 10 +{ 11 + /* |i| iterates over |ciphers| while |done| and |j| iterate over 12 + * |ss->cipherSuites|. */ 13 + unsigned int i, done; 14 + 15 + for (i = done = 0; i < len; i++) { 16 + PRUint16 id = ciphers[i]; 17 + unsigned int existingIndex, j; 18 + PRBool found = PR_FALSE; 19 + 20 + for (j = done; j < ssl_V3_SUITES_IMPLEMENTED; j++) { 21 + if (ss->cipherSuites[j].cipher_suite == id) { 22 + existingIndex = j; 23 + found = PR_TRUE; 24 + break; 25 + } 26 + } 27 + 28 + if (!found) { 29 + continue; 30 + } 31 + 32 + if (existingIndex != done) { 33 + const ssl3CipherSuiteCfg temp = ss->cipherSuites[done]; 34 + ss->cipherSuites[done] = ss->cipherSuites[existingIndex]; 35 + ss->cipherSuites[existingIndex] = temp; 36 + } 37 + done++; 38 + } 39 + 40 + /* Disable all cipher suites that weren't included. */ 41 + for (; done < ssl_V3_SUITES_IMPLEMENTED; done++) { 42 + ss->cipherSuites[done].enabled = 0; 43 + } 44 + 45 + return SECSuccess; 46 +} 47 + 48 /* copy global default policy into socket. */ 49 void 50 ssl3_InitSocketPolicy(sslSocket *ss) 51 diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h 52 --- a/nss/lib/ssl/ssl.h 2014-01-17 18:45:24.378132013 -0800 53 +++ b/nss/lib/ssl/ssl.h 2014-01-17 18:46:29.929216162 -0800 54 @@ -285,6 +285,13 @@ SSL_IMPORT SECStatus SSL_CipherPrefGetDe 55 SSL_IMPORT SECStatus SSL_CipherPolicySet(PRInt32 cipher, PRInt32 policy); 56 SSL_IMPORT SECStatus SSL_CipherPolicyGet(PRInt32 cipher, PRInt32 *policy); 57 58 +/* SSL_CipherOrderSet sets the cipher suite preference order from |ciphers|, 59 + * which must be an array of cipher suite ids of length |len|. All the given 60 + * cipher suite ids must appear in the array that is returned by 61 + * |SSL_GetImplementedCiphers| and may only appear once, at most. */ 62 +SSL_IMPORT SECStatus SSL_CipherOrderSet(PRFileDesc *fd, const PRUint16 *ciphers, 63 + unsigned int len); 64 + 65 /* SSLChannelBindingType enumerates the types of supported channel binding 66 * values. See RFC 5929. */ 67 typedef enum SSLChannelBindingType { 68 diff -pu a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h 69 --- a/nss/lib/ssl/sslimpl.h 2014-01-17 18:45:24.378132013 -0800 70 +++ b/nss/lib/ssl/sslimpl.h 2014-01-17 18:46:29.929216162 -0800 71 @@ -1743,6 +1743,8 @@ extern SECStatus ssl3_CipherPrefSet(sslS 72 extern SECStatus ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *on); 73 extern SECStatus ssl2_CipherPrefSet(sslSocket *ss, PRInt32 which, PRBool enabled); 74 extern SECStatus ssl2_CipherPrefGet(sslSocket *ss, PRInt32 which, PRBool *enabled); 75 +extern SECStatus ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *cipher, 76 + unsigned int len); 77 78 extern SECStatus ssl3_SetPolicy(ssl3CipherSuite which, PRInt32 policy); 79 extern SECStatus ssl3_GetPolicy(ssl3CipherSuite which, PRInt32 *policy); 80 diff -pu a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c 81 --- a/nss/lib/ssl/sslsock.c 2014-01-17 18:45:24.378132013 -0800 82 +++ b/nss/lib/ssl/sslsock.c 2014-01-17 18:46:29.929216162 -0800 83 @@ -1278,6 +1278,19 @@ SSL_CipherPrefSet(PRFileDesc *fd, PRInt3 84 return rv; 85 } 86 87 +SECStatus 88 +SSL_CipherOrderSet(PRFileDesc *fd, const PRUint16 *ciphers, unsigned int len) 89 +{ 90 + sslSocket *ss = ssl_FindSocket(fd); 91 + 92 + if (!ss) { 93 + SSL_DBG(("%d: SSL[%d]: bad socket in CipherOrderSet", SSL_GETPID(), 94 + fd)); 95 + return SECFailure; 96 + } 97 + return ssl3_CipherOrderSet(ss, ciphers, len); 98 +} 99 + 100 SECStatus 101 SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled) 102 { 103