diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h
index db09425..437a822 100644
--- a/lib/ssl/ssl.h
+++ b/lib/ssl/ssl.h
@@ -387,6 +387,13 @@ SSL_IMPORT SECStatus SSL_DHEGroupPrefSet(PRFileDesc *fd,
 */
 SSL_IMPORT SECStatus SSL_EnableWeakDHEPrimeGroup(PRFileDesc *fd, PRBool enabled);
 
+/* 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 --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
index 5c09f25..572bba9 100644
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
@@ -13390,6 +13390,46 @@ SSL_SignatureMaxCount() {
     return MAX_SIGNATURE_ALGORITHMS;
 }
 
+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 --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
index 080debe..3403091 100644
--- a/lib/ssl/sslimpl.h
+++ b/lib/ssl/sslimpl.h
@@ -1786,6 +1786,8 @@ extern SECStatus ssl3_CipherPrefSet(sslSocket *ss, ssl3CipherSuite which, PRBool
 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 --git a/lib/ssl/sslsock.c b/lib/ssl/sslsock.c
index 28e3543..8ad1517 100644
--- a/lib/ssl/sslsock.c
+++ b/lib/ssl/sslsock.c
@@ -1369,6 +1369,19 @@ SSL_CipherPrefSet(PRFileDesc *fd, PRInt32 which, PRBool enabled)
 }
 
 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)
 {
     SECStatus  rv;