| diff --git a/lib/ssl/ssl.h b/lib/ssl/ssl.h |
| index 3550580..70665a1 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 d7d186a..b100b9b 100644 |
| --- a/lib/ssl/ssl3con.c |
| +++ b/lib/ssl/ssl3con.c |
| @@ -13797,6 +13797,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 c0e3a0b..f56ab53 100644 |
| --- a/lib/ssl/sslimpl.h |
| +++ b/lib/ssl/sslimpl.h |
| @@ -1835,6 +1835,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 e312d82..e82c916 100644 |
| --- a/lib/ssl/sslsock.c |
| +++ b/lib/ssl/sslsock.c |
| @@ -1500,6 +1500,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; |