diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c --- a/nss/lib/ssl/ssl3con.c 2014-01-17 18:45:24.378132013 -0800 +++ b/nss/lib/ssl/ssl3con.c 2014-01-17 18:46:29.929216162 -0800 @@ -12540,6 +12540,46 @@ ssl3_CipherPrefGet(sslSocket *ss, ssl3Ci return rv; } +SECStatus +ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *ciphers, unsigned int len) +{ + /* |i| iterates over |ciphers| while |done| and |j| iterate over + * |ss->cipherSuites|. */ + unsigned int i, done; + + for (i = done = 0; i < len; i++) { + PRUint16 id = ciphers[i]; + unsigned int existingIndex, j; + PRBool found = PR_FALSE; + + for (j = done; j < ssl_V3_SUITES_IMPLEMENTED; j++) { + if (ss->cipherSuites[j].cipher_suite == id) { + existingIndex = j; + found = PR_TRUE; + break; + } + } + + if (!found) { + continue; + } + + if (existingIndex != done) { + const ssl3CipherSuiteCfg temp = ss->cipherSuites[done]; + ss->cipherSuites[done] = ss->cipherSuites[existingIndex]; + ss->cipherSuites[existingIndex] = temp; + } + done++; + } + + /* Disable all cipher suites that weren't included. */ + for (; done < ssl_V3_SUITES_IMPLEMENTED; done++) { + ss->cipherSuites[done].enabled = 0; + } + + return SECSuccess; +} + /* copy global default policy into socket. */ void ssl3_InitSocketPolicy(sslSocket *ss) diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h --- a/nss/lib/ssl/ssl.h 2014-01-17 18:45:24.378132013 -0800 +++ b/nss/lib/ssl/ssl.h 2014-01-17 18:46:29.929216162 -0800 @@ -285,6 +285,13 @@ SSL_IMPORT SECStatus SSL_CipherPrefGetDe SSL_IMPORT SECStatus SSL_CipherPolicySet(PRInt32 cipher, PRInt32 policy); SSL_IMPORT SECStatus SSL_CipherPolicyGet(PRInt32 cipher, PRInt32 *policy); +/* SSL_CipherOrderSet sets the cipher suite preference order from |ciphers|, + * which must be an array of cipher suite ids of length |len|. All the given + * cipher suite ids must appear in the array that is returned by + * |SSL_GetImplementedCiphers| and may only appear once, at most. */ +SSL_IMPORT SECStatus SSL_CipherOrderSet(PRFileDesc *fd, const PRUint16 *ciphers, + unsigned int len); + /* SSLChannelBindingType enumerates the types of supported channel binding * values. See RFC 5929. */ typedef enum SSLChannelBindingType { diff -pu a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h --- a/nss/lib/ssl/sslimpl.h 2014-01-17 18:45:24.378132013 -0800 +++ b/nss/lib/ssl/sslimpl.h 2014-01-17 18:46:29.929216162 -0800 @@ -1743,6 +1743,8 @@ extern SECStatus ssl3_CipherPrefSet(sslS extern SECStatus ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *on); extern SECStatus ssl2_CipherPrefSet(sslSocket *ss, PRInt32 which, PRBool enabled); extern SECStatus ssl2_CipherPrefGet(sslSocket *ss, PRInt32 which, PRBool *enabled); +extern SECStatus ssl3_CipherOrderSet(sslSocket *ss, const ssl3CipherSuite *cipher, + unsigned int len); extern SECStatus ssl3_SetPolicy(ssl3CipherSuite which, PRInt32 policy); extern SECStatus ssl3_GetPolicy(ssl3CipherSuite which, PRInt32 *policy); diff -pu a/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c --- a/nss/lib/ssl/sslsock.c 2014-01-17 18:45:24.378132013 -0800 +++ b/nss/lib/ssl/sslsock.c 2014-01-17 18:46:29.929216162 -0800 @@ -1278,6 +1278,19 @@ SSL_CipherPrefSet(PRFileDesc *fd, PRInt3 return rv; } +SECStatus +SSL_CipherOrderSet(PRFileDesc *fd, const PRUint16 *ciphers, unsigned int len) +{ + sslSocket *ss = ssl_FindSocket(fd); + + if (!ss) { + SSL_DBG(("%d: SSL[%d]: bad socket in CipherOrderSet", SSL_GETPID(), + fd)); + return SECFailure; + } + return ssl3_CipherOrderSet(ss, ciphers, len); +} + SECStatus SSL_CipherPrefGet(PRFileDesc *fd, PRInt32 which, PRBool *enabled) {