summaryrefslogtreecommitdiffstats
path: root/net/third_party/nss/patches/cachecerts.patch
blob: 9fe07cabcd8a25d1f3c732f45e51868ad3bc2c29 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
From 4c2b4b3992f81f062248f03296f7eb59b5fc0868 Mon Sep 17 00:00:00 2001
From: Adam Langley <agl@chromium.org>
Date: Mon, 3 Oct 2011 12:20:29 -0400
Subject: [PATCH] cachecerts.patch

---
 mozilla/security/nss/lib/ssl/ssl3con.c  |   54 +++++++++++++++++++++++++++++-
 mozilla/security/nss/lib/ssl/sslimpl.h  |    3 ++
 mozilla/security/nss/lib/ssl/sslnonce.c |    4 ++
 3 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/mozilla/security/nss/lib/ssl/ssl3con.c b/mozilla/security/nss/lib/ssl/ssl3con.c
index 455a532..9830e65 100644
--- a/mozilla/security/nss/lib/ssl/ssl3con.c
+++ b/mozilla/security/nss/lib/ssl/ssl3con.c
@@ -72,6 +72,7 @@
 #endif
 
 static void      ssl3_CleanupPeerCerts(sslSocket *ss);
+static void      ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid);
 static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec,
                                        PK11SlotInfo * serverKeySlot);
 static SECStatus ssl3_DeriveMasterSecret(sslSocket *ss, PK11SymKey *pms);
@@ -5141,6 +5142,7 @@ ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 	/* copy the peer cert from the SID */
 	if (sid->peerCert != NULL) {
 	    ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
+	    ssl3_CopyPeerCertsFromSID(ss, sid);
 	}
 
 
@@ -6393,6 +6395,7 @@ compression_found:
 	ss->sec.ci.sid = sid;
 	if (sid->peerCert != NULL) {
 	    ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);
+	    ssl3_CopyPeerCertsFromSID(ss, sid);
 	}
 
 	/*
@@ -7761,6 +7764,44 @@ ssl3_CleanupPeerCerts(sslSocket *ss)
     ss->ssl3.peerCertChain = NULL;
 }
 
+static void
+ssl3_CopyPeerCertsFromSID(sslSocket *ss, sslSessionID *sid)
+{
+    PRArenaPool *arena;
+    ssl3CertNode *lastCert = NULL;
+    ssl3CertNode *certs = NULL;
+    int i;
+
+    if (!sid->peerCertChain[0])
+	return;
+    PORT_Assert(!ss->ssl3.peerCertArena);
+    PORT_Assert(!ss->ssl3.peerCertChain);
+    ss->ssl3.peerCertArena = arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+    for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) {
+	ssl3CertNode *c = PORT_ArenaNew(arena, ssl3CertNode);
+	c->cert = CERT_DupCertificate(sid->peerCertChain[i]);
+	c->next = NULL;
+	if (lastCert) {
+	    lastCert->next = c;
+	} else {
+	    certs = c;
+	}
+	lastCert = c;
+    }
+    ss->ssl3.peerCertChain = certs;
+}
+
+static void
+ssl3_CopyPeerCertsToSID(ssl3CertNode *certs, sslSessionID *sid)
+{
+    int i = 0;
+    ssl3CertNode *c = certs;
+    for (; i < MAX_PEER_CERT_CHAIN_SIZE && c; i++, c = c->next) {
+	PORT_Assert(!sid->peerCertChain[i]);
+	sid->peerCertChain[i] = CERT_DupCertificate(c->cert);
+    }
+}
+
 /* Called from ssl3_HandleHandshakeMessage() when it has deciphered a complete
  * ssl3 Certificate message.
  * Caller must hold Handshake and RecvBuf locks.
@@ -7769,6 +7810,7 @@ static SECStatus
 ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 {
     ssl3CertNode *   c;
+    ssl3CertNode *   lastCert 	= NULL;
     ssl3CertNode *   certs 	= NULL;
     PRArenaPool *    arena 	= NULL;
     CERTCertificate *cert;
@@ -7896,8 +7938,13 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
 	if (c->cert->trust)
 	    trusted = PR_TRUE;
 
-	c->next = certs;
-	certs = c;
+	c->next = NULL;
+	if (lastCert) {
+	    lastCert->next = c;
+	} else {
+	    certs = c;
+	}
+	lastCert = c;
     }
 
     if (remaining != 0)
@@ -7947,6 +7994,7 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length)
     }
 
     ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
+    ssl3_CopyPeerCertsToSID(certs, ss->sec.ci.sid);
 
     if (!ss->sec.isServer) {
 	/* set the server authentication and key exchange types and sizes
@@ -8118,6 +8166,8 @@ ssl3_RestartHandshakeAfterServerCert(sslSocket *ss)
     if (ss->handshake != NULL) {
 	ss->handshake = ssl_GatherRecord1stHandshake;
 	ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
+	ssl3_CopyPeerCertsToSID((ssl3CertNode *)ss->ssl3.peerCertChain,
+				ss->sec.ci.sid);
 
 	ssl_GetRecvBufLock(ss);
 	if (ss->ssl3.hs.msgState.buf != NULL) {
diff --git a/mozilla/security/nss/lib/ssl/sslimpl.h b/mozilla/security/nss/lib/ssl/sslimpl.h
index d1c1181..48d6d83 100644
--- a/mozilla/security/nss/lib/ssl/sslimpl.h
+++ b/mozilla/security/nss/lib/ssl/sslimpl.h
@@ -569,10 +569,13 @@ typedef enum {	never_cached,
 		invalid_cache		/* no longer in any cache. */
 } Cached;
 
+#define MAX_PEER_CERT_CHAIN_SIZE 8
+
 struct sslSessionIDStr {
     sslSessionID *        next;   /* chain used for client sockets, only */
 
     CERTCertificate *     peerCert;
+    CERTCertificate *     peerCertChain[MAX_PEER_CERT_CHAIN_SIZE];
     const char *          peerID;     /* client only */
     const char *          urlSvrName; /* client only */
     CERTCertificate *     localCert;
diff --git a/mozilla/security/nss/lib/ssl/sslnonce.c b/mozilla/security/nss/lib/ssl/sslnonce.c
index 63dc5a2..64adc1f 100644
--- a/mozilla/security/nss/lib/ssl/sslnonce.c
+++ b/mozilla/security/nss/lib/ssl/sslnonce.c
@@ -197,6 +197,7 @@ lock_cache(void)
 static void
 ssl_DestroySID(sslSessionID *sid)
 {
+    int i;
     SSL_TRC(8, ("SSL: destroy sid: sid=0x%x cached=%d", sid, sid->cached));
     PORT_Assert((sid->references == 0));
 
@@ -216,6 +217,9 @@ ssl_DestroySID(sslSessionID *sid)
     if ( sid->peerCert ) {
 	CERT_DestroyCertificate(sid->peerCert);
     }
+    for (i = 0; i < MAX_PEER_CERT_CHAIN_SIZE && sid->peerCertChain[i]; i++) {
+	CERT_DestroyCertificate(sid->peerCertChain[i]);
+    }
     if ( sid->localCert ) {
 	CERT_DestroyCertificate(sid->localCert);
     }