- add sources.
[platform/framework/web/crosswalk.git] / src / net / third_party / nss / patches / alpn.patch
1 diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
2 --- a/nss/lib/ssl/ssl3con.c     2013-07-31 14:17:20.669282120 -0700
3 +++ b/nss/lib/ssl/ssl3con.c     2013-07-31 14:28:56.549496061 -0700
4 @@ -9912,8 +9912,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     2013-07-31 14:10:00.342814862 -0700
18 +++ b/nss/lib/ssl/ssl3ext.c     2013-07-31 14:28:56.549496061 -0700
19 @@ -53,8 +53,12 @@ static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss,
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 @@ -252,6 +256,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
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 @@ -271,18 +276,19 @@ static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = {
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 @@ -606,6 +612,11 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
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 @@ -639,6 +650,44 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
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 @@ -672,6 +721,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 2013-07-31 14:10:35.113325316 -0700
200 +++ b/nss/lib/ssl/ssl.h 2013-07-31 14:28:56.589496647 -0700
201 @@ -203,6 +203,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 @@ -212,7 +217,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        2013-07-31 14:13:43.806096237 -0700
230 +++ b/nss/lib/ssl/sslt.h        2013-07-31 14:28:56.609496941 -0700
231 @@ -195,12 +195,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               = 30031,
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_ */