summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-11 15:20:12 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-11 15:20:12 +0000
commita121c90cf3279e6001d0f91472b74b02699e2976 (patch)
tree691ab98c9033861131d1f2efe3343b93bc53f611
parentc5b97aac8117ffac51a2cf3cc7a1070ab5ff6e93 (diff)
downloadchromium_src-a121c90cf3279e6001d0f91472b74b02699e2976.zip
chromium_src-a121c90cf3279e6001d0f91472b74b02699e2976.tar.gz
chromium_src-a121c90cf3279e6001d0f91472b74b02699e2976.tar.bz2
Update our copy of libssl from NSS CVS.
http://codereview.chromium.org/596013 BUG=none TEST=none git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38773 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--net/third_party/nss/README.google7
-rw-r--r--net/third_party/nss/patches/nextproto.patch483
-rw-r--r--net/third_party/nss/patches/versionskew.patch47
-rw-r--r--net/third_party/nss/ssl/ssl.def13
-rw-r--r--net/third_party/nss/ssl/ssl.h111
-rw-r--r--net/third_party/nss/ssl/ssl3con.c494
-rw-r--r--net/third_party/nss/ssl/ssl3ecc.c6
-rw-r--r--net/third_party/nss/ssl/ssl3ext.c408
-rw-r--r--net/third_party/nss/ssl/ssl3prot.h18
-rw-r--r--net/third_party/nss/ssl/sslcon.c29
-rw-r--r--net/third_party/nss/ssl/sslerr.h5
-rw-r--r--net/third_party/nss/ssl/sslimpl.h50
-rw-r--r--net/third_party/nss/ssl/sslinfo.c42
-rw-r--r--net/third_party/nss/ssl/sslproto.h11
-rw-r--r--net/third_party/nss/ssl/sslreveal.c42
-rw-r--r--net/third_party/nss/ssl/sslsecur.c210
-rw-r--r--net/third_party/nss/ssl/sslsnce.c335
-rw-r--r--net/third_party/nss/ssl/sslsock.c149
-rw-r--r--net/third_party/nss/ssl/sslt.h22
19 files changed, 2167 insertions, 315 deletions
diff --git a/net/third_party/nss/README.google b/net/third_party/nss/README.google
index fa1e35e..d34e65e 100644
--- a/net/third_party/nss/README.google
+++ b/net/third_party/nss/README.google
@@ -1,12 +1,17 @@
This directory includes a copy of NSS's libssl from the CVS repo at:
:pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot
-The snapshot was updated at Wed Dec 2 16:05:49 PST 2009
+The snapshot was updated to the CVS tag: NSS_3_12_6_BETA1
Patches:
* Next protocol negotiation support.
+ patches/nextproto.patch
http://codereview.chromium.org/415005
+ * Commenting out a couple of functions because they need NSS symbols
+ which may not exist in the system NSS library.
+ patches/versionskew.patch
+
The ssl/bodge directory contains files taken from the NSS repo that we required
for building libssl outside of its usual build environment.
diff --git a/net/third_party/nss/patches/nextproto.patch b/net/third_party/nss/patches/nextproto.patch
new file mode 100644
index 0000000..dbca92a
--- /dev/null
+++ b/net/third_party/nss/patches/nextproto.patch
@@ -0,0 +1,483 @@
+diff --git a/mozilla/security/nss/cmd/tstclnt/tstclnt.c b/mozilla/security/nss/cmd/tstclnt/tstclnt.c
+index f0b5701..e795b33 100644
+--- a/mozilla/security/nss/cmd/tstclnt/tstclnt.c
++++ b/mozilla/security/nss/cmd/tstclnt/tstclnt.c
+@@ -863,7 +863,13 @@ int main(int argc, char **argv)
+ SECU_PrintError(progName, "error enabling compression");
+ return 1;
+ }
+-
++
++ rv = SSL_SetNextProtoNego(s, "\004flip\004http1.1", 10);
++ if (rv != SECSuccess) {
++ SECU_PrintError(progName, "error enabling next protocol negotiation");
++ return 1;
++ }
++
+ SSL_SetPKCS11PinArg(s, &pwdata);
+
+ SSL_AuthCertificateHook(s, SSL_AuthCertificate, (void *)handle);
+diff --git a/mozilla/security/nss/lib/ssl/ssl.def b/mozilla/security/nss/lib/ssl/ssl.def
+index a5b2767..287505f 100644
+--- a/mozilla/security/nss/lib/ssl/ssl.def
++++ b/mozilla/security/nss/lib/ssl/ssl.def
+@@ -150,3 +150,10 @@ SSL_SNISocketConfigHook;
+ ;+ local:
+ ;+*;
+ ;+};
++;+NSS_CHROMIUM {
++;+ global:
++SSL_GetNextProto;
++SSL_SetNextProtoNego;
++;+ local:
++;+*;
++;+};
+diff --git a/mozilla/security/nss/lib/ssl/ssl.h b/mozilla/security/nss/lib/ssl/ssl.h
+index d0b5aa7..5b572b2 100644
+--- a/mozilla/security/nss/lib/ssl/ssl.h
++++ b/mozilla/security/nss/lib/ssl/ssl.h
+@@ -136,6 +136,18 @@ SSL_IMPORT SECStatus SSL_OptionSetDefault(PRInt32 option, PRBool on);
+ SSL_IMPORT SECStatus SSL_OptionGetDefault(PRInt32 option, PRBool *on);
+ SSL_IMPORT SECStatus SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHandle);
+
++SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd,
++ const unsigned char *data,
++ unsigned short length);
++SSL_IMPORT SECStatus SSL_GetNextProto(PRFileDesc *fd,
++ int *state,
++ unsigned char *buf,
++ unsigned *length,
++ unsigned buf_len);
++#define SSL_NEXT_PROTO_NO_SUPPORT 0 /* No peer support */
++#define SSL_NEXT_PROTO_NEGOTIATED 1 /* Mutual agreement */
++#define SSL_NEXT_PROTO_NO_OVERLAP 2 /* No protocol overlap found */
++
+ /*
+ ** Control ciphers that SSL uses. If on is non-zero then the named cipher
+ ** is enabled, otherwise it is disabled.
+diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/ssl/ssl3con.c
+index 6b37c4f..545e51e 100644
+--- a/mozilla/security/nss/lib/ssl/ssl3con.c
++++ b/mozilla/security/nss/lib/ssl/ssl3con.c
+@@ -81,6 +81,7 @@ static SECStatus ssl3_InitState( sslSocket *ss);
+ static SECStatus ssl3_SendCertificate( sslSocket *ss);
+ static SECStatus ssl3_SendEmptyCertificate( sslSocket *ss);
+ static SECStatus ssl3_SendCertificateRequest(sslSocket *ss);
++static SECStatus ssl3_SendNextProto( sslSocket *ss);
+ static SECStatus ssl3_SendFinished( sslSocket *ss, PRInt32 flags);
+ static SECStatus ssl3_SendServerHello( sslSocket *ss);
+ static SECStatus ssl3_SendServerHelloDone( sslSocket *ss);
+@@ -5717,6 +5718,12 @@ ssl3_HandleServerHelloDone(sslSocket *ss)
+ if (rv != SECSuccess) {
+ goto loser; /* err code was set. */
+ }
++
++ rv = ssl3_SendNextProto(ss);
++ if (rv != SECSuccess) {
++ goto loser; /* err code was set. */
++ }
++
+ rv = ssl3_SendFinished(ss, 0);
+ if (rv != SECSuccess) {
+ goto loser; /* err code was set. */
+@@ -8138,6 +8145,40 @@ ssl3_ComputeTLSFinished(ssl3CipherSpec *spec,
+ }
+
+ /* called from ssl3_HandleServerHelloDone
++ */
++static SECStatus
++ssl3_SendNextProto(sslSocket *ss)
++{
++ SECStatus rv;
++ int padding_len;
++ static const unsigned char padding[32] = {0};
++
++ if (ss->ssl3.nextProtoState == SSL_NEXT_PROTO_NO_SUPPORT)
++ return SECSuccess;
++
++ PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
++ PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
++
++ padding_len = 32 - ((ss->ssl3.nextProto.len + 2) % 32);
++
++ rv = ssl3_AppendHandshakeHeader(ss, next_proto, ss->ssl3.nextProto.len +
++ 2 + padding_len);
++ if (rv != SECSuccess) {
++ return rv; /* error code set by AppendHandshakeHeader */
++ }
++ rv = ssl3_AppendHandshakeVariable(ss, ss->ssl3.nextProto.data,
++ ss->ssl3.nextProto.len, 1);
++ if (rv != SECSuccess) {
++ return rv; /* error code set by AppendHandshake */
++ }
++ rv = ssl3_AppendHandshakeVariable(ss, padding, padding_len, 1);
++ if (rv != SECSuccess) {
++ return rv; /* error code set by AppendHandshake */
++ }
++ return rv;
++}
++
++/* called from ssl3_HandleServerHelloDone
+ * ssl3_HandleClientHello
+ * ssl3_HandleFinished
+ */
+@@ -9457,6 +9498,11 @@ ssl3_DestroySSL3Info(sslSocket *ss)
+ ssl3_DestroyCipherSpec(&ss->ssl3.specs[1], PR_TRUE/*freeSrvName*/);
+
+ ss->ssl3.initialized = PR_FALSE;
++
++ if (ss->ssl3.nextProto.data) {
++ PORT_Free(ss->ssl3.nextProto.data);
++ ss->ssl3.nextProto.data = NULL;
++ }
+ }
+
+ /* End of ssl3con.c */
+diff --git a/mozilla/security/nss/lib/ssl/ssl3ext.c b/mozilla/security/nss/lib/ssl/ssl3ext.c
+index fd0d9b9..4269028 100644
+--- a/mozilla/security/nss/lib/ssl/ssl3ext.c
++++ b/mozilla/security/nss/lib/ssl/ssl3ext.c
+@@ -235,6 +235,7 @@ static const ssl3HelloExtensionHandler clientHelloHandlers[] = {
+ #endif
+ { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn },
+ { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
++ { ssl_next_proto_neg_xtn, &ssl3_ServerHandleNextProtoNegoXtn },
+ { -1, NULL }
+ };
+
+@@ -245,6 +246,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
+ /* TODO: add a handler for ssl_ec_point_formats_xtn */
+ { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn },
+ { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
++ { ssl_next_proto_neg_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
+ { -1, NULL }
+ };
+
+@@ -267,7 +269,8 @@ ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
+ { ssl_elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn },
+ { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn },
+ #endif
+- { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }
++ { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn },
++ { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn }
+ /* any extra entries will appear as { 0, NULL } */
+ };
+
+@@ -532,6 +535,123 @@ ssl3_SendSessionTicketXtn(
+ return -1;
+ }
+
++/* handle an incoming Next Protocol Negotiation extension. */
++SECStatus
++ssl3_ServerHandleNextProtoNegoXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
++{
++ if (data->len != 0) {
++ /* Clients MUST send an empty NPN extension, if any. */
++ return SECFailure;
++ }
++
++ ss->ssl3.hs.nextProtoNego = PR_TRUE;
++ return SECSuccess;
++}
++
++/* ssl3_ValidateNextProtoNego checks that the given block of data is valid: none
++ * of the length may be 0 and the sum of the lengths must equal the length of
++ * the block. */
++SECStatus
++ssl3_ValidateNextProtoNego(const unsigned char* data, unsigned short length)
++{
++ unsigned int offset = 0;
++
++ while (offset < length) {
++ if (data[offset] == 0) {
++ return SECFailure;
++ }
++ offset += (unsigned int)data[offset] + 1;
++ }
++
++ if (offset > length)
++ return SECFailure;
++
++ return SECSuccess;
++}
++
++SECStatus
++ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
++ SECItem *data)
++{
++ unsigned int i, j;
++ SECStatus rv;
++ unsigned char *result;
++
++ if (data->len == 0) {
++ /* The server supports the extension, but doesn't have any
++ * protocols configured. In this case we request our favoured
++ * protocol. */
++ goto pick_first;
++ }
++
++ rv = ssl3_ValidateNextProtoNego(data->data, data->len);
++ if (rv != SECSuccess)
++ return rv;
++
++ /* For each protocol in server preference order, see if we support it. */
++ for (i = 0; i < data->len; ) {
++ for (j = 0; j < ss->opt.nextProtoNego.len; ) {
++ if (data->data[i] == ss->opt.nextProtoNego.data[j] &&
++ memcmp(&data->data[i+1], &ss->opt.nextProtoNego.data[j+1],
++ data->data[i]) == 0) {
++ /* We found a match */
++ ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NEGOTIATED;
++ result = &data->data[i];
++ goto found;
++ }
++ j += (unsigned int)ss->opt.nextProtoNego.data[j] + 1;
++ }
++
++ i += (unsigned int)data->data[i] + 1;
++ }
++
++ pick_first:
++ ss->ssl3.nextProtoState = SSL_NEXT_PROTO_NO_OVERLAP;
++ result = ss->opt.nextProtoNego.data;
++
++ found:
++ if (ss->ssl3.nextProto.data)
++ PORT_Free(ss->ssl3.nextProto.data);
++ ss->ssl3.nextProto.data = PORT_Alloc(result[0]);
++ PORT_Memcpy(ss->ssl3.nextProto.data, result + 1, result[0]);
++ ss->ssl3.nextProto.len = result[0];
++ return SECSuccess;
++}
++
++PRInt32
++ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss,
++ PRBool append,
++ PRUint32 maxBytes)
++{
++ PRInt32 extension_length;
++
++ /* Renegotiations do not send this extension. */
++ if (ss->opt.nextProtoNego.len == 0 || ss->firstHsDone) {
++ return 0;
++ }
++
++ extension_length = 4;
++
++ if (append && maxBytes >= extension_length) {
++ SECStatus rv;
++ rv = ssl3_AppendHandshakeNumber(ss, ssl_next_proto_neg_xtn, 2);
++ if (rv != SECSuccess)
++ goto loser;
++ rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
++ if (rv != SECSuccess)
++ goto loser;
++ TLSExtensionData *xtnData = &ss->xtnData;
++ xtnData->advertised[xtnData->numAdvertised++] = ssl_next_proto_neg_xtn;
++ } else if (maxBytes < extension_length) {
++ return 0;
++ }
++
++ return extension_length;
++
++ loser:
++ return -1;
++}
++
+ /*
+ * NewSessionTicket
+ * Called from ssl3_HandleFinished
+diff --git a/mozilla/security/nss/lib/ssl/ssl3prot.h b/mozilla/security/nss/lib/ssl/ssl3prot.h
+index 0fc1675..c82c891 100644
+--- a/mozilla/security/nss/lib/ssl/ssl3prot.h
++++ b/mozilla/security/nss/lib/ssl/ssl3prot.h
+@@ -157,7 +157,8 @@ typedef enum {
+ server_hello_done = 14,
+ certificate_verify = 15,
+ client_key_exchange = 16,
+- finished = 20
++ finished = 20,
++ next_proto = 67
+ } SSL3HandshakeType;
+
+ typedef struct {
+diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/ssl/sslimpl.h
+index ea36cfb..0ec579d 100644
+--- a/mozilla/security/nss/lib/ssl/sslimpl.h
++++ b/mozilla/security/nss/lib/ssl/sslimpl.h
+@@ -317,6 +317,11 @@ typedef struct {
+ #endif /* NSS_ENABLE_ECC */
+
+ typedef struct sslOptionsStr {
++ /* For clients, this is a validated list of protocols in preference order
++ * and wire format. For servers, this is the list of support protocols,
++ * also in wire format. */
++ SECItem nextProtoNego;
++
+ unsigned int useSecurity : 1; /* 1 */
+ unsigned int useSocks : 1; /* 2 */
+ unsigned int requestCertificate : 1; /* 3 */
+@@ -789,6 +794,7 @@ const ssl3CipherSuiteDef *suite_def;
+ #ifdef NSS_ENABLE_ECC
+ PRUint32 negotiatedECCurves; /* bit mask */
+ #endif /* NSS_ENABLE_ECC */
++ PRBool nextProtoNego;/* Our peer has sent this extension */
+ } SSL3HandshakeState;
+
+
+@@ -830,6 +836,16 @@ struct ssl3StateStr {
+ PRBool initialized;
+ SSL3HandshakeState hs;
+ ssl3CipherSpec specs[2]; /* one is current, one is pending. */
++
++ /* In a client: if the server supports Next Protocol Negotiation, then
++ * this is the protocol that was requested.
++ * In a server: this is the protocol that the client requested via Next
++ * Protocol Negotiation.
++ *
++ * In either case, if the data pointer is non-NULL, then it is malloced
++ * data. */
++ SECItem nextProto;
++ int nextProtoState; /* See SSL_NEXT_PROTO_* defines */
+ };
+
+ typedef struct {
+@@ -1495,8 +1511,12 @@ extern SECStatus ssl3_HandleSupportedPointFormatsXtn(sslSocket * ss,
+ PRUint16 ex_type, SECItem *data);
+ extern SECStatus ssl3_ClientHandleSessionTicketXtn(sslSocket *ss,
+ PRUint16 ex_type, SECItem *data);
++extern SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss,
++ PRUint16 ex_type, SECItem *data);
+ extern SECStatus ssl3_ServerHandleSessionTicketXtn(sslSocket *ss,
+ PRUint16 ex_type, SECItem *data);
++extern SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss,
++ PRUint16 ex_type, SECItem *data);
+
+ /* ClientHello and ServerHello extension senders.
+ * Note that not all extension senders are exposed here; only those that
+@@ -1527,6 +1547,10 @@ extern PRInt32 ssl3_SendSupportedCurvesXtn(sslSocket *ss,
+ extern PRInt32 ssl3_SendSupportedPointFormatsXtn(sslSocket *ss,
+ PRBool append, PRUint32 maxBytes);
+ #endif
++extern PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append,
++ PRUint32 maxBytes);
++extern SECStatus ssl3_ValidateNextProtoNego(const unsigned char* data,
++ unsigned short length);
+
+ /* call the registered extension handlers. */
+ extern SECStatus ssl3_HandleHelloExtensions(sslSocket *ss,
+diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/ssl/sslsock.c
+index aab48d6..2ff2992 100644
+--- a/mozilla/security/nss/lib/ssl/sslsock.c
++++ b/mozilla/security/nss/lib/ssl/sslsock.c
+@@ -163,6 +163,7 @@ static const sslSocketOps ssl_secure_ops = { /* SSL. */
+ ** default settings for socket enables
+ */
+ static sslOptions ssl_defaults = {
++ { siBuffer, NULL, 0 }, /* nextProtoNego */
+ PR_TRUE, /* useSecurity */
+ PR_FALSE, /* useSocks */
+ PR_FALSE, /* requestCertificate */
+@@ -437,6 +438,10 @@ ssl_DestroySocketContents(sslSocket *ss)
+ ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair);
+ ss->ephemeralECDHKeyPair = NULL;
+ }
++ if (ss->opt.nextProtoNego.data) {
++ PORT_Free(ss->opt.nextProtoNego.data);
++ ss->opt.nextProtoNego.data = NULL;
++ }
+ PORT_Assert(!ss->xtnData.sniNameArr);
+ if (ss->xtnData.sniNameArr) {
+ PORT_Free(ss->xtnData.sniNameArr);
+@@ -1255,6 +1260,75 @@ SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd)
+ return fd;
+ }
+
++/* SSL_SetNextProtoNego sets the list of supported protocols for the given
++ * socket. The list is a series of 8-bit, length prefixed strings. */
++SECStatus
++SSL_SetNextProtoNego(PRFileDesc *fd, const unsigned char *data,
++ unsigned short length)
++{
++ sslSocket *ss = ssl_FindSocket(fd);
++
++ if (!ss) {
++ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetNextProtoNego", SSL_GETPID(),
++ fd));
++ return SECFailure;
++ }
++
++ if (ssl3_ValidateNextProtoNego(data, length) != SECSuccess)
++ return SECFailure;
++
++ ssl_GetSSL3HandshakeLock(ss);
++ if (ss->opt.nextProtoNego.data)
++ PORT_Free(ss->opt.nextProtoNego.data);
++ ss->opt.nextProtoNego.data = PORT_Alloc(length);
++ if (!ss->opt.nextProtoNego.data) {
++ ssl_ReleaseSSL3HandshakeLock(ss);
++ return SECFailure;
++ }
++ memcpy(ss->opt.nextProtoNego.data, data, length);
++ ss->opt.nextProtoNego.len = length;
++ ss->opt.nextProtoNego.type = siBuffer;
++ ssl_ReleaseSSL3HandshakeLock(ss);
++
++ return SECSuccess;
++}
++
++/* SSL_GetNextProto reads the resulting Next Protocol Negotiation result for
++ * the given socket. It's only valid to call this once the handshake has
++ * completed.
++ *
++ * state is set to one of the SSL_NEXT_PROTO_* constants. The negotiated
++ * protocol, if any, is written into buf, which must be at least buf_len
++ * bytes long. If the negotiated protocol is longer than this, it is truncated.
++ * The number of bytes copied is written into length.
++ */
++SECStatus
++SSL_GetNextProto(PRFileDesc *fd, int *state, unsigned char *buf,
++ unsigned int *length, unsigned int buf_len)
++{
++ sslSocket *ss = ssl_FindSocket(fd);
++
++ if (!ss) {
++ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetNextProto", SSL_GETPID(),
++ fd));
++ return SECFailure;
++ }
++
++ *state = ss->ssl3.nextProtoState;
++
++ if (ss->ssl3.nextProtoState != SSL_NEXT_PROTO_NO_SUPPORT &&
++ ss->ssl3.nextProto.data) {
++ *length = ss->ssl3.nextProto.len;
++ if (*length > buf_len)
++ *length = buf_len;
++ PORT_Memcpy(buf, ss->ssl3.nextProto.data, *length);
++ } else {
++ *length = 0;
++ }
++
++ return SECSuccess;
++}
++
+ PRFileDesc *
+ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
+ {
+diff --git a/mozilla/security/nss/lib/ssl/sslt.h b/mozilla/security/nss/lib/ssl/sslt.h
+index c7d4553..f6e0b62 100644
+--- a/mozilla/security/nss/lib/ssl/sslt.h
++++ b/mozilla/security/nss/lib/ssl/sslt.h
+@@ -203,9 +203,10 @@ typedef enum {
+ ssl_ec_point_formats_xtn = 11,
+ #endif
+ ssl_session_ticket_xtn = 35,
++ ssl_next_proto_neg_xtn = 13172,
+ ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
+ } SSLExtensionType;
+
+-#define SSL_MAX_EXTENSIONS 5
++#define SSL_MAX_EXTENSIONS 6
+
+ #endif /* __sslt_h_ */
diff --git a/net/third_party/nss/patches/versionskew.patch b/net/third_party/nss/patches/versionskew.patch
new file mode 100644
index 0000000..1b96983
--- /dev/null
+++ b/net/third_party/nss/patches/versionskew.patch
@@ -0,0 +1,47 @@
+diff --git a/mozilla/security/nss/lib/ssl/sslsecur.c b/mozilla/security/nss/lib/ssl/sslsecur.c
+index 8f79135..80c2ba6 100644
+--- a/mozilla/security/nss/lib/ssl/sslsecur.c
++++ b/mozilla/security/nss/lib/ssl/sslsecur.c
+@@ -1307,6 +1307,10 @@ SSL_SetURL(PRFileDesc *fd, const char *url)
+ SECStatus
+ SSL_SetTrustAnchors(PRFileDesc *fd, CERTCertList *certList)
+ {
++ PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
++ PR_NOT_REACHED("not implemented");
++ return SECFailure;
++#if 0
+ sslSocket * ss = ssl_FindSocket(fd);
+ CERTDistNames *names = NULL;
+
+@@ -1334,6 +1338,7 @@ SSL_SetTrustAnchors(PRFileDesc *fd, CERTCertList *certList)
+ ssl_Release1stHandshakeLock(ss);
+
+ return SECSuccess;
++#endif
+ }
+
+ /*
+diff --git a/mozilla/security/nss/lib/ssl/sslsock.c b/mozilla/security/nss/lib/ssl/sslsock.c
+index aab48d6..01ef3bd 100644
+--- a/mozilla/security/nss/lib/ssl/sslsock.c
++++ b/mozilla/security/nss/lib/ssl/sslsock.c
+@@ -1258,6 +1258,11 @@ SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd)
+ PRFileDesc *
+ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
+ {
++ PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
++ PR_NOT_REACHED("not implemented");
++ return NULL;
++
++#if 0
+ sslSocket * sm = NULL, *ss = NULL;
+ int i;
+ sslServerCerts * mc = sm->serverCerts;
+@@ -1360,6 +1365,7 @@ SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
+ return fd;
+ loser:
+ return NULL;
++#endif
+ }
+
+ /************************************************************************/
diff --git a/net/third_party/nss/ssl/ssl.def b/net/third_party/nss/ssl/ssl.def
index 6a11804..287505f 100644
--- a/net/third_party/nss/ssl/ssl.def
+++ b/net/third_party/nss/ssl/ssl.def
@@ -139,7 +139,18 @@ SSL_CanBypass;
;+ local:
;+*;
;+};
-;+NSS_CHROMIUM { # Chromium experimental
+;+NSS_3.12.6 { # NSS 3.12.6 release
+;+ global:
+SSL_ConfigServerSessionIDCacheWithOpt;
+SSL_GetNegotiatedHostInfo;
+SSL_HandshakeNegotiatedExtension;
+SSL_ReconfigFD;
+SSL_SetTrustAnchors;
+SSL_SNISocketConfigHook;
+;+ local:
+;+*;
+;+};
+;+NSS_CHROMIUM {
;+ global:
SSL_GetNextProto;
SSL_SetNextProtoNego;
diff --git a/net/third_party/nss/ssl/ssl.h b/net/third_party/nss/ssl/ssl.h
index c17f7b1..5b572b2 100644
--- a/net/third_party/nss/ssl/ssl.h
+++ b/net/third_party/nss/ssl/ssl.h
@@ -36,7 +36,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-/* $Id: ssl.h,v 1.31 2009/11/25 05:24:25 wtc%google.com Exp $ */
+/* $Id: ssl.h,v 1.35 2010/02/04 03:21:11 wtc%google.com Exp $ */
#ifndef __ssl_h_
#define __ssl_h_
@@ -117,10 +117,11 @@ SSL_IMPORT PRFileDesc *SSL_ImportFD(PRFileDesc *model, PRFileDesc *fd);
#define SSL_ENABLE_DEFLATE 19 /* Enable TLS compression with */
/* DEFLATE (off by default) */
#define SSL_ENABLE_RENEGOTIATION 20 /* Values below (default: never) */
-#define SSL_REQUIRE_SAFE_NEGOTIATION 21 /* Peer must use renegotiation */
- /* extension in ALL handshakes. */
+#define SSL_REQUIRE_SAFE_NEGOTIATION 21 /* Peer must send Signalling */
+ /* Cipher Suite Value (SCSV) or */
+ /* Renegotiation Info (RI) */
+ /* extension in ALL handshakes. */
/* default: off */
- /* NOT YET IMPLEMENTED in 3.12.5 */
#ifdef SSL_DEPRECATED_FUNCTION
/* Old deprecated function names */
@@ -184,11 +185,14 @@ SSL_IMPORT SECStatus SSL_CipherPolicyGet(PRInt32 cipher, PRInt32 *policy);
/* Never renegotiate at all. */
#define SSL_RENEGOTIATE_NEVER ((PRBool)0)
/* Renegotiate without restriction, whether or not the peer's client hello */
-/* bears the renegotiation info extension (like we always did in the past).*/
+/* bears the renegotiation info extension. Vulnerable, as in the past. */
#define SSL_RENEGOTIATE_UNRESTRICTED ((PRBool)1)
-/* Only renegotiate if the peer's hello bears the TLS renegotiation_info */
-/* extension. Cannot renegotiate in SSL 3.0 sessions. */
-#define SSL_RENEGOTIATE_REQUIRES_XTN ((PRBool)2) /* (NOT YET IMPLEMENTED) */
+/* Only renegotiate if the peer's hello bears the TLS renegotiation_info */
+/* extension. This is safe renegotiation. */
+#define SSL_RENEGOTIATE_REQUIRES_XTN ((PRBool)2)
+/* Disallow all renegotiation in server sockets only, but allow clients */
+/* to continue to renegotiate with vulnerable servers. */
+#define SSL_RENEGOTIATE_CLIENT_ONLY ((PRBool)3)
/*
** Reset the handshake state for fd. This will make the complete SSL
@@ -282,6 +286,61 @@ SSL_IMPORT SECStatus SSL_GetClientAuthDataHook(PRFileDesc *fd,
/*
+** SNI extension processing callback function.
+** It is called when SSL socket receives SNI extension in ClientHello message.
+** Upon this callback invocation, application is responsible to reconfigure the
+** socket with the data for a particular server name.
+** There are three potential outcomes of this function invocation:
+** * application does not recognize the name or the type and wants the
+** "unrecognized_name" alert be sent to the client. In this case the callback
+** function must return SSL_SNI_SEND_ALERT status.
+** * application does not recognize the name, but wants to continue with
+** the handshake using the current socket configuration. In this case,
+** no socket reconfiguration is needed and the function should return
+** SSL_SNI_CURRENT_CONFIG_IS_USED.
+** * application recognizes the name and reconfigures the socket with
+** appropriate certs, key, etc. There are many ways to reconfigure. NSS
+** provides SSL_ReconfigFD function that can be used to update the socket
+** data from model socket. To continue with the rest of the handshake, the
+** implementation function should return an index of a name it has chosen.
+** LibSSL will ignore any SNI extension received in a ClientHello message
+** if application does not register a SSLSNISocketConfig callback.
+** Each type field of SECItem indicates the name type.
+** NOTE: currently RFC3546 defines only one name type: sni_host_name.
+** Client is allowed to send only one name per known type. LibSSL will
+** send an "unrecognized_name" alert if SNI extension name list contains more
+** then one name of a type.
+*/
+typedef PRInt32 (PR_CALLBACK *SSLSNISocketConfig)(PRFileDesc *fd,
+ const SECItem *srvNameArr,
+ PRUint32 srvNameArrSize,
+ void *arg);
+
+/*
+** SSLSNISocketConfig should return an index within 0 and srvNameArrSize-1
+** when it has reconfigured the socket fd to use certs and keys, etc
+** for a specific name. There are two other allowed return values. One
+** tells libSSL to use the default cert and key. The other tells libSSL
+** to send the "unrecognized_name" alert. These values are:
+**/
+#define SSL_SNI_CURRENT_CONFIG_IS_USED -1
+#define SSL_SNI_SEND_ALERT -2
+
+/*
+** Set application implemented SNISocketConfig callback.
+*/
+SSL_IMPORT SECStatus SSL_SNISocketConfigHook(PRFileDesc *fd,
+ SSLSNISocketConfig f,
+ void *arg);
+
+/*
+** Reconfigure fd SSL socket with model socket parameters. Sets
+** server certs and keys, list of trust anchor, socket options
+** and all SSL socket call backs and parameters.
+*/
+SSL_IMPORT PRFileDesc *SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd);
+
+/*
* Set the client side argument for SSL to retrieve PKCS #11 pin.
* fd - the file descriptor for the connection in question
* a - pkcs11 application specific data
@@ -298,7 +357,7 @@ SSL_IMPORT SECStatus SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f,
void *arg);
/*
-** Configure ssl for running a secure server. Needs the
+** Configure SSL socket for running a secure server. Needs the
** certificate for the server and the servers private key. The arguments
** are copied.
*/
@@ -307,7 +366,7 @@ SSL_IMPORT SECStatus SSL_ConfigSecureServer(
SECKEYPrivateKey *key, SSLKEAType kea);
/*
-** Configure a secure servers session-id cache. Define the maximum number
+** Configure a secure server's session-id cache. Define the maximum number
** of entries in the cache, the longevity of the entires, and the directory
** where the cache files will be placed. These values can be zero, and
** if so, the implementation will choose defaults.
@@ -318,6 +377,18 @@ SSL_IMPORT SECStatus SSL_ConfigServerSessionIDCache(int maxCacheEntries,
PRUint32 timeout,
PRUint32 ssl3_timeout,
const char * directory);
+
+/* Configure a secure server's session-id cache. Depends on value of
+ * enableMPCache, configures malti-proc or single proc cache. */
+SSL_IMPORT SECStatus SSL_ConfigServerSessionIDCacheWithOpt(
+ PRUint32 timeout,
+ PRUint32 ssl3_timeout,
+ const char * directory,
+ int maxCacheEntries,
+ int maxCertCacheEntries,
+ int maxSrvNameCacheEntries,
+ PRBool enableMPCache);
+
/*
** Like SSL_ConfigServerSessionIDCache, with one important difference.
** If the application will run multiple processes (as opposed to, or in
@@ -393,11 +464,17 @@ SSL_IMPORT SECStatus SSL_RedoHandshake(PRFileDesc *fd);
#endif
/*
- * Allow the application to pass a URL or hostname into the SSL library
+ * Allow the application to pass a URL or hostname into the SSL library.
*/
SSL_IMPORT SECStatus SSL_SetURL(PRFileDesc *fd, const char *url);
/*
+ * Allow an application to define a set of trust anchors for peer
+ * cert validation.
+ */
+SSL_IMPORT SECStatus SSL_SetTrustAnchors(PRFileDesc *fd, CERTCertList *list);
+
+/*
** Return the number of bytes that SSL has waiting in internal buffers.
** Return 0 if security is not enabled.
*/
@@ -436,7 +513,6 @@ SSL_IMPORT CERTCertificate * SSL_RevealCert(PRFileDesc * socket);
SSL_IMPORT void * SSL_RevealPinArg(PRFileDesc * socket);
SSL_IMPORT char * SSL_RevealURL(PRFileDesc * socket);
-
/* This callback may be passed to the SSL library via a call to
* SSL_GetClientAuthDataHook() for each SSL client socket.
* It will be invoked when SSL needs to know what certificate and private key
@@ -499,6 +575,9 @@ SSL_IMPORT SECStatus SSL_GetChannelInfo(PRFileDesc *fd, SSLChannelInfo *info,
SSL_IMPORT SECStatus SSL_GetCipherSuiteInfo(PRUint16 cipherSuite,
SSLCipherSuiteInfo *info, PRUintn len);
+/* Returnes negotiated through SNI host info. */
+SSL_IMPORT SECItem *SSL_GetNegotiatedHostInfo(PRFileDesc *fd);
+
/*
** Return a new reference to the certificate that was most recently sent
** to the peer on this SSL/TLS connection, or NULL if none has been sent.
@@ -536,6 +615,14 @@ SSL_IMPORT SECStatus SSL_CanBypass(CERTCertificate *cert,
PRUint16 *ciphers, int nciphers,
PRBool *pcanbypass, void *pwArg);
+/*
+** Did the handshake with the peer negotiate the given extension?
+** Output parameter valid only if function returns SECSuccess
+*/
+SSL_IMPORT SECStatus SSL_HandshakeNegotiatedExtension(PRFileDesc * socket,
+ SSLExtensionType extId,
+ PRBool *yes);
+
SEC_END_PROTOS
#endif /* __ssl_h_ */
diff --git a/net/third_party/nss/ssl/ssl3con.c b/net/third_party/nss/ssl/ssl3con.c
index 0018859..545e51e 100644
--- a/net/third_party/nss/ssl/ssl3con.c
+++ b/net/third_party/nss/ssl/ssl3con.c
@@ -39,7 +39,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-/* $Id: ssl3con.c,v 1.126 2009/12/01 17:59:46 wtc%google.com Exp $ */
+/* $Id: ssl3con.c,v 1.134 2010/02/03 03:44:29 wtc%google.com Exp $ */
#include "cert.h"
#include "ssl.h"
@@ -1169,7 +1169,7 @@ ssl3_CleanupKeyMaterial(ssl3KeyMaterial *mat)
** Caller must hold SpecWriteLock.
*/
static void
-ssl3_DestroyCipherSpec(ssl3CipherSpec *spec)
+ssl3_DestroyCipherSpec(ssl3CipherSpec *spec, PRBool freeSrvName)
{
PRBool freeit = (PRBool)(!spec->bypassCiphers);
/* PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); Don't have ss! */
@@ -1187,6 +1187,9 @@ ssl3_DestroyCipherSpec(ssl3CipherSpec *spec)
spec->destroyDecompressContext(spec->decompressContext, 1);
spec->decompressContext = NULL;
}
+ if (freeSrvName && spec->srvVirtName.data) {
+ SECITEM_FreeItem(&spec->srvVirtName, PR_FALSE);
+ }
if (spec->master_secret != NULL) {
PK11_FreeSymKey(spec->master_secret);
spec->master_secret = NULL;
@@ -1445,8 +1448,8 @@ const ssl3BulkCipherDef *cipher_def;
SSLCompressionMethod compression_method;
SECStatus rv;
- PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
pwSpec = ss->ssl3.pwSpec;
@@ -1558,6 +1561,14 @@ const ssl3BulkCipherDef *cipher_def;
* is decrypting, and vice versa.
*/
optArg1 = !optArg1;
+ break;
+ /* kill warnings. */
+ case ssl_calg_null:
+ case ssl_calg_rc4:
+ case ssl_calg_rc2:
+ case ssl_calg_idea:
+ case ssl_calg_fortezza:
+ break;
}
rv = (*initFn)(clientContext,
@@ -1626,7 +1637,7 @@ const ssl3BulkCipherDef *cipher_def;
SSLCipherAlgorithm calg;
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
-
+ PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
PORT_Assert(ss->ssl3.prSpec == ss->ssl3.pwSpec);
pwSpec = ss->ssl3.pwSpec;
@@ -2723,7 +2734,7 @@ ssl3_SendChangeCipherSpecs(sslSocket *ss)
* (Both the read and write sides have changed) destroy it.
*/
if (ss->ssl3.prSpec == ss->ssl3.pwSpec) {
- ssl3_DestroyCipherSpec(ss->ssl3.pwSpec);
+ ssl3_DestroyCipherSpec(ss->ssl3.pwSpec, PR_FALSE/*freeSrvName*/);
}
ssl_ReleaseSpecWriteLock(ss); /**************************************/
@@ -2785,7 +2796,7 @@ ssl3_HandleChangeCipherSpecs(sslSocket *ss, sslBuffer *buf)
* (Both the read and write sides have changed) destroy it.
*/
if (ss->ssl3.prSpec == ss->ssl3.pwSpec) {
- ssl3_DestroyCipherSpec(ss->ssl3.prSpec);
+ ssl3_DestroyCipherSpec(ss->ssl3.prSpec, PR_FALSE/*freeSrvName*/);
}
ssl_ReleaseSpecWriteLock(ss); /*************************************/
return SECSuccess;
@@ -3206,6 +3217,8 @@ ssl3_AppendHandshake(sslSocket *ss, const void *void_src, PRInt32 bytes)
PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) ); /* protects sendBuf. */
+ if (!bytes)
+ return SECSuccess;
if (ss->sec.ci.sendBuf.space < MAX_SEND_BUF_LENGTH && room < bytes) {
rv = sslBuffer_Grow(&ss->sec.ci.sendBuf, PR_MAX(MIN_SEND_BUF_LENGTH,
PR_MIN(MAX_SEND_BUF_LENGTH, ss->sec.ci.sendBuf.len + bytes)));
@@ -3715,6 +3728,7 @@ ssl3_SendClientHello(sslSocket *ss)
int length;
int num_suites;
int actual_count = 0;
+ PRBool isTLS = PR_FALSE;
PRInt32 total_exten_len = 0;
unsigned numCompressionMethods;
@@ -3728,6 +3742,7 @@ ssl3_SendClientHello(sslSocket *ss)
if (rv != SECSuccess) {
return rv; /* ssl3_InitState has set the error code. */
}
+ ss->ssl3.hs.sendingSCSV = PR_FALSE; /* Must be reset every handshake */
/* We might be starting a session renegotiation in which case we should
* clear previous state.
@@ -3825,6 +3840,7 @@ ssl3_SendClientHello(sslSocket *ss)
}
}
+ isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0);
ssl_GetSpecWriteLock(ss);
cwSpec = ss->ssl3.cwSpec;
if (cwSpec->mac_def->mac == mac_null) {
@@ -3852,7 +3868,17 @@ ssl3_SendClientHello(sslSocket *ss)
if (!num_suites)
return SECFailure; /* ssl3_config_match_init has set error code. */
- if (ss->opt.enableTLS && ss->version > SSL_LIBRARY_VERSION_3_0) {
+ /* HACK for SCSV in SSL 3.0. On initial handshake, prepend SCSV,
+ * only if we're willing to complete an SSL 3.0 handshake.
+ */
+ if (!ss->firstHsDone && ss->opt.enableSSL3) {
+ /* Must set this before calling Hello Extension Senders,
+ * to suppress sending of empty RI extension.
+ */
+ ss->ssl3.hs.sendingSCSV = PR_TRUE;
+ }
+
+ if (isTLS || (ss->firstHsDone && ss->peerRequestedProtection)) {
PRUint32 maxBytes = 65535; /* 2^16 - 1 */
PRInt32 extLen;
@@ -3866,8 +3892,10 @@ ssl3_SendClientHello(sslSocket *ss)
if (total_exten_len > 0)
total_exten_len += 2;
}
+
#if defined(NSS_ENABLE_ECC) && !defined(NSS_ECC_MORE_THAN_SUITE_B)
- else { /* SSL3 only */
+ if (!total_exten_len || !isTLS) {
+ /* not sending the elliptic_curves and ec_point_formats extensions */
ssl3_DisableECCSuites(ss, NULL); /* disable all ECC suites */
}
#endif
@@ -3876,6 +3904,9 @@ ssl3_SendClientHello(sslSocket *ss)
num_suites = count_cipher_suites(ss, ss->ssl3.policy, PR_TRUE);
if (!num_suites)
return SECFailure; /* count_cipher_suites has set error code. */
+ if (ss->ssl3.hs.sendingSCSV) {
+ ++num_suites; /* make room for SCSV */
+ }
/* count compression methods */
numCompressionMethods = 0;
@@ -3923,7 +3954,15 @@ ssl3_SendClientHello(sslSocket *ss)
return rv; /* err set by ssl3_AppendHandshake* */
}
-
+ if (ss->ssl3.hs.sendingSCSV) {
+ /* Add the actual SCSV */
+ rv = ssl3_AppendHandshakeNumber(ss, TLS_RENEGO_PROTECTION_REQUEST,
+ sizeof(ssl3CipherSuite));
+ if (rv != SECSuccess) {
+ return rv; /* err set by ssl3_AppendHandshake* */
+ }
+ actual_count++;
+ }
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
if (config_match(suite, ss->ssl3.policy, PR_TRUE)) {
@@ -3978,9 +4017,14 @@ ssl3_SendClientHello(sslSocket *ss)
}
maxBytes -= extLen;
PORT_Assert(!maxBytes);
+ }
+ if (ss->ssl3.hs.sendingSCSV) {
+ /* Since we sent the SCSV, pretend we sent empty RI extension. */
+ TLSExtensionData *xtnData = &ss->xtnData;
+ xtnData->advertised[xtnData->numAdvertised++] =
+ ssl_renegotiation_info_xtn;
}
-
rv = ssl3_FlushHandshake(ss, 0);
if (rv != SECSuccess) {
return rv; /* error code set by ssl3_FlushHandshake */
@@ -4491,19 +4535,6 @@ sendRSAClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
goto loser;
}
-#if defined(TRACE)
- if (ssl_trace >= 100) {
- SECStatus extractRV = PK11_ExtractKeyValue(pms);
- if (extractRV == SECSuccess) {
- SECItem * keyData = PK11_GetKeyData(pms);
- if (keyData && keyData->data && keyData->len) {
- ssl_PrintBuf(ss, "Pre-Master Secret",
- keyData->data, keyData->len);
- }
- }
- }
-#endif
-
/* Get the wrapped (encrypted) pre-master secret, enc_pms */
enc_pms.len = SECKEY_PublicKeyStrength(svrPubKey);
enc_pms.data = (unsigned char*)PORT_Alloc(enc_pms.len);
@@ -4518,6 +4549,48 @@ sendRSAClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
goto loser;
}
+#if defined(TRACE)
+ if (ssl_trace >= 100 || ssl_keylog_iob) {
+ SECStatus extractRV = PK11_ExtractKeyValue(pms);
+ if (extractRV == SECSuccess) {
+ SECItem * keyData = PK11_GetKeyData(pms);
+ if (keyData && keyData->data && keyData->len) {
+ if (ssl_trace >= 100) {
+ ssl_PrintBuf(ss, "Pre-Master Secret",
+ keyData->data, keyData->len);
+ }
+ if (ssl_keylog_iob && enc_pms.len >= 8 && keyData->len == 48) {
+ /* https://developer.mozilla.org/en/NSS_Key_Log_Format */
+
+ /* There could be multiple, concurrent writers to the
+ * keylog, so we have to do everything in a single call to
+ * fwrite. */
+ char buf[4 + 8*2 + 1 + 48*2 + 1];
+ static const char hextable[16] = "0123456789abcdef";
+ unsigned int i;
+
+ strcpy(buf, "RSA ");
+
+ for (i = 0; i < 8; i++) {
+ buf[4 + i*2] = hextable[enc_pms.data[i] >> 4];
+ buf[4 + i*2 + 1] = hextable[enc_pms.data[i] & 15];
+ }
+ buf[20] = ' ';
+
+ for (i = 0; i < 48; i++) {
+ buf[21 + i*2] = hextable[keyData->data[i] >> 4];
+ buf[21 + i*2 + 1] = hextable[keyData->data[i] & 15];
+ }
+ buf[sizeof(buf) - 1] = '\n';
+
+ fwrite(buf, sizeof(buf), 1, ssl_keylog_iob);
+ fflush(ssl_keylog_iob);
+ }
+ }
+ }
+ }
+#endif
+
rv = ssl3_InitPendingCipherSpec(ss, pms);
PK11_FreeSymKey(pms); pms = NULL;
@@ -4909,20 +4982,36 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
}
ss->ssl3.hs.compression = (SSLCompressionMethod)temp;
- /* Note that if !isTLS && length != 0, we do NOT goto alert_loser.
+ /* Note that if !isTLS and the extra stuff is not extensions, we
+ * do NOT goto alert_loser.
* There are some old SSL 3.0 implementations that do send stuff
* after the end of the server hello, and we deliberately ignore
* such stuff in the interest of maximal interoperability (being
* "generous in what you accept").
+ * Update: Starting in NSS 3.12.6, we handle the renegotiation_info
+ * extension in SSL 3.0.
*/
- if (isTLS && length != 0) {
+ if (length != 0) {
SECItem extensions;
rv = ssl3_ConsumeHandshakeVariable(ss, &extensions, 2, &b, &length);
- if (rv != SECSuccess || length != 0)
- goto alert_loser;
- rv = ssl3_HandleHelloExtensions(ss, &extensions.data, &extensions.len);
- if (rv != SECSuccess)
- goto alert_loser;
+ if (rv != SECSuccess || length != 0) {
+ if (isTLS)
+ goto alert_loser;
+ } else {
+ rv = ssl3_HandleHelloExtensions(ss, &extensions.data,
+ &extensions.len);
+ if (rv != SECSuccess)
+ goto alert_loser;
+ }
+ }
+ if ((ss->opt.requireSafeNegotiation ||
+ (ss->firstHsDone && (ss->peerRequestedProtection ||
+ ss->opt.enableRenegotiation == SSL_RENEGOTIATE_REQUIRES_XTN))) &&
+ !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
+ desc = handshake_failure;
+ errCode = ss->firstHsDone ? SSL_ERROR_RENEGOTIATION_NOT_ALLOWED
+ : SSL_ERROR_UNSAFE_NEGOTIATION;
+ goto alert_loser;
}
/* Any errors after this point are not "malformed" errors. */
@@ -5037,7 +5126,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
sid->u.ssl3.sessionTicket.ticket.data != NULL)
SSL_AtomicIncrementLong(& ssl3stats.hsh_sid_stateless_resumes );
- if (ssl3_ExtensionNegotiated(ss, session_ticket_xtn))
+ if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn))
ss->ssl3.hs.ws = wait_new_session_ticket;
else
ss->ssl3.hs.ws = wait_change_cipher;
@@ -5642,7 +5731,7 @@ ssl3_HandleServerHelloDone(sslSocket *ss)
ssl_ReleaseXmitBufLock(ss); /*******************************/
- if (ssl3_ExtensionNegotiated(ss, session_ticket_xtn))
+ if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn))
ss->ssl3.hs.ws = wait_new_session_ticket;
else
ss->ssl3.hs.ws = wait_change_cipher;
@@ -5679,6 +5768,25 @@ ssl3_SendHelloRequest(sslSocket *ss)
return SECSuccess;
}
+/*
+ * Called from:
+ * ssl3_HandleClientHello()
+ */
+static SECComparison
+ssl3_ServerNameCompare(const SECItem *name1, const SECItem *name2)
+{
+ if (!name1 != !name2) {
+ return SECLessThan;
+ }
+ if (!name1) {
+ return SECEqual;
+ }
+ if (name1->type != name2->type) {
+ return SECLessThan;
+ }
+ return SECITEM_CompareItem(name1, name2);
+}
+
/* Sets memory error when returning NULL.
* Called from:
* ssl3_SendClientHello()
@@ -5695,6 +5803,21 @@ ssl3_NewSessionID(sslSocket *ss, PRBool is_server)
if (sid == NULL)
return sid;
+ if (is_server) {
+ const SECItem * srvName;
+ SECStatus rv = SECSuccess;
+
+ ssl_GetSpecReadLock(ss); /********************************/
+ srvName = &ss->ssl3.prSpec->srvVirtName;
+ if (srvName->len && srvName->data) {
+ rv = SECITEM_CopyItem(NULL, &sid->u.ssl3.srvName, srvName);
+ }
+ ssl_ReleaseSpecReadLock(ss); /************************************/
+ if (rv != SECSuccess) {
+ PORT_Free(sid);
+ return NULL;
+ }
+ }
sid->peerID = (ss->peerID == NULL) ? NULL : PORT_Strdup(ss->peerID);
sid->urlSvrName = (ss->url == NULL) ? NULL : PORT_Strdup(ss->url);
sid->addr = ss->sec.ci.peer;
@@ -5802,6 +5925,9 @@ ssl3_SendServerHelloSequence(sslSocket *ss)
return SECSuccess;
}
+/* An empty TLS Renegotiation Info (RI) extension */
+static const PRUint8 emptyRIext[5] = {0xff, 0x01, 0x00, 0x01, 0x00};
+
/* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
* ssl3 Client Hello message.
* Caller must hold Handshake and RecvBuf locks.
@@ -5854,7 +5980,8 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
goto alert_loser;
}
if (ss->ssl3.hs.ws == idle_handshake &&
- ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) {
+ (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER ||
+ ss->opt.enableRenegotiation == SSL_RENEGOTIATE_CLIENT_ONLY)) {
desc = no_renegotiation;
level = alert_warning;
errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
@@ -5923,13 +6050,43 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
goto loser; /* malformed */
}
}
+ if (!ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
+ /* If we didn't receive an RI extension, look for the SCSV,
+ * and if found, treat it just like an empty RI extension
+ * by processing a local copy of an empty RI extension.
+ */
+ for (i = 0; i + 1 < suites.len; i += 2) {
+ PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
+ if (suite_i == TLS_RENEGO_PROTECTION_REQUEST) {
+ SSL3Opaque * b2 = (SSL3Opaque *)emptyRIext;
+ PRUint32 L2 = sizeof emptyRIext;
+ (void)ssl3_HandleHelloExtensions(ss, &b2, &L2);
+ break;
+ }
+ }
+ }
+ if (ss->firstHsDone &&
+ ss->opt.enableRenegotiation == SSL_RENEGOTIATE_REQUIRES_XTN &&
+ !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
+ desc = no_renegotiation;
+ level = alert_warning;
+ errCode = SSL_ERROR_RENEGOTIATION_NOT_ALLOWED;
+ goto alert_loser;
+ }
+ if ((ss->opt.requireSafeNegotiation ||
+ (ss->firstHsDone && ss->peerRequestedProtection)) &&
+ !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
+ desc = handshake_failure;
+ errCode = SSL_ERROR_UNSAFE_NEGOTIATION;
+ goto alert_loser;
+ }
/* We do stateful resumes only if either of the following
* conditions are satisfied: (1) the client does not support the
* session ticket extension, or (2) the client support the session
* ticket extension, but sent an empty ticket.
*/
- if (!ssl3_ExtensionNegotiated(ss, session_ticket_xtn) ||
+ if (!ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) ||
ss->xtnData.emptySessionTicket) {
if (sidBytes.len > 0 && !ss->opt.noCache) {
SSL_TRC(7, ("%d: SSL3[%d]: server, lookup client session-id for 0x%08x%08x%08x%08x",
@@ -5973,9 +6130,9 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
* but OpenSSL-0.9.8g does not accept session tickets while
* resuming.)
*/
- if (ssl3_ExtensionNegotiated(ss, session_ticket_xtn) && sid == NULL) {
+ if (ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn) && sid == NULL) {
ssl3_RegisterServerHelloExtensionSender(ss,
- session_ticket_xtn, ssl3_SendSessionTicketXtn);
+ ssl_session_ticket_xtn, ssl3_SendSessionTicketXtn);
}
if (sid != NULL) {
@@ -6053,10 +6210,9 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
break;
#endif
/* Double check that the cached cipher suite is in the client's list */
- for (i = 0; i < suites.len; i += 2) {
- if ((suites.data[i] == MSB(suite->cipher_suite)) &&
- (suites.data[i + 1] == LSB(suite->cipher_suite))) {
-
+ for (i = 0; i + 1 < suites.len; i += 2) {
+ PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
+ if (suite_i == suite->cipher_suite) {
ss->ssl3.hs.cipher_suite = suite->cipher_suite;
ss->ssl3.hs.suite_def =
ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
@@ -6087,10 +6243,9 @@ ssl3_HandleClientHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
if (!config_match(suite, ss->ssl3.policy, PR_TRUE))
continue;
- for (i = 0; i < suites.len; i += 2) {
- if ((suites.data[i] == MSB(suite->cipher_suite)) &&
- (suites.data[i + 1] == LSB(suite->cipher_suite))) {
-
+ for (i = 0; i + 1 < suites.len; i += 2) {
+ PRUint16 suite_i = (suites.data[i] << 8) | suites.data[i + 1];
+ if (suite_i == suite->cipher_suite) {
ss->ssl3.hs.cipher_suite = suite->cipher_suite;
ss->ssl3.hs.suite_def =
ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
@@ -6232,6 +6387,32 @@ compression_found:
ss->sec.localCert =
CERT_DupCertificate(ss->serverCerts[sid->keaType].serverCert);
+ /* Copy cached name in to pending spec */
+ if (sid != NULL &&
+ sid->version > SSL_LIBRARY_VERSION_3_0 &&
+ sid->u.ssl3.srvName.len && sid->u.ssl3.srvName.data) {
+ /* Set server name from sid */
+ SECItem *sidName = &sid->u.ssl3.srvName;
+ SECItem *pwsName = &ss->ssl3.pwSpec->srvVirtName;
+ if (pwsName->data) {
+ SECITEM_FreeItem(pwsName, PR_FALSE);
+ }
+ rv = SECITEM_CopyItem(NULL, pwsName, sidName);
+ if (rv != SECSuccess) {
+ errCode = PORT_GetError();
+ desc = internal_error;
+ goto alert_loser;
+ }
+ }
+
+ /* Clean up sni name array */
+ if (ssl3_ExtensionNegotiated(ss, ssl_server_name_xtn) &&
+ ss->xtnData.sniNameArr) {
+ PORT_Free(ss->xtnData.sniNameArr);
+ ss->xtnData.sniNameArr = NULL;
+ ss->xtnData.sniNameArrSize = 0;
+ }
+
ssl_GetXmitBufLock(ss); haveXmitBufLock = PR_TRUE;
rv = ssl3_SendServerHello(ss);
@@ -6285,6 +6466,146 @@ compression_found:
}
SSL_AtomicIncrementLong(& ssl3stats.hch_sid_cache_misses );
+ if (ssl3_ExtensionNegotiated(ss, ssl_server_name_xtn)) {
+ int ret = 0;
+ if (ss->sniSocketConfig) do { /* not a loop */
+ ret = SSL_SNI_SEND_ALERT;
+ /* If extension is negotiated, the len of names should > 0. */
+ if (ss->xtnData.sniNameArrSize) {
+ /* Calling client callback to reconfigure the socket. */
+ ret = (SECStatus)(*ss->sniSocketConfig)(ss->fd,
+ ss->xtnData.sniNameArr,
+ ss->xtnData.sniNameArrSize,
+ ss->sniSocketConfigArg);
+ }
+ if (ret <= SSL_SNI_SEND_ALERT) {
+ /* Application does not know the name or was not able to
+ * properly reconfigure the socket. */
+ errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
+ desc = unrecognized_name;
+ break;
+ } else if (ret == SSL_SNI_CURRENT_CONFIG_IS_USED) {
+ SECStatus rv = SECSuccess;
+ SECItem * cwsName, *pwsName;
+
+ ssl_GetSpecWriteLock(ss); /*******************************/
+ pwsName = &ss->ssl3.pwSpec->srvVirtName;
+ cwsName = &ss->ssl3.cwSpec->srvVirtName;
+#ifndef SSL_SNI_ALLOW_NAME_CHANGE_2HS
+ /* not allow name change on the 2d HS */
+ if (ss->firstHsDone) {
+ if (ssl3_ServerNameCompare(pwsName, cwsName)) {
+ ssl_ReleaseSpecWriteLock(ss); /******************/
+ errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
+ desc = handshake_failure;
+ ret = SSL_SNI_SEND_ALERT;
+ break;
+ }
+ }
+#endif
+ if (pwsName->data) {
+ SECITEM_FreeItem(pwsName, PR_FALSE);
+ }
+ if (cwsName->data) {
+ rv = SECITEM_CopyItem(NULL, pwsName, cwsName);
+ }
+ ssl_ReleaseSpecWriteLock(ss); /**************************/
+ if (rv != SECSuccess) {
+ errCode = SSL_ERROR_INTERNAL_ERROR_ALERT;
+ desc = internal_error;
+ ret = SSL_SNI_SEND_ALERT;
+ break;
+ }
+ } else if (ret < ss->xtnData.sniNameArrSize) {
+ /* Application has configured new socket info. Lets check it
+ * and save the name. */
+ SECStatus rv;
+ SECItem * name = &ss->xtnData.sniNameArr[ret];
+ int configedCiphers;
+ SECItem * pwsName;
+
+ /* get rid of the old name and save the newly picked. */
+ /* This code is protected by ssl3HandshakeLock. */
+ ssl_GetSpecWriteLock(ss); /*******************************/
+#ifndef SSL_SNI_ALLOW_NAME_CHANGE_2HS
+ /* not allow name change on the 2d HS */
+ if (ss->firstHsDone) {
+ SECItem *cwsName = &ss->ssl3.cwSpec->srvVirtName;
+ if (ssl3_ServerNameCompare(name, cwsName)) {
+ ssl_ReleaseSpecWriteLock(ss); /******************/
+ errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
+ desc = handshake_failure;
+ ret = SSL_SNI_SEND_ALERT;
+ break;
+ }
+ }
+#endif
+ pwsName = &ss->ssl3.pwSpec->srvVirtName;
+ if (pwsName->data) {
+ SECITEM_FreeItem(pwsName, PR_FALSE);
+ }
+ rv = SECITEM_CopyItem(NULL, pwsName, name);
+ ssl_ReleaseSpecWriteLock(ss); /***************************/
+ if (rv != SECSuccess) {
+ errCode = SSL_ERROR_INTERNAL_ERROR_ALERT;
+ desc = internal_error;
+ ret = SSL_SNI_SEND_ALERT;
+ break;
+ }
+ configedCiphers = ssl3_config_match_init(ss);
+ if (configedCiphers <= 0) {
+ /* no ciphers are working/supported */
+ errCode = PORT_GetError();
+ desc = handshake_failure;
+ ret = SSL_SNI_SEND_ALERT;
+ break;
+ }
+ /* Need to tell the client that application has picked
+ * the name from the offered list and reconfigured the socket.
+ */
+ ssl3_RegisterServerHelloExtensionSender(ss, ssl_server_name_xtn,
+ ssl3_SendServerNameXtn);
+ } else {
+ /* Callback returned index outside of the boundary. */
+ PORT_Assert(ret < ss->xtnData.sniNameArrSize);
+ errCode = SSL_ERROR_INTERNAL_ERROR_ALERT;
+ desc = internal_error;
+ ret = SSL_SNI_SEND_ALERT;
+ break;
+ }
+ } while (0);
+ /* Free sniNameArr. The data that each SECItem in the array
+ * points into is the data from the input buffer "b". It will
+ * not be available outside the scope of this or it's child
+ * functions.*/
+ if (ss->xtnData.sniNameArr) {
+ PORT_Free(ss->xtnData.sniNameArr);
+ ss->xtnData.sniNameArr = NULL;
+ ss->xtnData.sniNameArrSize = 0;
+ }
+ if (ret <= SSL_SNI_SEND_ALERT) {
+ /* desc and errCode should be set. */
+ goto alert_loser;
+ }
+ }
+#ifndef SSL_SNI_ALLOW_NAME_CHANGE_2HS
+ else if (ss->firstHsDone) {
+ /* Check that we don't have the name is current spec
+ * if this extension was not negotiated on the 2d hs. */
+ PRBool passed = PR_TRUE;
+ ssl_GetSpecReadLock(ss); /*******************************/
+ if (ss->ssl3.cwSpec->srvVirtName.data) {
+ passed = PR_FALSE;
+ }
+ ssl_ReleaseSpecReadLock(ss); /***************************/
+ if (!passed) {
+ errCode = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
+ desc = handshake_failure;
+ goto alert_loser;
+ }
+ }
+#endif
+
sid = ssl3_NewSessionID(ss, PR_TRUE);
if (sid == NULL) {
errCode = PORT_GetError();
@@ -6430,11 +6751,9 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length)
ssl3CipherSuiteCfg *suite = &ss->cipherSuites[j];
if (!config_match(suite, ss->ssl3.policy, PR_TRUE))
continue;
- for (i = 0; i < suite_length; i += 3) {
- if ((suites[i] == 0) &&
- (suites[i+1] == MSB(suite->cipher_suite)) &&
- (suites[i+2] == LSB(suite->cipher_suite))) {
-
+ for (i = 0; i+2 < suite_length; i += 3) {
+ PRUint32 suite_i = (suites[i] << 16)|(suites[i+1] << 8)|suites[i+2];
+ if (suite_i == suite->cipher_suite) {
ss->ssl3.hs.cipher_suite = suite->cipher_suite;
ss->ssl3.hs.suite_def =
ssl_LookupCipherSuiteDef(ss->ssl3.hs.cipher_suite);
@@ -6447,6 +6766,26 @@ ssl3_HandleV2ClientHello(sslSocket *ss, unsigned char *buffer, int length)
suite_found:
+ /* Look for the SCSV, and if found, treat it just like an empty RI
+ * extension by processing a local copy of an empty RI extension.
+ */
+ for (i = 0; i+2 < suite_length; i += 3) {
+ PRUint32 suite_i = (suites[i] << 16) | (suites[i+1] << 8) | suites[i+2];
+ if (suite_i == TLS_RENEGO_PROTECTION_REQUEST) {
+ SSL3Opaque * b2 = (SSL3Opaque *)emptyRIext;
+ PRUint32 L2 = sizeof emptyRIext;
+ (void)ssl3_HandleHelloExtensions(ss, &b2, &L2);
+ break;
+ }
+ }
+
+ if (ss->opt.requireSafeNegotiation &&
+ !ssl3_ExtensionNegotiated(ss, ssl_renegotiation_info_xtn)) {
+ desc = handshake_failure;
+ errCode = SSL_ERROR_UNSAFE_NEGOTIATION;
+ goto alert_loser;
+ }
+
ss->ssl3.hs.compression = ssl_compression_null;
ss->sec.send = ssl3_SendApplicationData;
@@ -7872,6 +8211,11 @@ ssl3_SendFinished(sslSocket *ss, PRInt32 flags)
}
if (isTLS) {
+ if (isServer)
+ ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished;
+ else
+ ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished;
+ ss->ssl3.hs.finishedBytes = sizeof tlsFinished;
rv = ssl3_AppendHandshakeHeader(ss, finished, sizeof tlsFinished);
if (rv != SECSuccess)
goto fail; /* err set by AppendHandshake. */
@@ -7879,6 +8223,11 @@ ssl3_SendFinished(sslSocket *ss, PRInt32 flags)
if (rv != SECSuccess)
goto fail; /* err set by AppendHandshake. */
} else {
+ if (isServer)
+ ss->ssl3.hs.finishedMsgs.sFinished[1] = hashes;
+ else
+ ss->ssl3.hs.finishedMsgs.sFinished[0] = hashes;
+ ss->ssl3.hs.finishedBytes = sizeof hashes;
rv = ssl3_AppendHandshakeHeader(ss, finished, sizeof hashes);
if (rv != SECSuccess)
goto fail; /* err set by AppendHandshake. */
@@ -8017,6 +8366,11 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
}
rv = ssl3_ComputeTLSFinished(ss->ssl3.crSpec, !isServer,
hashes, &tlsFinished);
+ if (!isServer)
+ ss->ssl3.hs.finishedMsgs.tFinished[1] = tlsFinished;
+ else
+ ss->ssl3.hs.finishedMsgs.tFinished[0] = tlsFinished;
+ ss->ssl3.hs.finishedBytes = sizeof tlsFinished;
if (rv != SECSuccess ||
0 != NSS_SecureMemcmp(&tlsFinished, b, length)) {
(void)SSL3_SendAlert(ss, alert_fatal, decrypt_error);
@@ -8030,6 +8384,11 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
return SECFailure;
}
+ if (!isServer)
+ ss->ssl3.hs.finishedMsgs.sFinished[1] = *hashes;
+ else
+ ss->ssl3.hs.finishedMsgs.sFinished[0] = *hashes;
+ ss->ssl3.hs.finishedBytes = sizeof *hashes;
if (0 != NSS_SecureMemcmp(hashes, b, length)) {
(void)ssl3_HandshakeFailure(ss);
PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
@@ -8052,7 +8411,7 @@ ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,
* ServerHello message.)
*/
if (isServer && !ss->ssl3.hs.isResuming &&
- ssl3_ExtensionNegotiated(ss, session_ticket_xtn)) {
+ ssl3_ExtensionNegotiated(ss, ssl_session_ticket_xtn)) {
rv = ssl3_SendNewSessionTicket(ss);
if (rv != SECSuccess) {
goto xmit_loser;
@@ -8643,11 +9002,33 @@ const ssl3BulkCipherDef *cipher_def;
databuf->space,
plaintext->buf,
plaintext->len);
+
if (rv != SECSuccess) {
int err = ssl_MapLowLevelError(SSL_ERROR_DECOMPRESSION_FAILURE);
- PORT_Free(plaintext->buf);
SSL3_SendAlert(ss, alert_fatal,
isTLS ? decompression_failure : bad_record_mac);
+
+ /* There appears to be a bug with (at least) Apache + OpenSSL where
+ * resumed SSLv3 connections don't actually use compression. See
+ * comments 93-95 of
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=275744
+ *
+ * So, if we get a decompression error, and the record appears to
+ * be already uncompressed, then we return a more specific error
+ * code to hopefully save somebody some debugging time in the
+ * future.
+ */
+ if (plaintext->len >= 4) {
+ unsigned int len = ((unsigned int) plaintext->buf[1] << 16) |
+ ((unsigned int) plaintext->buf[2] << 8) |
+ (unsigned int) plaintext->buf[3];
+ if (len == plaintext->len - 4) {
+ /* This appears to be uncompressed already */
+ err = SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD;
+ }
+ }
+
+ PORT_Free(plaintext->buf);
PORT_SetError(err);
return SECFailure;
}
@@ -8782,6 +9163,7 @@ ssl3_InitState(sslSocket *ss)
ss->ssl3.crSpec = ss->ssl3.cwSpec = &ss->ssl3.specs[0];
ss->ssl3.prSpec = ss->ssl3.pwSpec = &ss->ssl3.specs[1];
ss->ssl3.hs.rehandshake = PR_FALSE;
+ ss->ssl3.hs.sendingSCSV = PR_FALSE;
ssl3_InitCipherSpec(ss, ss->ssl3.crSpec);
ssl3_InitCipherSpec(ss, ss->ssl3.prSpec);
@@ -9049,7 +9431,9 @@ ssl3_RedoHandshake(sslSocket *ss, PRBool flushCache)
PORT_SetError(SSL_ERROR_HANDSHAKE_NOT_COMPLETED);
return SECFailure;
}
- if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) {
+ if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER ||
+ (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_CLIENT_ONLY &&
+ ss->sec.isServer)) {
PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
return SECFailure;
}
@@ -9110,8 +9494,8 @@ ssl3_DestroySSL3Info(sslSocket *ss)
PORT_Free(ss->ssl3.hs.msg_body.buf);
/* free up the CipherSpecs */
- ssl3_DestroyCipherSpec(&ss->ssl3.specs[0]);
- ssl3_DestroyCipherSpec(&ss->ssl3.specs[1]);
+ ssl3_DestroyCipherSpec(&ss->ssl3.specs[0], PR_TRUE/*freeSrvName*/);
+ ssl3_DestroyCipherSpec(&ss->ssl3.specs[1], PR_TRUE/*freeSrvName*/);
ss->ssl3.initialized = PR_FALSE;
diff --git a/net/third_party/nss/ssl/ssl3ecc.c b/net/third_party/nss/ssl/ssl3ecc.c
index fafecfa..42720e5 100644
--- a/net/third_party/nss/ssl/ssl3ecc.c
+++ b/net/third_party/nss/ssl/ssl3ecc.c
@@ -40,7 +40,7 @@
* ***** END LICENSE BLOCK ***** */
/* ECC code moved here from ssl3con.c */
-/* $Id: ssl3ecc.c,v 1.22 2008/03/10 00:01:28 wtc%google.com Exp $ */
+/* $Id: ssl3ecc.c,v 1.23 2010/01/28 16:14:25 kaie%kuix.de Exp $ */
#include "nss.h"
#include "cert.h"
@@ -1059,7 +1059,7 @@ ssl3_SendSupportedCurvesXtn(
if (!ss->sec.isServer) {
TLSExtensionData *xtnData = &ss->xtnData;
xtnData->advertised[xtnData->numAdvertised++] =
- elliptic_curves_xtn;
+ ssl_elliptic_curves_xtn;
}
}
return (sizeof EClist);
@@ -1083,7 +1083,7 @@ ssl3_SendSupportedPointFormatsXtn(
if (!ss->sec.isServer) {
TLSExtensionData *xtnData = &ss->xtnData;
xtnData->advertised[xtnData->numAdvertised++] =
- ec_point_formats_xtn;
+ ssl_ec_point_formats_xtn;
}
}
return (sizeof ECPtFmt);
diff --git a/net/third_party/nss/ssl/ssl3ext.c b/net/third_party/nss/ssl/ssl3ext.c
index 1eaf47c..ead0cfd 100644
--- a/net/third_party/nss/ssl/ssl3ext.c
+++ b/net/third_party/nss/ssl/ssl3ext.c
@@ -41,11 +41,12 @@
* ***** END LICENSE BLOCK ***** */
/* TLS extension code moved here from ssl3ecc.c */
-/* $Id: ssl3ext.c,v 1.5 2009/11/07 18:23:06 wtc%google.com Exp $ */
+/* $Id: ssl3ext.c,v 1.11 2010/02/03 02:38:20 wtc%google.com Exp $ */
#include "nssrenam.h"
#include "nss.h"
#include "ssl.h"
+#include "sslproto.h"
#include "sslimpl.h"
#include "pk11pub.h"
#include "blapi.h"
@@ -61,8 +62,7 @@ static unsigned char session_ticket_mac_key[SHA256_LENGTH];
static PRBool session_ticket_keys_initialized = PR_FALSE;
static PRCallOnceType generate_session_keys_once;
-static PRInt32 ssl3_SendServerNameXtn(sslSocket * ss,
- PRBool append, PRUint32 maxBytes);
+/* forward static function declarations */
static SECStatus ssl3_ParseEncryptedSessionTicket(sslSocket *ss,
SECItem *data, EncryptedSessionTicket *enc_session_ticket);
static SECStatus ssl3_AppendToItem(SECItem *item, const unsigned char *buf,
@@ -74,6 +74,10 @@ static SECStatus ssl3_GetSessionTicketKeysPKCS11(sslSocket *ss,
static SECStatus ssl3_GetSessionTicketKeys(const unsigned char **aes_key,
PRUint32 *aes_key_length, const unsigned char **mac_key,
PRUint32 *mac_key_length);
+static PRInt32 ssl3_SendRenegotiationInfoXtn(sslSocket * ss,
+ PRBool append, PRUint32 maxBytes);
+static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss,
+ PRUint16 ex_type, SECItem *data);
/*
* Write bytes. Using this function means the SECItem structure
@@ -222,42 +226,58 @@ ssl3_GetSessionTicketKeys(const unsigned char **aes_key,
* In the second generation, this table will be dynamic, and functions
* will be registered here.
*/
+/* This table is used by the server, to handle client hello extensions. */
static const ssl3HelloExtensionHandler clientHelloHandlers[] = {
- { server_name_xtn, &ssl3_HandleServerNameXtn },
+ { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
#ifdef NSS_ENABLE_ECC
- { elliptic_curves_xtn, &ssl3_HandleSupportedCurvesXtn },
- { ec_point_formats_xtn, &ssl3_HandleSupportedPointFormatsXtn },
+ { ssl_elliptic_curves_xtn, &ssl3_HandleSupportedCurvesXtn },
+ { ssl_ec_point_formats_xtn, &ssl3_HandleSupportedPointFormatsXtn },
#endif
- { session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn },
- { next_proto_neg_xtn, &ssl3_ServerHandleNextProtoNegoXtn },
+ { ssl_session_ticket_xtn, &ssl3_ServerHandleSessionTicketXtn },
+ { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
+ { ssl_next_proto_neg_xtn, &ssl3_ServerHandleNextProtoNegoXtn },
+ { -1, NULL }
+};
+
+/* These two tables are used by the client, to handle server hello
+ * extensions. */
+static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
+ { ssl_server_name_xtn, &ssl3_HandleServerNameXtn },
+ /* TODO: add a handler for ssl_ec_point_formats_xtn */
+ { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn },
+ { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
+ { ssl_next_proto_neg_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
{ -1, NULL }
};
-static const ssl3HelloExtensionHandler serverHelloHandlers[] = {
- { server_name_xtn, &ssl3_HandleServerNameXtn },
- /* TODO: add a handler for ec_point_formats_xtn */
- { session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn },
- { next_proto_neg_xtn, &ssl3_ClientHandleNextProtoNegoXtn },
+static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = {
+ { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
{ -1, NULL }
};
-/* Table of functions to format TLS hello extensions, one per extension.
- * This static table is for the formatting of client hello extensions.
+/* Tables of functions to format TLS hello extensions, one function per
+ * extension.
+ * These static tables are for the formatting of client hello extensions.
* The server's table of hello senders is dynamic, in the socket struct,
* and sender functions are registered there.
*/
static const
-ssl3HelloExtensionSender clientHelloSenders[MAX_EXTENSIONS] = {
- { server_name_xtn, &ssl3_SendServerNameXtn },
+ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
+ { ssl_server_name_xtn, &ssl3_SendServerNameXtn },
+ { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn },
#ifdef NSS_ENABLE_ECC
- { elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn },
- { ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn },
-#else
- { -1, NULL },
- { -1, NULL },
+ { ssl_elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn },
+ { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn },
#endif
- { session_ticket_xtn, ssl3_SendSessionTicketXtn },
- { next_proto_neg_xtn, ssl3_ClientSendNextProtoNegoXtn }
+ { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn },
+ { ssl_next_proto_neg_xtn, &ssl3_ClientSendNextProtoNegoXtn }
+ /* any extra entries will appear as { 0, NULL } */
+};
+
+static const
+ssl3HelloExtensionSender clientHelloSendersSSL3[SSL_MAX_EXTENSIONS] = {
+ { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }
+ /* any extra entries will appear as { 0, NULL } */
};
static PRBool
@@ -287,60 +307,159 @@ ssl3_ClientExtensionAdvertised(sslSocket *ss, PRUint16 ex_type) {
/* Format an SNI extension, using the name from the socket's URL,
* unless that name is a dotted decimal string.
+ * Used by client and server.
*/
-static PRInt32
-ssl3_SendServerNameXtn(
- sslSocket * ss,
- PRBool append,
- PRUint32 maxBytes)
+PRInt32
+ssl3_SendServerNameXtn(sslSocket * ss, PRBool append,
+ PRUint32 maxBytes)
{
- PRUint32 len;
- PRNetAddr netAddr;
-
- /* must have a hostname */
- if (!ss || !ss->url || !ss->url[0])
- return 0;
- /* must not be an IPv4 or IPv6 address */
- if (PR_SUCCESS == PR_StringToNetAddr(ss->url, &netAddr)) {
- /* is an IP address (v4 or v6) */
- return 0;
+ SECStatus rv;
+ if (!ss->sec.isServer) {
+ PRUint32 len;
+ PRNetAddr netAddr;
+
+ /* must have a hostname */
+ if (!ss || !ss->url || !ss->url[0])
+ return 0;
+ /* must not be an IPv4 or IPv6 address */
+ if (PR_SUCCESS == PR_StringToNetAddr(ss->url, &netAddr)) {
+ /* is an IP address (v4 or v6) */
+ return 0;
+ }
+ len = PORT_Strlen(ss->url);
+ if (append && maxBytes >= len + 9) {
+ /* extension_type */
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_server_name_xtn, 2);
+ if (rv != SECSuccess) return -1;
+ /* length of extension_data */
+ rv = ssl3_AppendHandshakeNumber(ss, len + 5, 2);
+ if (rv != SECSuccess) return -1;
+ /* length of server_name_list */
+ rv = ssl3_AppendHandshakeNumber(ss, len + 3, 2);
+ if (rv != SECSuccess) return -1;
+ /* Name Type (sni_host_name) */
+ rv = ssl3_AppendHandshake(ss, "\0", 1);
+ if (rv != SECSuccess) return -1;
+ /* HostName (length and value) */
+ rv = ssl3_AppendHandshakeVariable(ss, (PRUint8 *)ss->url, len, 2);
+ if (rv != SECSuccess) return -1;
+ if (!ss->sec.isServer) {
+ TLSExtensionData *xtnData = &ss->xtnData;
+ xtnData->advertised[xtnData->numAdvertised++] =
+ ssl_server_name_xtn;
+ }
+ }
+ return len + 9;
}
- len = PORT_Strlen(ss->url);
- if (append && maxBytes >= len + 9) {
- SECStatus rv;
- /* extension_type */
- rv = ssl3_AppendHandshakeNumber(ss, server_name_xtn, 2);
- if (rv != SECSuccess) return -1;
- /* length of extension_data */
- rv = ssl3_AppendHandshakeNumber(ss, len + 5, 2);
- if (rv != SECSuccess) return -1;
- /* length of server_name_list */
- rv = ssl3_AppendHandshakeNumber(ss, len + 3, 2);
- if (rv != SECSuccess) return -1;
- /* Name Type (host_name) */
- rv = ssl3_AppendHandshake(ss, "\0", 1);
- if (rv != SECSuccess) return -1;
- /* HostName (length and value) */
- rv = ssl3_AppendHandshakeVariable(ss, (unsigned char *)ss->url, len, 2);
- if (rv != SECSuccess) return -1;
- if (!ss->sec.isServer) {
- TLSExtensionData *xtnData = &ss->xtnData;
- xtnData->advertised[xtnData->numAdvertised++] = server_name_xtn;
- }
+ /* Server side */
+ if (append && maxBytes >= 4) {
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_server_name_xtn, 2);
+ if (rv != SECSuccess) return -1;
+ /* length of extension_data */
+ rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
+ if (rv != SECSuccess) return -1;
}
- return len + 9;
+ return 4;
}
/* handle an incoming SNI extension, by ignoring it. */
SECStatus
ssl3_HandleServerNameXtn(sslSocket * ss, PRUint16 ex_type, SECItem *data)
{
- /* TODO: if client, should verify extension_data is empty. */
- /* TODO: if server, should send empty extension_data. */
- /* For now, we ignore this, as if we didn't understand it. :-) */
+ SECItem *names = NULL;
+ PRUint32 listCount = 0, namesPos = 0, i;
+ TLSExtensionData *xtnData = &ss->xtnData;
+ SECItem ldata;
+ PRInt32 listLenBytes = 0;
+
+ if (!ss->sec.isServer) {
+ /* Verify extension_data is empty. */
+ if (data->data || data->len ||
+ !ssl3_ExtensionNegotiated(ss, ssl_server_name_xtn)) {
+ /* malformed or was not initiated by the client.*/
+ return SECFailure;
+ }
+ return SECSuccess;
+ }
+
+ /* Server side - consume client data and register server sender. */
+ /* do not parse the data if don't have user extension handling function. */
+ if (!ss->sniSocketConfig) {
+ return SECSuccess;
+ }
+ /* length of server_name_list */
+ listLenBytes = ssl3_ConsumeHandshakeNumber(ss, 2, &data->data, &data->len);
+ if (listLenBytes == 0 || listLenBytes != data->len) {
+ return SECFailure;
+ }
+ ldata = *data;
+ /* Calculate the size of the array.*/
+ while (listLenBytes > 0) {
+ SECItem litem;
+ SECStatus rv;
+ PRInt32 type;
+ /* Name Type (sni_host_name) */
+ type = ssl3_ConsumeHandshakeNumber(ss, 1, &ldata.data, &ldata.len);
+ if (!ldata.len) {
+ return SECFailure;
+ }
+ rv = ssl3_ConsumeHandshakeVariable(ss, &litem, 2, &ldata.data, &ldata.len);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+ /* Adjust total length for cunsumed item, item len and type.*/
+ listLenBytes -= litem.len + 3;
+ if (listLenBytes > 0 && !ldata.len) {
+ return SECFailure;
+ }
+ listCount += 1;
+ }
+ if (!listCount) {
+ return SECFailure;
+ }
+ names = PORT_ZNewArray(SECItem, listCount);
+ if (!names) {
+ return SECFailure;
+ }
+ for (i = 0;i < listCount;i++) {
+ int j;
+ PRInt32 type;
+ SECStatus rv;
+ PRBool nametypePresent = PR_FALSE;
+ /* Name Type (sni_host_name) */
+ type = ssl3_ConsumeHandshakeNumber(ss, 1, &data->data, &data->len);
+ /* Check if we have such type in the list */
+ for (j = 0;j < listCount && names[j].data;j++) {
+ if (names[j].type == type) {
+ nametypePresent = PR_TRUE;
+ break;
+ }
+ }
+ /* HostName (length and value) */
+ rv = ssl3_ConsumeHandshakeVariable(ss, &names[namesPos], 2,
+ &data->data, &data->len);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ if (nametypePresent == PR_FALSE) {
+ namesPos += 1;
+ }
+ }
+ /* Free old and set the new data. */
+ if (xtnData->sniNameArr) {
+ PORT_Free(ss->xtnData.sniNameArr);
+ }
+ xtnData->sniNameArr = names;
+ xtnData->sniNameArrSize = namesPos;
+ xtnData->negotiated[xtnData->numNegotiated++] = ssl_server_name_xtn;
+
return SECSuccess;
-}
+loser:
+ PORT_Free(names);
+ return SECFailure;
+}
+
/* Called by both clients and servers.
* Clients sends a filled in session ticket if one is available, and otherwise
* sends an empty ticket. Servers always send empty tickets.
@@ -386,7 +505,7 @@ ssl3_SendSessionTicketXtn(
if (append && maxBytes >= extension_length) {
SECStatus rv;
/* extension_type */
- rv = ssl3_AppendHandshakeNumber(ss, session_ticket_xtn, 2);
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_session_ticket_xtn, 2);
if (rv != SECSuccess)
goto loser;
if (session_ticket && session_ticket->ticket.data &&
@@ -402,7 +521,8 @@ ssl3_SendSessionTicketXtn(
if (!ss->sec.isServer) {
TLSExtensionData *xtnData = &ss->xtnData;
- xtnData->advertised[xtnData->numAdvertised++] = session_ticket_xtn;
+ xtnData->advertised[xtnData->numAdvertised++] =
+ ssl_session_ticket_xtn;
}
} else if (maxBytes < extension_length) {
PORT_Assert(0);
@@ -514,15 +634,14 @@ ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss,
if (append && maxBytes >= extension_length) {
SECStatus rv;
- TLSExtensionData *xtnData;
- rv = ssl3_AppendHandshakeNumber(ss, next_proto_neg_xtn, 2);
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_next_proto_neg_xtn, 2);
if (rv != SECSuccess)
goto loser;
rv = ssl3_AppendHandshakeNumber(ss, 0, 2);
if (rv != SECSuccess)
goto loser;
- xtnData = &ss->xtnData;
- xtnData->advertised[xtnData->numAdvertised++] = next_proto_neg_xtn;
+ ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
+ ssl_next_proto_neg_xtn;
} else if (maxBytes < extension_length) {
return 0;
}
@@ -575,6 +694,8 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
unsigned int computed_mac_length;
unsigned char iv[AES_BLOCK_SIZE];
SECItem ivItem;
+ SECItem *srvName = NULL;
+ PRUint32 srvNameLen = 0;
CK_MECHANISM_TYPE msWrapMech = 0; /* dummy default value,
* must be >= 0 */
@@ -635,6 +756,11 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
}
ms_is_wrapped = PR_TRUE;
}
+ /* Prep to send negotiated name */
+ srvName = &ss->ssl3.pwSpec->srvVirtName;
+ if (srvName->data && srvName->len) {
+ srvNameLen = 2 + srvName->len; /* len bytes + name len */
+ }
ciphertext_length =
sizeof(PRUint16) /* ticket_version */
@@ -649,6 +775,8 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
+ ms_item.len /* master_secret */
+ 1 /* client_auth_type */
+ cert_length /* cert */
+ + 1 /* server name type */
+ + srvNameLen /* name len + length field */
+ sizeof(ticket.ticket_lifetime_hint);
padding_length = AES_BLOCK_SIZE -
(ciphertext_length % AES_BLOCK_SIZE);
@@ -731,6 +859,22 @@ ssl3_SendNewSessionTicket(sslSocket *ss)
sizeof(ticket.ticket_lifetime_hint));
if (rv != SECSuccess) goto loser;
+ if (srvNameLen) {
+ /* Name Type (sni_host_name) */
+ rv = ssl3_AppendNumberToItem(&plaintext, srvName->type, 1);
+ if (rv != SECSuccess) goto loser;
+ /* HostName (length and value) */
+ rv = ssl3_AppendNumberToItem(&plaintext, srvName->len, 2);
+ if (rv != SECSuccess) goto loser;
+ rv = ssl3_AppendToItem(&plaintext, srvName->data, srvName->len);
+ if (rv != SECSuccess) goto loser;
+ } else {
+ /* No Name */
+ rv = ssl3_AppendNumberToItem(&plaintext, (char)TLS_STE_NO_SERVER_NAME,
+ 1);
+ if (rv != SECSuccess) goto loser;
+ }
+
PORT_Assert(plaintext.len == padding_length);
for (i = 0; i < padding_length; i++)
plaintext.data[i] = (unsigned char)padding_length;
@@ -903,6 +1047,7 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
unsigned int buffer_len;
PRInt32 temp;
SECItem cert_item;
+ PRInt8 nameType = TLS_STE_NO_SERVER_NAME;
/* Turn off stateless session resumption if the client sends a
* SessionTicket extension, even if the extension turns out to be
@@ -1155,6 +1300,20 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
goto no_ticket;
parsed_session_ticket->timestamp = (PRUint32)temp;
+ /* Read server name */
+ nameType =
+ ssl3_ConsumeHandshakeNumber(ss, 1, &buffer, &buffer_len);
+ if (nameType != TLS_STE_NO_SERVER_NAME) {
+ SECItem name_item;
+ rv = ssl3_ConsumeHandshakeVariable(ss, &name_item, 2, &buffer,
+ &buffer_len);
+ if (rv != SECSuccess) goto no_ticket;
+ rv = SECITEM_CopyItem(NULL, &parsed_session_ticket->srvName,
+ &name_item);
+ if (rv != SECSuccess) goto no_ticket;
+ parsed_session_ticket->srvName.type = nameType;
+ }
+
/* Done parsing. Check that all bytes have been consumed. */
if (buffer_len != padding_length)
goto no_ticket;
@@ -1211,6 +1370,9 @@ ssl3_ServerHandleSessionTicketXtn(sslSocket *ss, PRUint16 ex_type,
goto loser;
}
}
+ if (parsed_session_ticket->srvName.data != NULL) {
+ sid->u.ssl3.srvName = parsed_session_ticket->srvName;
+ }
ss->statelessResume = PR_TRUE;
ss->sec.ci.sid = sid;
}
@@ -1293,8 +1455,15 @@ ssl3_ParseEncryptedSessionTicket(sslSocket *ss, SECItem *data,
SECStatus
ssl3_HandleHelloExtensions(sslSocket *ss, SSL3Opaque **b, PRUint32 *length)
{
- const ssl3HelloExtensionHandler * handlers =
- ss->sec.isServer ? clientHelloHandlers : serverHelloHandlers;
+ const ssl3HelloExtensionHandler * handlers;
+
+ if (ss->sec.isServer) {
+ handlers = clientHelloHandlers;
+ } else if (ss->version > SSL_LIBRARY_VERSION_3_0) {
+ handlers = serverHelloHandlersTLS;
+ } else {
+ handlers = serverHelloHandlersSSL3;
+ }
while (*length) {
const ssl3HelloExtensionHandler * handler;
@@ -1347,7 +1516,7 @@ ssl3_RegisterServerHelloExtensionSender(sslSocket *ss, PRUint16 ex_type,
int i;
ssl3HelloExtensionSender *sender = &ss->xtnData.serverSenders[0];
- for (i = 0; i < MAX_EXTENSIONS; ++i, ++sender) {
+ for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) {
if (!sender->ex_sender) {
sender->ex_type = ex_type;
sender->ex_sender = cb;
@@ -1360,7 +1529,7 @@ ssl3_RegisterServerHelloExtensionSender(sslSocket *ss, PRUint16 ex_type,
break;
}
}
- PORT_Assert(i < MAX_EXTENSIONS); /* table needs to grow */
+ PORT_Assert(i < SSL_MAX_EXTENSIONS); /* table needs to grow */
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
@@ -1373,10 +1542,12 @@ ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
PRInt32 total_exten_len = 0;
int i;
- if (!sender)
- sender = &clientHelloSenders[0];
+ if (!sender) {
+ sender = ss->version > SSL_LIBRARY_VERSION_3_0 ?
+ &clientHelloSendersTLS[0] : &clientHelloSendersSSL3[0];
+ }
- for (i = 0; i < MAX_EXTENSIONS; ++i, ++sender) {
+ for (i = 0; i < SSL_MAX_EXTENSIONS; ++i, ++sender) {
if (sender->ex_sender) {
PRInt32 extLen = (*sender->ex_sender)(ss, append, maxBytes);
if (extLen < 0)
@@ -1387,3 +1558,82 @@ ssl3_CallHelloExtensionSenders(sslSocket *ss, PRBool append, PRUint32 maxBytes,
}
return total_exten_len;
}
+
+
+/* Extension format:
+ * Extension number: 2 bytes
+ * Extension length: 2 bytes
+ * Verify Data Length: 1 byte
+ * Verify Data (TLS): 12 bytes (client) or 24 bytes (server)
+ * Verify Data (SSL): 36 bytes (client) or 72 bytes (server)
+ */
+static PRInt32
+ssl3_SendRenegotiationInfoXtn(
+ sslSocket * ss,
+ PRBool append,
+ PRUint32 maxBytes)
+{
+ PRInt32 len, needed;
+
+ /* In draft-ietf-tls-renegotiation-03, it is NOT RECOMMENDED to send
+ * both the SCSV and the empty RI, so when we send SCSV in
+ * the initial handshake, we don't also send RI.
+ */
+ if (!ss || ss->ssl3.hs.sendingSCSV)
+ return 0;
+ len = !ss->firstHsDone ? 0 :
+ (ss->sec.isServer ? ss->ssl3.hs.finishedBytes * 2
+ : ss->ssl3.hs.finishedBytes);
+ needed = 5 + len;
+ if (append && maxBytes >= needed) {
+ SECStatus rv;
+ /* extension_type */
+ rv = ssl3_AppendHandshakeNumber(ss, ssl_renegotiation_info_xtn, 2);
+ if (rv != SECSuccess) return -1;
+ /* length of extension_data */
+ rv = ssl3_AppendHandshakeNumber(ss, len + 1, 2);
+ if (rv != SECSuccess) return -1;
+ /* verify_Data from previous Finished message(s) */
+ rv = ssl3_AppendHandshakeVariable(ss,
+ ss->ssl3.hs.finishedMsgs.data, len, 1);
+ if (rv != SECSuccess) return -1;
+ if (!ss->sec.isServer) {
+ TLSExtensionData *xtnData = &ss->xtnData;
+ xtnData->advertised[xtnData->numAdvertised++] =
+ ssl_renegotiation_info_xtn;
+ }
+ }
+ return needed;
+}
+
+/* This function runs in both the client and server. */
+static SECStatus
+ssl3_HandleRenegotiationInfoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
+{
+ SECStatus rv = SECSuccess;
+ PRUint32 len = 0;
+
+ if (ss->firstHsDone) {
+ len = ss->sec.isServer ? ss->ssl3.hs.finishedBytes
+ : ss->ssl3.hs.finishedBytes * 2;
+ }
+ if (data->len != 1 + len ||
+ data->data[0] != len || (len &&
+ NSS_SecureMemcmp(ss->ssl3.hs.finishedMsgs.data,
+ data->data + 1, len))) {
+ /* Can we do this here? Or, must we arrange for the caller to do it? */
+ (void)SSL3_SendAlert(ss, alert_fatal, handshake_failure);
+ PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
+ return SECFailure;
+ }
+ /* remember that we got this extension and it was correct. */
+ ss->peerRequestedProtection = 1;
+ ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
+ if (ss->sec.isServer) {
+ /* prepare to send back the appropriate response */
+ rv = ssl3_RegisterServerHelloExtensionSender(ss, ex_type,
+ ssl3_SendRenegotiationInfoXtn);
+ }
+ return rv;
+}
+
diff --git a/net/third_party/nss/ssl/ssl3prot.h b/net/third_party/nss/ssl/ssl3prot.h
index 84d73a9..c82c891 100644
--- a/net/third_party/nss/ssl/ssl3prot.h
+++ b/net/third_party/nss/ssl/ssl3prot.h
@@ -38,7 +38,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-/* $Id: ssl3prot.h,v 1.15 2009/11/07 18:23:06 wtc%google.com Exp $ */
+/* $Id: ssl3prot.h,v 1.18 2010/02/03 02:25:35 alexei.volkov.bugs%sun.com Exp $ */
#ifndef __ssl3proto_h_
#define __ssl3proto_h_
@@ -344,20 +344,8 @@ typedef struct {
unsigned char *mac;
} EncryptedSessionTicket;
-/* Supported extensions. */
-/* Update MAX_EXTENSIONS whenever a new extension type is added. */
-typedef enum {
- server_name_xtn = 0,
-#ifdef NSS_ENABLE_ECC
- elliptic_curves_xtn = 10,
- ec_point_formats_xtn = 11,
-#endif
- session_ticket_xtn = 35,
- next_proto_neg_xtn = 13172
-} ExtensionType;
-
-#define MAX_EXTENSIONS 5
-
#define TLS_EX_SESS_TICKET_MAC_LENGTH 32
+#define TLS_STE_NO_SERVER_NAME -1
+
#endif /* __ssl3proto_h_ */
diff --git a/net/third_party/nss/ssl/sslcon.c b/net/third_party/nss/ssl/sslcon.c
index 500b787..c02b315 100644
--- a/net/third_party/nss/ssl/sslcon.c
+++ b/net/third_party/nss/ssl/sslcon.c
@@ -37,7 +37,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-/* $Id: sslcon.c,v 1.37 2009/10/16 17:45:35 wtc%google.com Exp $ */
+/* $Id: sslcon.c,v 1.39 2010/02/04 03:08:44 wtc%google.com Exp $ */
#include "nssrenam.h"
#include "cert.h"
@@ -3007,6 +3007,7 @@ ssl2_BeginClientHandshake(sslSocket *ss)
unsigned int i;
int sendLen, sidLen = 0;
SECStatus rv;
+ TLSExtensionData *xtnData;
PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
@@ -3151,7 +3152,8 @@ ssl2_BeginClientHandshake(sslSocket *ss)
localCipherSpecs = ss->cipherSpecs;
localCipherSize = ss->sizeCipherSpecs;
- sendLen = SSL_HL_CLIENT_HELLO_HBYTES + localCipherSize + sidLen +
+ /* Add 3 for SCSV */
+ sendLen = SSL_HL_CLIENT_HELLO_HBYTES + localCipherSize + 3 + sidLen +
SSL_CHALLENGE_BYTES;
/* Generate challenge bytes for server */
@@ -3176,8 +3178,9 @@ ssl2_BeginClientHandshake(sslSocket *ss)
msg[1] = MSB(ss->clientHelloVersion);
msg[2] = LSB(ss->clientHelloVersion);
- msg[3] = MSB(localCipherSize);
- msg[4] = LSB(localCipherSize);
+ /* Add 3 for SCSV */
+ msg[3] = MSB(localCipherSize + 3);
+ msg[4] = LSB(localCipherSize + 3);
msg[5] = MSB(sidLen);
msg[6] = LSB(sidLen);
msg[7] = MSB(SSL_CHALLENGE_BYTES);
@@ -3185,6 +3188,16 @@ ssl2_BeginClientHandshake(sslSocket *ss)
cp += SSL_HL_CLIENT_HELLO_HBYTES;
PORT_Memcpy(cp, localCipherSpecs, localCipherSize);
cp += localCipherSize;
+ /*
+ * Add SCSV. SSL 2.0 cipher suites are listed before SSL 3.0 cipher
+ * suites in localCipherSpecs for compatibility with SSL 2.0 servers.
+ * Since SCSV looks like an SSL 3.0 cipher suite, we can't add it at
+ * the beginning.
+ */
+ cp[0] = 0x00;
+ cp[1] = 0x00;
+ cp[2] = 0xff;
+ cp += 3;
if (sidLen) {
PORT_Memcpy(cp, sid->u.ssl2.sessionID, sidLen);
cp += sidLen;
@@ -3207,6 +3220,14 @@ ssl2_BeginClientHandshake(sslSocket *ss)
goto loser;
}
+ /*
+ * Since we sent the SCSV, pretend we sent empty RI extension. We need
+ * to record the extension has been advertised after ssl3_InitState has
+ * been called, which ssl3_StartHandshakeHash took care for us above.
+ */
+ xtnData = &ss->xtnData;
+ xtnData->advertised[xtnData->numAdvertised++] = ssl_renegotiation_info_xtn;
+
/* Setup to receive servers hello message */
ssl_GetRecvBufLock(ss);
ss->gs.recordLen = 0;
diff --git a/net/third_party/nss/ssl/sslerr.h b/net/third_party/nss/ssl/sslerr.h
index c132ab9..61b721c 100644
--- a/net/third_party/nss/ssl/sslerr.h
+++ b/net/third_party/nss/ssl/sslerr.h
@@ -36,7 +36,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-/* $Id: sslerr.h,v 1.8 2009/11/06 20:11:28 nelson%bolyard.com Exp $ */
+/* $Id: sslerr.h,v 1.10 2010/02/03 03:44:29 wtc%google.com Exp $ */
#ifndef __SSL_ERR_H_
#define __SSL_ERR_H_
@@ -197,6 +197,9 @@ SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET = (SSL_ERROR_BASE + 110),
SSL_ERROR_DECOMPRESSION_FAILURE = (SSL_ERROR_BASE + 111),
SSL_ERROR_RENEGOTIATION_NOT_ALLOWED = (SSL_ERROR_BASE + 112),
+SSL_ERROR_UNSAFE_NEGOTIATION = (SSL_ERROR_BASE + 113),
+
+SSL_ERROR_RX_UNEXPECTED_UNCOMPRESSED_RECORD = (SSL_ERROR_BASE + 114),
SSL_ERROR_END_OF_LIST /* let the c compiler determine the value of this. */
} SSLErrorCodes;
diff --git a/net/third_party/nss/ssl/sslimpl.h b/net/third_party/nss/ssl/sslimpl.h
index 6f2316a..0ec579d 100644
--- a/net/third_party/nss/ssl/sslimpl.h
+++ b/net/third_party/nss/ssl/sslimpl.h
@@ -39,7 +39,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-/* $Id: sslimpl.h,v 1.70 2009/11/21 03:40:49 wtc%google.com Exp $ */
+/* $Id: sslimpl.h,v 1.76 2010/02/04 03:08:45 wtc%google.com Exp $ */
#ifndef __sslimpl_h_
#define __sslimpl_h_
@@ -137,7 +137,7 @@ extern int Debug;
#endif
#define ssl_InMonitor(m) PZ_InMonitor(m)
-#define LSB(x) ((unsigned char) (x & 0xff))
+#define LSB(x) ((unsigned char) ((x) & 0xff))
#define MSB(x) ((unsigned char) (((unsigned)(x)) >> 8))
/************************************************************************/
@@ -561,6 +561,9 @@ typedef struct {
SECItem msItem;
unsigned char key_block[NUM_MIXERS * MD5_LENGTH];
unsigned char raw_master_secret[56];
+ SECItem srvVirtName; /* for server: name that was negotiated
+ * with a client. For client - is
+ * always set to NULL.*/
} ssl3CipherSpec;
typedef enum { never_cached,
@@ -656,6 +659,7 @@ struct sslSessionIDStr {
* ClientHello message. This field is used by clients.
*/
NewSessionTicket sessionTicket;
+ SECItem srvName;
} ssl3;
} u;
};
@@ -730,16 +734,23 @@ typedef struct SessionTicketDataStr SessionTicketData;
struct TLSExtensionDataStr {
/* registered callbacks that send server hello extensions */
- ssl3HelloExtensionSender serverSenders[MAX_EXTENSIONS];
+ ssl3HelloExtensionSender serverSenders[SSL_MAX_EXTENSIONS];
/* Keep track of the extensions that are negotiated. */
PRUint16 numAdvertised;
PRUint16 numNegotiated;
- PRUint16 advertised[MAX_EXTENSIONS];
- PRUint16 negotiated[MAX_EXTENSIONS];
+ PRUint16 advertised[SSL_MAX_EXTENSIONS];
+ PRUint16 negotiated[SSL_MAX_EXTENSIONS];
/* SessionTicket Extension related data. */
PRBool ticketTimestampVerified;
PRBool emptySessionTicket;
+
+ /* SNI Extension related data
+ * Names data is not coppied from the input buffer. It can not be
+ * used outside the scope where input buffer is defined and that
+ * is beyond ssl3_HandleClientHello function. */
+ SECItem *sniNameArr;
+ PRUint32 sniNameArrSize;
};
/*
@@ -770,9 +781,16 @@ const ssl3CipherSuiteDef *suite_def;
PRBool rehandshake; /* immediately start another handshake
* when this one finishes */
PRBool usedStepDownKey; /* we did a server key exchange. */
+ PRBool sendingSCSV; /* instead of empty RI */
sslBuffer msgState; /* current state for handshake messages*/
/* protected by recvBufLock */
sslBuffer messages; /* Accumulated handshake messages */
+ PRUint16 finishedBytes; /* size of single finished below */
+ union {
+ TLSFinished tFinished[2]; /* client, then server */
+ SSL3Hashes sFinished[2];
+ SSL3Opaque data[72];
+ } finishedMsgs;
#ifdef NSS_ENABLE_ECC
PRUint32 negotiatedECCurves; /* bit mask */
#endif /* NSS_ENABLE_ECC */
@@ -877,6 +895,7 @@ typedef struct SessionTicketStr {
ClientIdentity client_identity;
SECItem peer_cert;
uint32 timestamp;
+ SECItem srvName; /* negotiated server name */
} SessionTicket;
/*
@@ -1022,6 +1041,7 @@ struct sslSocketStr {
unsigned long recvdCloseNotify; /* received SSL EOF. */
unsigned long TCPconnected;
unsigned long appDataBuffered;
+ unsigned long peerRequestedProtection; /* from old renegotiation */
/* version of the protocol to use */
SSL3ProtocolVersion version;
@@ -1050,6 +1070,8 @@ const unsigned char * preferredCipher;
void *authCertificateArg;
SSLGetClientAuthData getClientAuthData;
void *getClientAuthDataArg;
+ SSLSNISocketConfig sniSocketConfig;
+ void *sniSocketConfigArg;
SSLBadCertHandler handleBadCert;
void *badCertArg;
SSLHandshakeCallback handshakeCallback;
@@ -1130,6 +1152,7 @@ extern NSSRWLock * ssl_global_data_lock;
extern char ssl_debug;
extern char ssl_trace;
extern FILE * ssl_trace_iob;
+extern FILE * ssl_keylog_iob;
extern CERTDistNames * ssl3_server_ca_list;
extern PRUint32 ssl_sid_timeout;
extern PRUint32 ssl3_sid_timeout;
@@ -1501,6 +1524,23 @@ extern SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss,
*/
extern PRInt32 ssl3_SendSessionTicketXtn(sslSocket *ss, PRBool append,
PRUint32 maxBytes);
+
+/* ClientHello and ServerHello extension senders.
+ * The code is in ssl3ext.c.
+ */
+extern PRInt32 ssl3_SendServerNameXtn(sslSocket *ss, PRBool append,
+ PRUint32 maxBytes);
+
+/* Assigns new cert, cert chain and keys to ss->serverCerts
+ * struct. If certChain is NULL, tries to find one. Aborts if
+ * fails to do so. If cert and keyPair are NULL - unconfigures
+ * sslSocket of kea type.*/
+extern SECStatus ssl_ConfigSecureServer(sslSocket *ss, CERTCertificate *cert,
+ CERTCertificateList *certChain,
+ ssl3KeyPair *keyPair, SSLKEAType kea);
+/* Return key type for the cert */
+extern SSLKEAType ssl_FindCertKEAType(CERTCertificate * cert);
+
#ifdef NSS_ENABLE_ECC
extern PRInt32 ssl3_SendSupportedCurvesXtn(sslSocket *ss,
PRBool append, PRUint32 maxBytes);
diff --git a/net/third_party/nss/ssl/sslinfo.c b/net/third_party/nss/ssl/sslinfo.c
index baa1ab3..e4ee35f 100644
--- a/net/third_party/nss/ssl/sslinfo.c
+++ b/net/third_party/nss/ssl/sslinfo.c
@@ -34,7 +34,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-/* $Id: sslinfo.c,v 1.21 2009/11/09 22:00:18 wtc%google.com Exp $ */
+/* $Id: sslinfo.c,v 1.23 2010/01/15 01:49:33 alexei.volkov.bugs%sun.com Exp $ */
#include "ssl.h"
#include "sslimpl.h"
#include "sslproto.h"
@@ -307,3 +307,43 @@ SSL_IsExportCipherSuite(PRUint16 cipherSuite)
}
return PR_FALSE;
}
+
+SECItem*
+SSL_GetNegotiatedHostInfo(PRFileDesc *fd)
+{
+ SECItem *sniName = NULL;
+ sslSocket *ss;
+ char *name = NULL;
+
+ ss = ssl_FindSocket(fd);
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_GetNegotiatedHostInfo",
+ SSL_GETPID(), fd));
+ return NULL;
+ }
+
+ if (ss->sec.isServer) {
+ if (ss->version > SSL_LIBRARY_VERSION_3_0 &&
+ ss->ssl3.initialized) { /* TLS */
+ SECItem *crsName;
+ ssl_GetSpecReadLock(ss); /*********************************/
+ crsName = &ss->ssl3.crSpec->srvVirtName;
+ if (crsName->data) {
+ sniName = SECITEM_DupItem(crsName);
+ }
+ ssl_ReleaseSpecReadLock(ss); /*----------------------------*/
+ }
+ return sniName;
+ }
+ name = SSL_RevealURL(fd);
+ if (name) {
+ sniName = PORT_ZNew(SECItem);
+ if (!sniName) {
+ PORT_Free(name);
+ return NULL;
+ }
+ sniName->data = (void*)name;
+ sniName->len = PORT_Strlen(name);
+ }
+ return sniName;
+}
diff --git a/net/third_party/nss/ssl/sslproto.h b/net/third_party/nss/ssl/sslproto.h
index b0b466f..bf7b71b 100644
--- a/net/third_party/nss/ssl/sslproto.h
+++ b/net/third_party/nss/ssl/sslproto.h
@@ -39,7 +39,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-/* $Id: sslproto.h,v 1.13 2008/12/17 06:09:19 nelson%bolyard.com Exp $ */
+/* $Id: sslproto.h,v 1.14 2010/01/28 06:19:12 nelson%bolyard.com Exp $ */
#ifndef __sslproto_h_
#define __sslproto_h_
@@ -181,6 +181,15 @@
#define TLS_RSA_WITH_SEED_CBC_SHA 0x0096
+/* TLS "Signalling Cipher Suite Value" (SCSV). May be requested by client.
+ * Must NEVER be chosen by server. SSL 3.0 server acknowledges by sending
+ * back an empty Renegotiation Info (RI) server hello extension.
+ */
+#define TLS_RENEGO_PROTECTION_REQUEST 0x00FF
+
+/* Cipher Suite Values starting with 0xC000 are defined in informational
+ * RFCs.
+ */
#define TLS_ECDH_ECDSA_WITH_NULL_SHA 0xC001
#define TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xC002
#define TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xC003
diff --git a/net/third_party/nss/ssl/sslreveal.c b/net/third_party/nss/ssl/sslreveal.c
index a981dee..74f8814 100644
--- a/net/third_party/nss/ssl/sslreveal.c
+++ b/net/third_party/nss/ssl/sslreveal.c
@@ -36,7 +36,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-/* $Id: sslreveal.c,v 1.4 2004/04/27 23:04:39 gerv%gerv.net Exp $ */
+/* $Id: sslreveal.c,v 1.7 2010/02/04 03:21:11 wtc%google.com Exp $ */
#include "cert.h"
#include "ssl.h"
@@ -82,7 +82,7 @@ SSL_RevealPinArg(PRFileDesc * fd)
/* given PRFileDesc, returns a pointer to the URL associated with the socket
- * the caller should free url when done
+ * the caller should free url when done
*/
char *
SSL_RevealURL(PRFileDesc * fd)
@@ -98,3 +98,41 @@ SSL_RevealURL(PRFileDesc * fd)
return url;
}
+
+/* given PRFileDesc, returns status information related to extensions
+ * negotiated with peer during the handshake.
+ */
+
+SECStatus
+SSL_HandshakeNegotiatedExtension(PRFileDesc * socket,
+ SSLExtensionType extId,
+ PRBool *pYes)
+{
+ /* some decisions derived from SSL_GetChannelInfo */
+ sslSocket * sslsocket = NULL;
+ SECStatus rv = SECFailure;
+
+ if (!pYes)
+ return rv;
+
+ sslsocket = ssl_FindSocket(socket);
+
+ /* according to public API SSL_GetChannelInfo, this doesn't need a lock */
+ if (sslsocket && sslsocket->opt.useSecurity && sslsocket->firstHsDone) {
+ if (sslsocket->ssl3.initialized) { /* SSL3 and TLS */
+ /* now we know this socket went through ssl3_InitState() and
+ * ss->xtnData got initialized, which is the only member accessed by
+ * ssl3_ExtensionNegotiated();
+ * Member xtnData appears to get accessed in functions that handle
+ * the handshake (hello messages and extension sending),
+ * therefore the handshake lock should be sufficient.
+ */
+ ssl_GetSSL3HandshakeLock(sslsocket);
+ *pYes = ssl3_ExtensionNegotiated(sslsocket, extId);
+ ssl_ReleaseSSL3HandshakeLock(sslsocket);
+ rv = SECSuccess;
+ }
+ }
+
+ return rv;
+}
diff --git a/net/third_party/nss/ssl/sslsecur.c b/net/third_party/nss/ssl/sslsecur.c
index c13100a..80c2ba6 100644
--- a/net/third_party/nss/ssl/sslsecur.c
+++ b/net/third_party/nss/ssl/sslsecur.c
@@ -37,7 +37,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-/* $Id: sslsecur.c,v 1.42 2008/10/03 19:20:20 wtc%google.com Exp $ */
+/* $Id: sslsecur.c,v 1.43 2010/01/14 22:15:25 alexei.volkov.bugs%sun.com Exp $ */
#include "cert.h"
#include "secitem.h"
#include "keyhi.h"
@@ -672,6 +672,79 @@ static PRStatus serverCAListSetup(void *arg)
return PR_FAILURE;
}
+SECStatus
+ssl_ConfigSecureServer(sslSocket *ss, CERTCertificate *cert,
+ CERTCertificateList *certChain,
+ ssl3KeyPair *keyPair, SSLKEAType kea)
+{
+ CERTCertificateList *localCertChain = NULL;
+ sslServerCerts *sc = ss->serverCerts + kea;
+
+ /* load the server certificate */
+ if (sc->serverCert != NULL) {
+ CERT_DestroyCertificate(sc->serverCert);
+ sc->serverCert = NULL;
+ sc->serverKeyBits = 0;
+ }
+ /* load the server cert chain */
+ if (sc->serverCertChain != NULL) {
+ CERT_DestroyCertificateList(sc->serverCertChain);
+ sc->serverCertChain = NULL;
+ }
+ if (cert) {
+ sc->serverCert = CERT_DupCertificate(cert);
+ /* get the size of the cert's public key, and remember it */
+ sc->serverKeyBits = SECKEY_PublicKeyStrengthInBits(keyPair->pubKey);
+ if (!certChain) {
+ localCertChain =
+ CERT_CertChainFromCert(sc->serverCert, certUsageSSLServer,
+ PR_TRUE);
+ if (!localCertChain)
+ goto loser;
+ }
+ sc->serverCertChain = (certChain) ? CERT_DupCertList(certChain) :
+ localCertChain;
+ if (!sc->serverCertChain) {
+ goto loser;
+ }
+ localCertChain = NULL; /* consumed */
+ }
+
+ /* get keyPair */
+ if (sc->serverKeyPair != NULL) {
+ ssl3_FreeKeyPair(sc->serverKeyPair);
+ sc->serverKeyPair = NULL;
+ }
+ if (keyPair) {
+ SECKEY_CacheStaticFlags(keyPair->privKey);
+ sc->serverKeyPair = ssl3_GetKeyPairRef(keyPair);
+ }
+ if (kea == kt_rsa && cert && sc->serverKeyBits > 512 &&
+ !ss->opt.noStepDown && !ss->stepDownKeyPair) {
+ if (ssl3_CreateRSAStepDownKeys(ss) != SECSuccess) {
+ goto loser;
+ }
+ }
+ return SECSuccess;
+
+loser:
+ if (localCertChain) {
+ CERT_DestroyCertificateList(localCertChain);
+ }
+ if (sc->serverCert != NULL) {
+ CERT_DestroyCertificate(sc->serverCert);
+ sc->serverCert = NULL;
+ }
+ if (sc->serverCertChain != NULL) {
+ CERT_DestroyCertificateList(sc->serverCertChain);
+ sc->serverCertChain = NULL;
+ }
+ if (sc->serverKeyPair != NULL) {
+ ssl3_FreeKeyPair(sc->serverKeyPair);
+ sc->serverKeyPair = NULL;
+ }
+ return SECFailure;
+}
/* XXX need to protect the data that gets changed here.!! */
@@ -679,10 +752,10 @@ SECStatus
SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert,
SECKEYPrivateKey *key, SSL3KEAType kea)
{
- SECStatus rv;
sslSocket *ss;
- sslServerCerts *sc;
- SECKEYPublicKey * pubKey = NULL;
+ SECKEYPublicKey *pubKey = NULL;
+ ssl3KeyPair *keyPair = NULL;
+ SECStatus rv = SECFailure;
ss = ssl_FindSocket(fd);
if (!ss) {
@@ -708,41 +781,13 @@ SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert,
return SECFailure;
}
- sc = ss->serverCerts + kea;
- /* load the server certificate */
- if (sc->serverCert != NULL) {
- CERT_DestroyCertificate(sc->serverCert);
- sc->serverCert = NULL;
- }
if (cert) {
- sc->serverCert = CERT_DupCertificate(cert);
- if (!sc->serverCert)
- goto loser;
/* get the size of the cert's public key, and remember it */
pubKey = CERT_ExtractPublicKey(cert);
if (!pubKey)
- goto loser;
- sc->serverKeyBits = SECKEY_PublicKeyStrengthInBits(pubKey);
- }
-
-
- /* load the server cert chain */
- if (sc->serverCertChain != NULL) {
- CERT_DestroyCertificateList(sc->serverCertChain);
- sc->serverCertChain = NULL;
- }
- if (cert) {
- sc->serverCertChain = CERT_CertChainFromCert(
- sc->serverCert, certUsageSSLServer, PR_TRUE);
- if (sc->serverCertChain == NULL)
- goto loser;
+ return SECFailure;
}
- /* load the private key */
- if (sc->serverKeyPair != NULL) {
- ssl3_FreeKeyPair(sc->serverKeyPair);
- sc->serverKeyPair = NULL;
- }
if (key) {
SECKEYPrivateKey * keyCopy = NULL;
CK_MECHANISM_TYPE keyMech = CKM_INVALID_MECHANISM;
@@ -770,51 +815,34 @@ SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert,
keyCopy = SECKEY_CopyPrivateKey(key);
if (keyCopy == NULL)
goto loser;
- SECKEY_CacheStaticFlags(keyCopy);
- sc->serverKeyPair = ssl3_NewKeyPair(keyCopy, pubKey);
- if (sc->serverKeyPair == NULL) {
+ keyPair = ssl3_NewKeyPair(keyCopy, pubKey);
+ if (keyPair == NULL) {
SECKEY_DestroyPrivateKey(keyCopy);
goto loser;
}
pubKey = NULL; /* adopted by serverKeyPair */
}
-
- if (kea == kt_rsa && cert && sc->serverKeyBits > 512) {
- if (ss->opt.noStepDown) {
- /* disable all export ciphersuites */
- } else {
- rv = ssl3_CreateRSAStepDownKeys(ss);
- if (rv != SECSuccess) {
- return SECFailure; /* err set by ssl3_CreateRSAStepDownKeys */
- }
- }
+ if (ssl_ConfigSecureServer(ss, cert, NULL,
+ keyPair, kea) == SECFailure) {
+ goto loser;
}
/* Only do this once because it's global. */
if (PR_SUCCESS == PR_CallOnceWithArg(&setupServerCAListOnce,
&serverCAListSetup,
(void *)(ss->dbHandle))) {
- return SECSuccess;
+ rv = SECSuccess;
}
loser:
+ if (keyPair) {
+ ssl3_FreeKeyPair(keyPair);
+ }
if (pubKey) {
SECKEY_DestroyPublicKey(pubKey);
pubKey = NULL;
}
- if (sc->serverCert != NULL) {
- CERT_DestroyCertificate(sc->serverCert);
- sc->serverCert = NULL;
- }
- if (sc->serverCertChain != NULL) {
- CERT_DestroyCertificateList(sc->serverCertChain);
- sc->serverCertChain = NULL;
- }
- if (sc->serverKeyPair != NULL) {
- ssl3_FreeKeyPair(sc->serverKeyPair);
- sc->serverKeyPair = NULL;
- }
- return SECFailure;
+ return rv;
}
/************************************************************************/
@@ -1241,7 +1269,8 @@ SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f, void *arg)
/*
* Allow the application to pass the url or hostname into the SSL library
- * so that we can do some checking on it.
+ * so that we can do some checking on it. It will be used for the value in
+ * SNI extension of client hello message.
*/
SECStatus
SSL_SetURL(PRFileDesc *fd, const char *url)
@@ -1273,6 +1302,46 @@ SSL_SetURL(PRFileDesc *fd, const char *url)
}
/*
+ * Allow the application to pass the set of trust anchors
+ */
+SECStatus
+SSL_SetTrustAnchors(PRFileDesc *fd, CERTCertList *certList)
+{
+ PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
+ PR_NOT_REACHED("not implemented");
+ return SECFailure;
+#if 0
+ sslSocket * ss = ssl_FindSocket(fd);
+ CERTDistNames *names = NULL;
+
+ if (!certList) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetTrustAnchors",
+ SSL_GETPID(), fd));
+ return SECFailure;
+ }
+
+ names = CERT_DistNamesFromCertList(certList);
+ if (names == NULL) {
+ return SECFailure;
+ }
+ ssl_Get1stHandshakeLock(ss);
+ ssl_GetSSL3HandshakeLock(ss);
+ if (ss->ssl3.ca_list) {
+ CERT_FreeDistNames(ss->ssl3.ca_list);
+ }
+ ss->ssl3.ca_list = names;
+ ssl_ReleaseSSL3HandshakeLock(ss);
+ ssl_Release1stHandshakeLock(ss);
+
+ return SECSuccess;
+#endif
+}
+
+/*
** Returns Negative number on error, zero or greater on success.
** Returns the amount of data immediately available to be read.
*/
@@ -1440,3 +1509,22 @@ SSL_RestartHandshakeAfterServerCert(sslSocket *ss)
ssl_Release1stHandshakeLock(ss);
return rv;
}
+
+/* For more info see ssl.h */
+SECStatus
+SSL_SNISocketConfigHook(PRFileDesc *fd, SSLSNISocketConfig func,
+ void *arg)
+{
+ sslSocket *ss;
+
+ ss = ssl_FindSocket(fd);
+ if (!ss) {
+ SSL_DBG(("%d: SSL[%d]: bad socket in SNISocketConfigHook",
+ SSL_GETPID(), fd));
+ return SECFailure;
+ }
+
+ ss->sniSocketConfig = func;
+ ss->sniSocketConfigArg = arg;
+ return SECSuccess;
+}
diff --git a/net/third_party/nss/ssl/sslsnce.c b/net/third_party/nss/ssl/sslsnce.c
index 115766c..5658dc2 100644
--- a/net/third_party/nss/ssl/sslsnce.c
+++ b/net/third_party/nss/ssl/sslsnce.c
@@ -36,7 +36,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-/* $Id: sslsnce.c,v 1.51 2009/11/07 18:23:06 wtc%google.com Exp $ */
+/* $Id: sslsnce.c,v 1.52 2010/01/14 22:15:25 alexei.volkov.bugs%sun.com Exp $ */
/* Note: ssl_FreeSID() in sslnonce.c gets used for both client and server
* cache sids!
@@ -71,6 +71,8 @@
* encKeyCacheEntry ticketEncKey; // Wrapped in non-bypass mode
* encKeyCacheEntry ticketMacKey; // Wrapped in non-bypass mode
* PRBool ticketKeysValid;
+ * sidCacheLock srvNameCacheLock;
+ * srvNameCacheEntry srvNameData[ numSrvNameCacheEntries ];
* } cacheMemCacheData;
*/
#include "seccomon.h"
@@ -84,6 +86,7 @@
#include "pk11func.h"
#include "base64.h"
#include "keyhi.h"
+#include "blapi.h"
#include <stdio.h>
@@ -150,10 +153,12 @@ struct sidCacheEntryStr {
/* 4 */ PRUint32 masterWrapMech;
/* 4 */ SSL3KEAType exchKeyType;
/* 4 */ PRInt32 certIndex;
-/*116 */} ssl3;
+/* 4 */ PRInt32 srvNameIndex;
+/* 32 */ PRUint8 srvNameHash[SHA256_LENGTH]; /* SHA256 name hash */
+/*152 */} ssl3;
/* force sizeof(sidCacheEntry) to be a multiple of cache line size */
struct {
-/*120 */ PRUint8 filler[120]; /* 72+120==196, a multiple of 16 */
+/*152 */ PRUint8 filler[120]; /* 72+152==224, a multiple of 16 */
} forceSize;
} u;
};
@@ -186,6 +191,18 @@ struct encKeyCacheEntryStr {
};
typedef struct encKeyCacheEntryStr encKeyCacheEntry;
+#define SSL_MAX_DNS_HOST_NAME 1024
+
+struct srvNameCacheEntryStr {
+ PRUint16 type; /* 2 */
+ PRUint16 nameLen; /* 2 */
+ PRUint8 name[SSL_MAX_DNS_HOST_NAME + 12]; /* 1034 */
+ PRUint8 nameHash[SHA256_LENGTH]; /* 32 */
+ /* 1072 */
+};
+typedef struct srvNameCacheEntryStr srvNameCacheEntry;
+
+
struct cacheDescStr {
PRUint32 cacheMemSize;
@@ -203,6 +220,9 @@ struct cacheDescStr {
PRUint32 numKeyCacheEntries;
PRUint32 keyCacheSize;
+ PRUint32 numSrvNameCacheEntries;
+ PRUint32 srvNameCacheSize;
+
PRUint32 ssl2Timeout;
PRUint32 ssl3Timeout;
@@ -218,6 +238,7 @@ struct cacheDescStr {
sidCacheLock * sidCacheLocks;
sidCacheLock * keyCacheLock;
sidCacheLock * certCacheLock;
+ sidCacheLock * srvNameCacheLock;
sidCacheSet * sidCacheSets;
sidCacheEntry * sidCacheData;
certCacheEntry * certCacheData;
@@ -226,6 +247,7 @@ struct cacheDescStr {
encKeyCacheEntry * ticketEncKey;
encKeyCacheEntry * ticketMacKey;
PRUint32 * ticketKeysValid;
+ srvNameCacheEntry * srvNameCacheData;
/* Only the private copies of these pointers are valid */
char * cacheMem;
@@ -248,6 +270,7 @@ static PRBool isMultiProcess = PR_FALSE;
#define DEF_CERT_CACHE_ENTRIES 250
#define MIN_CERT_CACHE_ENTRIES 125 /* the effective size in old releases. */
#define DEF_KEY_CACHE_ENTRIES 250
+#define DEF_NAME_CACHE_ENTRIES 1000
#define SID_CACHE_ENTRIES_PER_SET 128
#define SID_ALIGNMENT 16
@@ -394,6 +417,59 @@ CacheCert(cacheDesc * cache, CERTCertificate *cert, sidCacheEntry *sce)
}
+/* Server configuration hash tables need to account the SECITEM.type
+ * field as well. These functions accomplish that. */
+static PLHashNumber
+Get32BitNameHash(const SECItem *name)
+{
+ PLHashNumber rv = SECITEM_Hash(name);
+
+ PRUint8 *rvc = (PRUint8 *)&rv;
+ rvc[ name->len % sizeof(rv) ] ^= name->type;
+
+ return rv;
+}
+
+/* Put a name in the cache. Update the cert index in the sce.
+*/
+static PRUint32
+CacheSrvName(cacheDesc * cache, SECItem *name, sidCacheEntry *sce)
+{
+ PRUint32 now;
+ PRUint32 ndx;
+ srvNameCacheEntry snce;
+
+ if (!name || name->len <= 0 ||
+ name->len > SSL_MAX_DNS_HOST_NAME) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return 0;
+ }
+
+ snce.type = name->type;
+ snce.nameLen = name->len;
+ PORT_Memcpy(snce.name, name->data, snce.nameLen);
+ SHA256_HashBuf(snce.nameHash, (unsigned char*)name->data,
+ name->len);
+ /* get index of the next name */
+ ndx = Get32BitNameHash(name);
+ /* get lock on cert cache */
+ now = LockSidCacheLock(cache->srvNameCacheLock, 0);
+ if (now) {
+ if (cache->numSrvNameCacheEntries > 0) {
+ /* Fit the index into array */
+ ndx %= cache->numSrvNameCacheEntries;
+ /* write the entry */
+ cache->srvNameCacheData[ndx] = snce;
+ /* remember where we put it. */
+ sce->u.ssl3.srvNameIndex = ndx;
+ /* Copy hash into sid hash */
+ PORT_Memcpy(sce->u.ssl3.srvNameHash, snce.nameHash, SHA256_LENGTH);
+ }
+ UnlockSidCacheLock(cache->srvNameCacheLock);
+ }
+ return now;
+}
+
/*
** Convert local SID to shared memory one
*/
@@ -454,6 +530,7 @@ ConvertFromSID(sidCacheEntry *to, sslSessionID *from)
to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType;
to->sessionIDLength = from->u.ssl3.sessionIDLength;
to->u.ssl3.certIndex = -1;
+ to->u.ssl3.srvNameIndex = -1;
PORT_Memcpy(to->sessionID, from->u.ssl3.sessionID,
to->sessionIDLength);
@@ -472,7 +549,9 @@ ConvertFromSID(sidCacheEntry *to, sslSessionID *from)
** Caller must hold cache lock when calling this.
*/
static sslSessionID *
-ConvertToSID(sidCacheEntry *from, certCacheEntry *pcce,
+ConvertToSID(sidCacheEntry * from,
+ certCacheEntry * pcce,
+ srvNameCacheEntry *psnce,
CERTCertDBHandle * dbHandle)
{
sslSessionID *to;
@@ -526,6 +605,17 @@ ConvertToSID(sidCacheEntry *from, certCacheEntry *pcce,
to->u.ssl3.keys = from->u.ssl3.keys;
to->u.ssl3.masterWrapMech = from->u.ssl3.masterWrapMech;
to->u.ssl3.exchKeyType = from->u.ssl3.exchKeyType;
+ if (from->u.ssl3.srvNameIndex != -1 && psnce) {
+ SECItem name;
+ SECStatus rv;
+ name.type = psnce->type;
+ name.len = psnce->nameLen;
+ name.data = psnce->name;
+ rv = SECITEM_CopyItem(NULL, &to->u.ssl3.srvName, &name);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
PORT_Memcpy(to->u.ssl3.sessionID, from->sessionID, from->sessionIDLength);
@@ -582,7 +672,9 @@ ConvertToSID(sidCacheEntry *from, certCacheEntry *pcce,
PORT_Free(to->u.ssl2.masterKey.data);
if (to->u.ssl2.cipherArg.data)
PORT_Free(to->u.ssl2.cipherArg.data);
- }
+ } else {
+ SECITEM_FreeItem(&to->u.ssl3.srvName, PR_FALSE);
+ }
PORT_Free(to);
}
return NULL;
@@ -682,12 +774,14 @@ ServerSessionIDLookup(const PRIPv6Addr *addr,
sslSessionID * sid = 0;
sidCacheEntry * psce;
certCacheEntry *pcce = 0;
+ srvNameCacheEntry *psnce = 0;
cacheDesc * cache = &globalCache;
PRUint32 now;
PRUint32 set;
PRInt32 cndx;
sidCacheEntry sce;
certCacheEntry cce;
+ srvNameCacheEntry snce;
set = SIDindex(cache, addr, sessionID, sessionIDLength);
now = LockSet(cache, set, 0);
@@ -696,36 +790,65 @@ ServerSessionIDLookup(const PRIPv6Addr *addr,
psce = FindSID(cache, set, now, addr, sessionID, sessionIDLength);
if (psce) {
- if (psce->version >= SSL_LIBRARY_VERSION_3_0 &&
- (cndx = psce->u.ssl3.certIndex) != -1) {
-
- PRUint32 gotLock = LockSidCacheLock(cache->certCacheLock, now);
- if (gotLock) {
- pcce = &cache->certCacheData[cndx];
-
- /* See if the cert's session ID matches the sce cache. */
- if ((pcce->sessionIDLength == psce->sessionIDLength) &&
- !PORT_Memcmp(pcce->sessionID, psce->sessionID,
- pcce->sessionIDLength)) {
- cce = *pcce;
- } else {
- /* The cert doesen't match the SID cache entry,
- ** so invalidate the SID cache entry.
- */
- psce->valid = 0;
- psce = 0;
- pcce = 0;
- }
- UnlockSidCacheLock(cache->certCacheLock);
- } else {
- /* what the ??. Didn't get the cert cache lock.
- ** Don't invalidate the SID cache entry, but don't find it.
- */
- PORT_Assert(!("Didn't get cert Cache Lock!"));
- psce = 0;
- pcce = 0;
- }
- }
+ if (psce->version >= SSL_LIBRARY_VERSION_3_0) {
+ if ((cndx = psce->u.ssl3.certIndex) != -1) {
+
+ PRUint32 gotLock = LockSidCacheLock(cache->certCacheLock, now);
+ if (gotLock) {
+ pcce = &cache->certCacheData[cndx];
+
+ /* See if the cert's session ID matches the sce cache. */
+ if ((pcce->sessionIDLength == psce->sessionIDLength) &&
+ !PORT_Memcmp(pcce->sessionID, psce->sessionID,
+ pcce->sessionIDLength)) {
+ cce = *pcce;
+ } else {
+ /* The cert doesen't match the SID cache entry,
+ ** so invalidate the SID cache entry.
+ */
+ psce->valid = 0;
+ psce = 0;
+ pcce = 0;
+ }
+ UnlockSidCacheLock(cache->certCacheLock);
+ } else {
+ /* what the ??. Didn't get the cert cache lock.
+ ** Don't invalidate the SID cache entry, but don't find it.
+ */
+ PORT_Assert(!("Didn't get cert Cache Lock!"));
+ psce = 0;
+ pcce = 0;
+ }
+ }
+ if ((cndx = psce->u.ssl3.srvNameIndex) != -1) {
+ PRUint32 gotLock = LockSidCacheLock(cache->srvNameCacheLock,
+ now);
+ if (gotLock) {
+ psnce = &cache->srvNameCacheData[cndx];
+
+ if (!PORT_Memcmp(psnce->nameHash, psce->u.ssl3.srvNameHash,
+ SHA256_LENGTH)) {
+ snce = *psnce;
+ } else {
+ /* The name doesen't match the SID cache entry,
+ ** so invalidate the SID cache entry.
+ */
+ psce->valid = 0;
+ psce = 0;
+ psnce = 0;
+ }
+ UnlockSidCacheLock(cache->srvNameCacheLock);
+ } else {
+ /* what the ??. Didn't get the cert cache lock.
+ ** Don't invalidate the SID cache entry, but don't find it.
+ */
+ PORT_Assert(!("Didn't get name Cache Lock!"));
+ psce = 0;
+ psnce = 0;
+ }
+
+ }
+ }
if (psce) {
psce->lastAccessTime = now;
sce = *psce; /* grab a copy while holding the lock */
@@ -736,7 +859,7 @@ ServerSessionIDLookup(const PRIPv6Addr *addr,
/* sce conains a copy of the cache entry.
** Convert shared memory format to local format
*/
- sid = ConvertToSID(&sce, pcce ? &cce : 0, dbHandle);
+ sid = ConvertToSID(&sce, pcce ? &cce : 0, psnce ? &snce : 0, dbHandle);
}
return sid;
}
@@ -796,9 +919,14 @@ ServerSessionIDCache(sslSessionID *sid)
ConvertFromSID(&sce, sid);
- if ((version >= SSL_LIBRARY_VERSION_3_0) &&
- (sid->peerCert != NULL)) {
- now = CacheCert(cache, sid->peerCert, &sce);
+ if (version >= SSL_LIBRARY_VERSION_3_0) {
+ SECItem *name = &sid->u.ssl3.srvName;
+ if (name->len && name->data) {
+ now = CacheSrvName(cache, name, &sce);
+ }
+ if (sid->peerCert != NULL) {
+ now = CacheCert(cache, sid->peerCert, &sce);
+ }
}
set = SIDindex(cache, &sce.addr, sce.sessionID, sce.sessionIDLength);
@@ -924,7 +1052,8 @@ CloseCache(cacheDesc *cache)
}
static SECStatus
-InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout,
+InitCache(cacheDesc *cache, int maxCacheEntries, int maxCertCacheEntries,
+ int maxSrvNameCacheEntries, PRUint32 ssl2_timeout,
PRUint32 ssl3_timeout, const char *directory, PRBool shared)
{
ptrdiff_t ptr;
@@ -973,6 +1102,11 @@ InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout,
cache->numSIDCacheSetsPerLock =
SID_HOWMANY(cache->numSIDCacheSets, cache->numSIDCacheLocks);
+ cache->numCertCacheEntries = (maxCertCacheEntries > 0) ?
+ maxCertCacheEntries : 0;
+ cache->numSrvNameCacheEntries = (maxSrvNameCacheEntries > 0) ?
+ maxSrvNameCacheEntries : 0;
+
/* compute size of shared memory, and offsets of all pointers */
ptr = 0;
cache->cacheMem = (char *)ptr;
@@ -981,7 +1115,8 @@ InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout,
cache->sidCacheLocks = (sidCacheLock *)ptr;
cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks;
cache->certCacheLock = cache->keyCacheLock + 1;
- ptr = (ptrdiff_t)(cache->certCacheLock + 1);
+ cache->srvNameCacheLock = cache->certCacheLock + 1;
+ ptr = (ptrdiff_t)(cache->srvNameCacheLock + 1);
ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
cache->sidCacheSets = (sidCacheSet *)ptr;
@@ -996,10 +1131,12 @@ InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout,
cache->sidCacheSize =
(char *)cache->certCacheData - (char *)cache->sidCacheData;
- /* This is really a poor way to computer this! */
- cache->numCertCacheEntries = cache->sidCacheSize / sizeof(certCacheEntry);
- if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES)
+ if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES) {
+ /* This is really a poor way to computer this! */
+ cache->numCertCacheEntries = cache->sidCacheSize / sizeof(certCacheEntry);
+ if (cache->numCertCacheEntries < MIN_CERT_CACHE_ENTRIES)
cache->numCertCacheEntries = MIN_CERT_CACHE_ENTRIES;
+ }
ptr = (ptrdiff_t)(cache->certCacheData + cache->numCertCacheEntries);
ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
@@ -1030,6 +1167,15 @@ InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout,
ptr = (ptrdiff_t)(cache->ticketKeysValid + 1);
ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
+ cache->srvNameCacheData = (srvNameCacheEntry *)ptr;
+ if (cache->numSrvNameCacheEntries < 0) {
+ cache->numSrvNameCacheEntries = DEF_NAME_CACHE_ENTRIES;
+ }
+ cache->srvNameCacheSize =
+ cache->numSrvNameCacheEntries * sizeof(srvNameCacheEntry);
+ ptr = (ptrdiff_t)(cache->srvNameCacheData + cache->numSrvNameCacheEntries);
+ ptr = SID_ROUNDUP(ptr, SID_ALIGNMENT);
+
cache->cacheMemSize = ptr;
if (ssl2_timeout) {
@@ -1113,6 +1259,7 @@ InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout,
*(ptrdiff_t *)(&cache->sidCacheLocks) += ptr;
*(ptrdiff_t *)(&cache->keyCacheLock ) += ptr;
*(ptrdiff_t *)(&cache->certCacheLock) += ptr;
+ *(ptrdiff_t *)(&cache->srvNameCacheLock) += ptr;
*(ptrdiff_t *)(&cache->sidCacheSets ) += ptr;
*(ptrdiff_t *)(&cache->sidCacheData ) += ptr;
*(ptrdiff_t *)(&cache->certCacheData) += ptr;
@@ -1121,11 +1268,12 @@ InitCache(cacheDesc *cache, int maxCacheEntries, PRUint32 ssl2_timeout,
*(ptrdiff_t *)(&cache->ticketEncKey ) += ptr;
*(ptrdiff_t *)(&cache->ticketMacKey ) += ptr;
*(ptrdiff_t *)(&cache->ticketKeysValid) += ptr;
+ *(ptrdiff_t *)(&cache->srvNameCacheData) += ptr;
/* initialize the locks */
init_time = ssl_Time();
pLock = cache->sidCacheLocks;
- for (locks_to_initialize = cache->numSIDCacheLocks + 2;
+ for (locks_to_initialize = cache->numSIDCacheLocks + 3;
locks_initialized < locks_to_initialize;
++locks_initialized, ++pLock ) {
@@ -1170,23 +1318,28 @@ SSL_SetMaxServerCacheLocks(PRUint32 maxLocks)
return SECSuccess;
}
-SECStatus
-SSL_ConfigServerSessionIDCacheInstance( cacheDesc *cache,
- int maxCacheEntries,
- PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char * directory, PRBool shared)
+static SECStatus
+ssl_ConfigServerSessionIDCacheInstanceWithOpt(cacheDesc *cache,
+ PRUint32 ssl2_timeout,
+ PRUint32 ssl3_timeout,
+ const char * directory,
+ PRBool shared,
+ int maxCacheEntries,
+ int maxCertCacheEntries,
+ int maxSrvNameCacheEntries)
{
SECStatus rv;
- PORT_Assert(sizeof(sidCacheEntry) == 192);
+ PORT_Assert(sizeof(sidCacheEntry) == 224);
PORT_Assert(sizeof(certCacheEntry) == 4096);
+ PORT_Assert(sizeof(srvNameCacheEntry) == 1072);
myPid = SSL_GETPID();
if (!directory) {
directory = DEFAULT_CACHE_DIRECTORY;
}
- rv = InitCache(cache, maxCacheEntries, ssl2_timeout, ssl3_timeout,
+ rv = InitCache(cache, maxCacheEntries, maxCertCacheEntries,
+ maxSrvNameCacheEntries, ssl2_timeout, ssl3_timeout,
directory, shared);
if (rv) {
SET_ERROR_CODE
@@ -1200,6 +1353,22 @@ SSL_ConfigServerSessionIDCacheInstance( cacheDesc *cache,
}
SECStatus
+SSL_ConfigServerSessionIDCacheInstance( cacheDesc *cache,
+ int maxCacheEntries,
+ PRUint32 ssl2_timeout,
+ PRUint32 ssl3_timeout,
+ const char * directory, PRBool shared)
+{
+ return ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache,
+ ssl2_timeout,
+ ssl3_timeout,
+ directory,
+ shared,
+ maxCacheEntries,
+ -1, -1);
+}
+
+SECStatus
SSL_ConfigServerSessionIDCache( int maxCacheEntries,
PRUint32 ssl2_timeout,
PRUint32 ssl3_timeout,
@@ -1231,11 +1400,13 @@ SSL_ShutdownServerSessionIDCache(void)
/* Use this function, instead of SSL_ConfigServerSessionIDCache,
* if the cache will be shared by multiple processes.
*/
-SECStatus
-SSL_ConfigMPServerSIDCache( int maxCacheEntries,
- PRUint32 ssl2_timeout,
- PRUint32 ssl3_timeout,
- const char * directory)
+static SECStatus
+ssl_ConfigMPServerSIDCacheWithOpt( PRUint32 ssl2_timeout,
+ PRUint32 ssl3_timeout,
+ const char * directory,
+ int maxCacheEntries,
+ int maxCertCacheEntries,
+ int maxSrvNameCacheEntries)
{
char * envValue;
char * inhValue;
@@ -1248,8 +1419,9 @@ SSL_ConfigMPServerSIDCache( int maxCacheEntries,
char fmString[PR_FILEMAP_STRING_BUFSIZE];
isMultiProcess = PR_TRUE;
- result = SSL_ConfigServerSessionIDCacheInstance(cache, maxCacheEntries,
- ssl2_timeout, ssl3_timeout, directory, PR_TRUE);
+ result = ssl_ConfigServerSessionIDCacheInstanceWithOpt(cache,
+ ssl2_timeout, ssl3_timeout, directory, PR_TRUE,
+ maxCacheEntries, maxCacheEntries, maxSrvNameCacheEntries);
if (result != SECSuccess)
return result;
@@ -1289,6 +1461,44 @@ SSL_ConfigMPServerSIDCache( int maxCacheEntries,
return result;
}
+/* Use this function, instead of SSL_ConfigServerSessionIDCache,
+ * if the cache will be shared by multiple processes.
+ */
+SECStatus
+SSL_ConfigMPServerSIDCache( int maxCacheEntries,
+ PRUint32 ssl2_timeout,
+ PRUint32 ssl3_timeout,
+ const char * directory)
+{
+ return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout,
+ ssl3_timeout,
+ directory,
+ maxCacheEntries,
+ -1, -1);
+}
+
+SECStatus
+SSL_ConfigServerSessionIDCacheWithOpt(
+ PRUint32 ssl2_timeout,
+ PRUint32 ssl3_timeout,
+ const char * directory,
+ int maxCacheEntries,
+ int maxCertCacheEntries,
+ int maxSrvNameCacheEntries,
+ PRBool enableMPCache)
+{
+ if (!enableMPCache) {
+ ssl_InitSessionCacheLocks(PR_FALSE);
+ return ssl_ConfigServerSessionIDCacheInstanceWithOpt(&globalCache,
+ ssl2_timeout, ssl3_timeout, directory, PR_FALSE,
+ maxCacheEntries, maxCertCacheEntries, maxSrvNameCacheEntries);
+ } else {
+ return ssl_ConfigMPServerSIDCacheWithOpt(ssl2_timeout, ssl3_timeout,
+ directory, maxCacheEntries, maxCertCacheEntries,
+ maxSrvNameCacheEntries);
+ }
+}
+
SECStatus
SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
{
@@ -1391,6 +1601,7 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
*(ptrdiff_t *)(&cache->sidCacheLocks) += ptr;
*(ptrdiff_t *)(&cache->keyCacheLock ) += ptr;
*(ptrdiff_t *)(&cache->certCacheLock) += ptr;
+ *(ptrdiff_t *)(&cache->srvNameCacheLock) += ptr;
*(ptrdiff_t *)(&cache->sidCacheSets ) += ptr;
*(ptrdiff_t *)(&cache->sidCacheData ) += ptr;
*(ptrdiff_t *)(&cache->certCacheData) += ptr;
@@ -1399,6 +1610,7 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
*(ptrdiff_t *)(&cache->ticketEncKey ) += ptr;
*(ptrdiff_t *)(&cache->ticketMacKey ) += ptr;
*(ptrdiff_t *)(&cache->ticketKeysValid) += ptr;
+ *(ptrdiff_t *)(&cache->srvNameCacheData) += ptr;
cache->cacheMemMap = my.cacheMemMap;
cache->cacheMem = my.cacheMem;
@@ -1420,7 +1632,7 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
/* note from jpierre : this should be free'd in child processes when
** a function is added to delete the SSL session cache in the future.
*/
- locks_to_initialize = cache->numSIDCacheLocks + 2;
+ locks_to_initialize = cache->numSIDCacheLocks + 3;
newLocks = PORT_NewArray(sidCacheLock, locks_to_initialize);
if (!newLocks)
goto loser;
@@ -1443,6 +1655,7 @@ SSL_InheritMPServerSIDCacheInstance(cacheDesc *cache, const char * envString)
/* also fix the key and cert cache which use the last 2 lock entries */
cache->keyCacheLock = cache->sidCacheLocks + cache->numSIDCacheLocks;
cache->certCacheLock = cache->keyCacheLock + 1;
+ cache->srvNameCacheLock = cache->certCacheLock + 1;
#endif
PORT_Free(myEnvString);
diff --git a/net/third_party/nss/ssl/sslsock.c b/net/third_party/nss/ssl/sslsock.c
index 2275800..722fe60 100644
--- a/net/third_party/nss/ssl/sslsock.c
+++ b/net/third_party/nss/ssl/sslsock.c
@@ -40,7 +40,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-/* $Id: sslsock.c,v 1.60 2009/11/25 05:24:25 wtc%google.com Exp $ */
+/* $Id: sslsock.c,v 1.64 2010/01/28 06:19:13 nelson%bolyard.com Exp $ */
#include "seccomon.h"
#include "cert.h"
#include "keyhi.h"
@@ -182,7 +182,7 @@ static sslOptions ssl_defaults = {
PR_FALSE, /* noLocks */
PR_FALSE, /* enableSessionTickets */
PR_FALSE, /* enableDeflate */
- 0, /* enableRenegotiation (default: never) */
+ 2, /* enableRenegotiation (default: requires extension) */
PR_FALSE, /* requireSafeNegotiation */
};
@@ -199,6 +199,7 @@ int ssl_lock_readers = 1; /* default true. */
char ssl_debug;
char ssl_trace;
FILE * ssl_trace_iob;
+FILE * ssl_keylog_iob;
char lockStatus[] = "Locks are ENABLED. ";
#define LOCKSTATUS_OFFSET 10 /* offset of ENABLED */
@@ -305,7 +306,7 @@ ssl_DupSocket(sslSocket *os)
int i;
sslServerCerts * oc = os->serverCerts;
sslServerCerts * sc = ss->serverCerts;
-
+
for (i=kt_null; i < kt_kea_size; i++, oc++, sc++) {
if (oc->serverCert && oc->serverCertChain) {
sc->serverCert = CERT_DupCertificate(oc->serverCert);
@@ -334,6 +335,8 @@ ssl_DupSocket(sslSocket *os)
ss->authCertificateArg = os->authCertificateArg;
ss->getClientAuthData = os->getClientAuthData;
ss->getClientAuthDataArg = os->getClientAuthDataArg;
+ ss->sniSocketConfig = os->sniSocketConfig;
+ ss->sniSocketConfigArg = os->sniSocketConfigArg;
ss->handleBadCert = os->handleBadCert;
ss->badCertArg = os->badCertArg;
ss->handshakeCallback = os->handshakeCallback;
@@ -439,6 +442,11 @@ ssl_DestroySocketContents(sslSocket *ss)
PORT_Free(ss->opt.nextProtoNego.data);
ss->opt.nextProtoNego.data = NULL;
}
+ PORT_Assert(!ss->xtnData.sniNameArr);
+ if (ss->xtnData.sniNameArr) {
+ PORT_Free(ss->xtnData.sniNameArr);
+ ss->xtnData.sniNameArr = NULL;
+ }
}
/*
@@ -1321,6 +1329,119 @@ SSL_GetNextProto(PRFileDesc *fd, int *state, unsigned char *buf,
return SECSuccess;
}
+PRFileDesc *
+SSL_ReconfigFD(PRFileDesc *model, PRFileDesc *fd)
+{
+ PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
+ PR_NOT_REACHED("not implemented");
+ return NULL;
+
+#if 0
+ sslSocket * sm = NULL, *ss = NULL;
+ int i;
+ sslServerCerts * mc = sm->serverCerts;
+ sslServerCerts * sc = ss->serverCerts;
+
+ if (model == NULL) {
+ PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
+ return NULL;
+ }
+ sm = ssl_FindSocket(model);
+ if (sm == NULL) {
+ SSL_DBG(("%d: SSL[%d]: bad model socket in ssl_ReconfigFD",
+ SSL_GETPID(), model));
+ return NULL;
+ }
+ ss = ssl_FindSocket(fd);
+ PORT_Assert(ss);
+ if (ss == NULL) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+
+ ss->opt = sm->opt;
+ PORT_Memcpy(ss->cipherSuites, sm->cipherSuites, sizeof sm->cipherSuites);
+
+ if (!ss->opt.useSecurity) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return NULL;
+ }
+ /* This int should be SSLKEAType, but CC on Irix complains,
+ * during the for loop.
+ */
+ for (i=kt_null; i < kt_kea_size; i++, mc++, sc++) {
+ if (mc->serverCert && mc->serverCertChain) {
+ if (sc->serverCert) {
+ CERT_DestroyCertificate(sc->serverCert);
+ }
+ sc->serverCert = CERT_DupCertificate(mc->serverCert);
+ if (sc->serverCertChain) {
+ CERT_DestroyCertificateList(sc->serverCertChain);
+ }
+ sc->serverCertChain = CERT_DupCertList(mc->serverCertChain);
+ if (!sc->serverCertChain)
+ goto loser;
+ }
+ if (mc->serverKeyPair) {
+ if (sc->serverKeyPair) {
+ ssl3_FreeKeyPair(sc->serverKeyPair);
+ }
+ sc->serverKeyPair = ssl3_GetKeyPairRef(mc->serverKeyPair);
+ sc->serverKeyBits = mc->serverKeyBits;
+ }
+ }
+ if (sm->stepDownKeyPair) {
+ if (ss->stepDownKeyPair) {
+ ssl3_FreeKeyPair(ss->stepDownKeyPair);
+ }
+ ss->stepDownKeyPair = ssl3_GetKeyPairRef(sm->stepDownKeyPair);
+ }
+ if (sm->ephemeralECDHKeyPair) {
+ if (ss->ephemeralECDHKeyPair) {
+ ssl3_FreeKeyPair(ss->ephemeralECDHKeyPair);
+ }
+ ss->ephemeralECDHKeyPair =
+ ssl3_GetKeyPairRef(sm->ephemeralECDHKeyPair);
+ }
+ /* copy trust anchor names */
+ if (sm->ssl3.ca_list) {
+ if (ss->ssl3.ca_list) {
+ CERT_FreeDistNames(ss->ssl3.ca_list);
+ }
+ ss->ssl3.ca_list = CERT_DupDistNames(sm->ssl3.ca_list);
+ if (!ss->ssl3.ca_list) {
+ goto loser;
+ }
+ }
+
+ if (sm->authCertificate)
+ ss->authCertificate = sm->authCertificate;
+ if (sm->authCertificateArg)
+ ss->authCertificateArg = sm->authCertificateArg;
+ if (sm->getClientAuthData)
+ ss->getClientAuthData = sm->getClientAuthData;
+ if (sm->getClientAuthDataArg)
+ ss->getClientAuthDataArg = sm->getClientAuthDataArg;
+ if (sm->sniSocketConfig)
+ ss->sniSocketConfig = sm->sniSocketConfig;
+ if (sm->sniSocketConfigArg)
+ ss->sniSocketConfigArg = sm->sniSocketConfigArg;
+ if (sm->handleBadCert)
+ ss->handleBadCert = sm->handleBadCert;
+ if (sm->badCertArg)
+ ss->badCertArg = sm->badCertArg;
+ if (sm->handshakeCallback)
+ ss->handshakeCallback = sm->handshakeCallback;
+ if (sm->handshakeCallbackData)
+ ss->handshakeCallbackData = sm->handshakeCallbackData;
+ if (sm->pkcs11PinArg)
+ ss->pkcs11PinArg = sm->pkcs11PinArg;
+ return fd;
+loser:
+ return NULL;
+#endif
+}
+
/************************************************************************/
/* The following functions are the TOP LEVEL SSL functions.
** They all get called through the NSPRIOMethods table below.
@@ -2223,6 +2344,15 @@ ssl_NewSocket(PRBool makeLocks)
ssl_trace = atoi(ev);
SSL_TRACE(("SSL: tracing set to %d", ssl_trace));
}
+ ev = getenv("SSLKEYLOGFILE");
+ if (ev && ev[0]) {
+ ssl_keylog_iob = fopen(ev, "a");
+ if (ftell(ssl_keylog_iob) == 0) {
+ fputs("# pre-master secret log file, generated by NSS\n",
+ ssl_keylog_iob);
+ }
+ SSL_TRACE(("SSL: logging pre-master secrets to %s", ev));
+ }
#endif /* TRACE */
ev = getenv("SSLDEBUG");
if (ev && ev[0]) {
@@ -2247,19 +2377,12 @@ ssl_NewSocket(PRBool makeLocks)
if (ev) {
if (ev[0] == '1' || LOWER(ev[0]) == 'u')
ssl_defaults.enableRenegotiation = SSL_RENEGOTIATE_UNRESTRICTED;
-#ifdef LATER
- /* When SSL_RENEGOTIATE_REQUIRES_XTN is implemented, it will be
- * the default. Until then, NEVER will be the default.
- */
else if (ev[0] == '0' || LOWER(ev[0]) == 'n')
ssl_defaults.enableRenegotiation = SSL_RENEGOTIATE_NEVER;
+ else if (ev[0] == '3' || LOWER(ev[0]) == 'c')
+ ssl_defaults.enableRenegotiation = SSL_RENEGOTIATE_CLIENT_ONLY;
else
ssl_defaults.enableRenegotiation = SSL_RENEGOTIATE_REQUIRES_XTN;
-#else
- else
- ssl_defaults.enableRenegotiation = SSL_RENEGOTIATE_NEVER;
-#endif
-
SSL_TRACE(("SSL: enableRenegotiation set to %d",
ssl_defaults.enableRenegotiation));
}
@@ -2309,6 +2432,8 @@ ssl_NewSocket(PRBool makeLocks)
/* Provide default implementation of hooks */
ss->authCertificate = SSL_AuthCertificate;
ss->authCertificateArg = (void *)ss->dbHandle;
+ ss->sniSocketConfig = NULL;
+ ss->sniSocketConfigArg = NULL;
ss->getClientAuthData = NULL;
ss->handleBadCert = NULL;
ss->badCertArg = NULL;
diff --git a/net/third_party/nss/ssl/sslt.h b/net/third_party/nss/ssl/sslt.h
index 80f1dc2..f6e0b62 100644
--- a/net/third_party/nss/ssl/sslt.h
+++ b/net/third_party/nss/ssl/sslt.h
@@ -37,7 +37,7 @@
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
-/* $Id: sslt.h,v 1.13 2009/11/07 18:23:06 wtc%google.com Exp $ */
+/* $Id: sslt.h,v 1.16 2010/02/04 03:21:11 wtc%google.com Exp $ */
#ifndef __sslt_h_
#define __sslt_h_
@@ -189,4 +189,24 @@ typedef struct SSLCipherSuiteInfoStr {
} SSLCipherSuiteInfo;
+typedef enum {
+ SSL_sni_host_name = 0,
+ SSL_sni_type_total
+} SSLSniNameType;
+
+/* Supported extensions. */
+/* Update SSL_MAX_EXTENSIONS whenever a new extension type is added. */
+typedef enum {
+ ssl_server_name_xtn = 0,
+#ifdef NSS_ENABLE_ECC
+ ssl_elliptic_curves_xtn = 10,
+ ssl_ec_point_formats_xtn = 11,
+#endif
+ ssl_session_ticket_xtn = 35,
+ ssl_next_proto_neg_xtn = 13172,
+ ssl_renegotiation_info_xtn = 0xff01 /* experimental number */
+} SSLExtensionType;
+
+#define SSL_MAX_EXTENSIONS 6
+
#endif /* __sslt_h_ */