OLD | NEW |
| (Empty) |
1 diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c | |
2 --- a/nss/lib/ssl/ssl3con.c 2014-01-03 19:41:44.744240754 -0800 | |
3 +++ b/nss/lib/ssl/ssl3con.c 2014-01-03 19:41:52.234363230 -0800 | |
4 @@ -10458,8 +10458,10 @@ ssl3_SendNextProto(sslSocket *ss) | |
5 int padding_len; | |
6 static const unsigned char padding[32] = {0}; | |
7 | |
8 - if (ss->ssl3.nextProto.len == 0) | |
9 + if (ss->ssl3.nextProto.len == 0 || | |
10 + ss->ssl3.nextProtoState == SSL_NEXT_PROTO_SELECTED) { | |
11 return SECSuccess; | |
12 + } | |
13 | |
14 PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); | |
15 PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss)); | |
16 diff -pu a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c | |
17 --- a/nss/lib/ssl/ssl3ext.c 2014-01-03 19:39:28.442012014 -0800 | |
18 +++ b/nss/lib/ssl/ssl3ext.c 2014-01-03 19:41:52.234363230 -0800 | |
19 @@ -52,8 +52,12 @@ static SECStatus ssl3_HandleRenegotiatio | |
20 PRUint16 ex_type, SECItem *data); | |
21 static SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, | |
22 PRUint16 ex_type, SECItem *data); | |
23 +static SECStatus ssl3_ClientHandleAppProtoXtn(sslSocket *ss, | |
24 + PRUint16 ex_type, SECItem *data); | |
25 static SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss, | |
26 PRUint16 ex_type, SECItem *data); | |
27 +static PRInt32 ssl3_ClientSendAppProtoXtn(sslSocket *ss, PRBool append, | |
28 + PRUint32 maxBytes); | |
29 static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append, | |
30 PRUint32 maxBytes); | |
31 static PRInt32 ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append, | |
32 @@ -251,6 +255,7 @@ static const ssl3HelloExtensionHandler s | |
33 { ssl_session_ticket_xtn, &ssl3_ClientHandleSessionTicketXtn }, | |
34 { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn }, | |
35 { ssl_next_proto_nego_xtn, &ssl3_ClientHandleNextProtoNegoXtn }, | |
36 + { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn }, | |
37 { ssl_use_srtp_xtn, &ssl3_HandleUseSRTPXtn }, | |
38 { ssl_channel_id_xtn, &ssl3_ClientHandleChannelIDXtn }, | |
39 { ssl_cert_status_xtn, &ssl3_ClientHandleStatusRequestXtn }, | |
40 @@ -270,18 +275,19 @@ static const ssl3HelloExtensionHandler s | |
41 */ | |
42 static const | |
43 ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = { | |
44 - { ssl_server_name_xtn, &ssl3_SendServerNameXtn }, | |
45 - { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }, | |
46 + { ssl_server_name_xtn, &ssl3_SendServerNameXtn }, | |
47 + { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn }, | |
48 #ifdef NSS_ENABLE_ECC | |
49 - { ssl_elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn }, | |
50 - { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn }, | |
51 + { ssl_elliptic_curves_xtn, &ssl3_SendSupportedCurvesXtn }, | |
52 + { ssl_ec_point_formats_xtn, &ssl3_SendSupportedPointFormatsXtn }, | |
53 #endif | |
54 - { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, | |
55 - { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn }, | |
56 - { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn }, | |
57 - { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn }, | |
58 - { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, | |
59 - { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn } | |
60 + { ssl_session_ticket_xtn, &ssl3_SendSessionTicketXtn }, | |
61 + { ssl_next_proto_nego_xtn, &ssl3_ClientSendNextProtoNegoXtn }, | |
62 + { ssl_app_layer_protocol_xtn, &ssl3_ClientSendAppProtoXtn }, | |
63 + { ssl_use_srtp_xtn, &ssl3_SendUseSRTPXtn }, | |
64 + { ssl_channel_id_xtn, &ssl3_ClientSendChannelIDXtn }, | |
65 + { ssl_cert_status_xtn, &ssl3_ClientSendStatusRequestXtn }, | |
66 + { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn } | |
67 /* any extra entries will appear as { 0, NULL } */ | |
68 }; | |
69 | |
70 @@ -614,6 +620,11 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSoc | |
71 | |
72 PORT_Assert(!ss->firstHsDone); | |
73 | |
74 + if (ssl3_ExtensionNegotiated(ss, ssl_app_layer_protocol_xtn)) { | |
75 + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
76 + return SECFailure; | |
77 + } | |
78 + | |
79 rv = ssl3_ValidateNextProtoNego(data->data, data->len); | |
80 if (rv != SECSuccess) | |
81 return rv; | |
82 @@ -647,6 +658,44 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSoc | |
83 return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &result); | |
84 } | |
85 | |
86 +static SECStatus | |
87 +ssl3_ClientHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data) | |
88 +{ | |
89 + const unsigned char* d = data->data; | |
90 + PRUint16 name_list_len; | |
91 + SECItem protocol_name; | |
92 + | |
93 + if (ssl3_ExtensionNegotiated(ss, ssl_next_proto_nego_xtn)) { | |
94 + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
95 + return SECFailure; | |
96 + } | |
97 + | |
98 + /* The extension data from the server has the following format: | |
99 + * uint16 name_list_len; | |
100 + * uint8 len; | |
101 + * uint8 protocol_name[len]; */ | |
102 + if (data->len < 4 || data->len > 2 + 1 + 255) { | |
103 + PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); | |
104 + return SECFailure; | |
105 + } | |
106 + | |
107 + name_list_len = ((PRUint16) d[0]) << 8 | | |
108 + ((PRUint16) d[1]); | |
109 + if (name_list_len != data->len - 2 || | |
110 + d[2] != data->len - 3) { | |
111 + PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID); | |
112 + return SECFailure; | |
113 + } | |
114 + | |
115 + protocol_name.data = data->data + 3; | |
116 + protocol_name.len = data->len - 3; | |
117 + | |
118 + SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE); | |
119 + ss->ssl3.nextProtoState = SSL_NEXT_PROTO_SELECTED; | |
120 + ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type; | |
121 + return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &protocol_name); | |
122 +} | |
123 + | |
124 static PRInt32 | |
125 ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, PRBool append, | |
126 PRUint32 maxBytes) | |
127 @@ -680,6 +729,70 @@ loser: | |
128 return -1; | |
129 } | |
130 | |
131 +static PRInt32 | |
132 +ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes) | |
133 +{ | |
134 + PRInt32 extension_length; | |
135 + unsigned char *alpn_protos = NULL; | |
136 + | |
137 + /* Renegotiations do not send this extension. */ | |
138 + if (!ss->opt.nextProtoNego.data || ss->firstHsDone) { | |
139 + return 0; | |
140 + } | |
141 + | |
142 + extension_length = 2 /* extension type */ + 2 /* extension length */ + | |
143 + 2 /* protocol name list length */ + | |
144 + ss->opt.nextProtoNego.len; | |
145 + | |
146 + if (append && maxBytes >= extension_length) { | |
147 + /* NPN requires that the client's fallback protocol is first in the | |
148 + * list. However, ALPN sends protocols in preference order. So we | |
149 + * allocate a buffer and move the first protocol to the end of the | |
150 + * list. */ | |
151 + SECStatus rv; | |
152 + const unsigned int len = ss->opt.nextProtoNego.len; | |
153 + | |
154 + alpn_protos = PORT_Alloc(len); | |
155 + if (alpn_protos == NULL) { | |
156 + return SECFailure; | |
157 + } | |
158 + if (len > 0) { | |
159 + /* Each protocol string is prefixed with a single byte length. */ | |
160 + unsigned int i = ss->opt.nextProtoNego.data[0] + 1; | |
161 + if (i <= len) { | |
162 + memcpy(alpn_protos, &ss->opt.nextProtoNego.data[i], len - i); | |
163 + memcpy(alpn_protos + len - i, ss->opt.nextProtoNego.data, i); | |
164 + } else { | |
165 + /* This seems to be invalid data so we'll send as-is. */ | |
166 + memcpy(alpn_protos, ss->opt.nextProtoNego.data, len); | |
167 + } | |
168 + } | |
169 + | |
170 + rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2); | |
171 + if (rv != SECSuccess) | |
172 + goto loser; | |
173 + rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2); | |
174 + if (rv != SECSuccess) | |
175 + goto loser; | |
176 + rv = ssl3_AppendHandshakeVariable(ss, alpn_protos, len, 2); | |
177 + PORT_Free(alpn_protos); | |
178 + alpn_protos = NULL; | |
179 + if (rv != SECSuccess) | |
180 + goto loser; | |
181 + ss->xtnData.advertised[ss->xtnData.numAdvertised++] = | |
182 + ssl_app_layer_protocol_xtn; | |
183 + } else if (maxBytes < extension_length) { | |
184 + return 0; | |
185 + } | |
186 + | |
187 + return extension_length; | |
188 + | |
189 +loser: | |
190 + if (alpn_protos) | |
191 + PORT_Free(alpn_protos); | |
192 + return -1; | |
193 +} | |
194 + | |
195 static SECStatus | |
196 ssl3_ClientHandleChannelIDXtn(sslSocket *ss, PRUint16 ex_type, | |
197 SECItem *data) | |
198 diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h | |
199 --- a/nss/lib/ssl/ssl.h 2014-01-03 19:40:03.522585625 -0800 | |
200 +++ b/nss/lib/ssl/ssl.h 2014-01-03 19:41:52.234363230 -0800 | |
201 @@ -206,6 +206,16 @@ SSL_IMPORT SECStatus SSL_SetNextProtoCal | |
202 * protocol in server-preference order. If no matching protocol is found it | |
203 * selects the first supported protocol. | |
204 * | |
205 + * Using this function also allows the client to transparently support ALPN. | |
206 + * The same set of protocols will be advertised via ALPN and, if the server | |
207 + * uses ALPN to select a protocol, SSL_GetNextProto will return | |
208 + * SSL_NEXT_PROTO_SELECTED as the state. | |
209 + * | |
210 + * Since NPN uses the first protocol as the fallback protocol, when sending an | |
211 + * ALPN extension, the first protocol is moved to the end of the list. This | |
212 + * indicates that the fallback protocol is the least preferred. The other | |
213 + * protocols should be in preference order. | |
214 + * | |
215 * The supported protocols are specified in |data| in wire-format (8-bit | |
216 * length-prefixed). For example: "\010http/1.1\006spdy/2". */ | |
217 SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd, | |
218 @@ -215,7 +225,8 @@ SSL_IMPORT SECStatus SSL_SetNextProtoNeg | |
219 typedef enum SSLNextProtoState { | |
220 SSL_NEXT_PROTO_NO_SUPPORT = 0, /* No peer support */ | |
221 SSL_NEXT_PROTO_NEGOTIATED = 1, /* Mutual agreement */ | |
222 - SSL_NEXT_PROTO_NO_OVERLAP = 2 /* No protocol overlap found */ | |
223 + SSL_NEXT_PROTO_NO_OVERLAP = 2, /* No protocol overlap found */ | |
224 + SSL_NEXT_PROTO_SELECTED = 3 /* Server selected proto (ALPN) */ | |
225 } SSLNextProtoState; | |
226 | |
227 /* SSL_GetNextProto can be used in the HandshakeCallback or any time after | |
228 diff -pu a/nss/lib/ssl/sslt.h b/nss/lib/ssl/sslt.h | |
229 --- a/nss/lib/ssl/sslt.h 2014-01-03 19:41:26.443941511 -0800 | |
230 +++ b/nss/lib/ssl/sslt.h 2014-01-03 19:41:52.234363230 -0800 | |
231 @@ -200,12 +200,13 @@ typedef enum { | |
232 #endif | |
233 ssl_signature_algorithms_xtn = 13, | |
234 ssl_use_srtp_xtn = 14, | |
235 + ssl_app_layer_protocol_xtn = 16, | |
236 ssl_session_ticket_xtn = 35, | |
237 ssl_next_proto_nego_xtn = 13172, | |
238 ssl_channel_id_xtn = 30032, | |
239 ssl_renegotiation_info_xtn = 0xff01 /* experimental number */ | |
240 } SSLExtensionType; | |
241 | |
242 -#define SSL_MAX_EXTENSIONS 10 | |
243 +#define SSL_MAX_EXTENSIONS 11 | |
244 | |
245 #endif /* __sslt_h_ */ | |
OLD | NEW |