blob: 16d4745dcd810f84816652f77f3197fab79c4cdf [file] [log] [blame]
diff --git a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h
index 4cf02aa..24627ed 100644
--- a/nss/lib/ssl/ssl.h
+++ b/nss/lib/ssl/ssl.h
@@ -265,6 +265,13 @@ SSL_IMPORT SECStatus SSL_CipherPrefGetDefault(PRInt32 cipher, PRBool *enabled);
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 --git a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
index c2d9eeb..350d09c 100644
--- a/nss/lib/ssl/ssl3con.c
+++ b/nss/lib/ssl/ssl3con.c
@@ -12423,6 +12423,46 @@ ssl3_CipherPrefGet(sslSocket *ss, ssl3CipherSuite which, PRBool *enabled)
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 --git a/nss/lib/ssl/sslimpl.h b/nss/lib/ssl/sslimpl.h
index 1e4655f..7521dba 100644
--- a/nss/lib/ssl/sslimpl.h
+++ b/nss/lib/ssl/sslimpl.h
@@ -1711,6 +1711,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/nss/lib/ssl/sslsock.c b/nss/lib/ssl/sslsock.c
index 965215d..9f8286c 100644
--- a/nss/lib/ssl/sslsock.c
+++ b/nss/lib/ssl/sslsock.c
@@ -1344,6 +1344,19 @@ SSL_CipherPrefSet(PRFileDesc *fd, PRInt32 which, PRBool enabled)
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)
{