- add sources.
[platform/framework/web/crosswalk.git] / src / net / third_party / nss / ssl / ssl3gthr.c
1 /*
2  * Gather (Read) entire SSL3 records from socket into buffer.  
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8 #include "cert.h"
9 #include "ssl.h"
10 #include "sslimpl.h"
11 #include "ssl3prot.h"
12
13 /* 
14  * Attempt to read in an entire SSL3 record.
15  * Blocks here for blocking sockets, otherwise returns -1 with 
16  *      PR_WOULD_BLOCK_ERROR when socket would block.
17  *
18  * returns  1 if received a complete SSL3 record.
19  * returns  0 if recv returns EOF
20  * returns -1 if recv returns < 0  
21  *      (The error value may have already been set to PR_WOULD_BLOCK_ERROR)
22  *
23  * Caller must hold the recv buf lock.
24  *
25  * The Gather state machine has 3 states:  GS_INIT, GS_HEADER, GS_DATA.
26  * GS_HEADER: waiting for the 5-byte SSL3 record header to come in.
27  * GS_DATA:   waiting for the body of the SSL3 record   to come in.
28  *
29  * This loop returns when either
30  *      (a) an error or EOF occurs,
31  *      (b) PR_WOULD_BLOCK_ERROR,
32  *      (c) data (entire SSL3 record) has been received.
33  */
34 static int
35 ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags)
36 {
37     unsigned char *bp;
38     unsigned char *lbp;
39     int            nb;
40     int            err;
41     int            rv           = 1;
42
43     PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
44     if (gs->state == GS_INIT) {
45         gs->state       = GS_HEADER;
46         gs->remainder   = 5;
47         gs->offset      = 0;
48         gs->writeOffset = 0;
49         gs->readOffset  = 0;
50         gs->inbuf.len   = 0;
51     }
52     
53     lbp = gs->inbuf.buf;
54     for(;;) {
55         SSL_TRC(30, ("%d: SSL3[%d]: gather state %d (need %d more)",
56                 SSL_GETPID(), ss->fd, gs->state, gs->remainder));
57         bp = ((gs->state != GS_HEADER) ? lbp : gs->hdr) + gs->offset;
58         nb = ssl_DefRecv(ss, bp, gs->remainder, flags);
59
60         if (nb > 0) {
61             PRINT_BUF(60, (ss, "raw gather data:", bp, nb));
62         } else if (nb == 0) {
63             /* EOF */
64             SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd));
65             rv = 0;
66             break;
67         } else /* if (nb < 0) */ {
68             SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd,
69                      PR_GetError()));
70             rv = SECFailure;
71             break;
72         }
73
74         PORT_Assert( nb <= gs->remainder );
75         if (nb > gs->remainder) {
76             /* ssl_DefRecv is misbehaving!  this error is fatal to SSL. */
77             gs->state = GS_INIT;         /* so we don't crash next time */
78             rv = SECFailure;
79             break;
80         }
81
82         gs->offset    += nb;
83         gs->remainder -= nb;
84         if (gs->state == GS_DATA)
85             gs->inbuf.len += nb;
86
87         /* if there's more to go, read some more. */
88         if (gs->remainder > 0) {
89             continue;
90         }
91
92         /* have received entire record header, or entire record. */
93         switch (gs->state) {
94         case GS_HEADER:
95             /*
96             ** Have received SSL3 record header in gs->hdr.
97             ** Now extract the length of the following encrypted data, 
98             ** and then read in the rest of the SSL3 record into gs->inbuf.
99             */
100             gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4];
101
102             /* This is the max fragment length for an encrypted fragment
103             ** plus the size of the record header.
104             */
105             if(gs->remainder > (MAX_FRAGMENT_LENGTH + 2048 + 5)) {
106                 SSL3_SendAlert(ss, alert_fatal, unexpected_message);
107                 gs->state = GS_INIT;
108                 PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
109                 return SECFailure;
110             }
111
112             gs->state     = GS_DATA;
113             gs->offset    = 0;
114             gs->inbuf.len = 0;
115
116             if (gs->remainder > gs->inbuf.space) {
117                 err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
118                 if (err) {      /* realloc has set error code to no mem. */
119                     return err;
120                 }
121                 lbp = gs->inbuf.buf;
122             }
123             break;      /* End this case.  Continue around the loop. */
124
125
126         case GS_DATA:
127             /* 
128             ** SSL3 record has been completely received.
129             */
130             gs->state = GS_INIT;
131             return 1;
132         }
133     }
134
135     return rv;
136 }
137
138 /*
139  * Read in an entire DTLS record.
140  *
141  * Blocks here for blocking sockets, otherwise returns -1 with
142  *      PR_WOULD_BLOCK_ERROR when socket would block.
143  *
144  * This is simpler than SSL because we are reading on a datagram socket
145  * and datagrams must contain >=1 complete records.
146  *
147  * returns  1 if received a complete DTLS record.
148  * returns  0 if recv returns EOF
149  * returns -1 if recv returns < 0
150  *      (The error value may have already been set to PR_WOULD_BLOCK_ERROR)
151  *
152  * Caller must hold the recv buf lock.
153  *
154  * This loop returns when either
155  *      (a) an error or EOF occurs,
156  *      (b) PR_WOULD_BLOCK_ERROR,
157  *      (c) data (entire DTLS record) has been received.
158  */
159 static int
160 dtls_GatherData(sslSocket *ss, sslGather *gs, int flags)
161 {
162     int            nb;
163     int            err;
164     int            rv           = 1;
165
166     SSL_TRC(30, ("dtls_GatherData"));
167
168     PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
169
170     gs->state = GS_HEADER;
171     gs->offset = 0;
172
173     if (gs->dtlsPacketOffset == gs->dtlsPacket.len) {  /* No data left */
174         gs->dtlsPacketOffset = 0;
175         gs->dtlsPacket.len = 0;
176
177         /* Resize to the maximum possible size so we can fit a full datagram */
178         /* This is the max fragment length for an encrypted fragment
179         ** plus the size of the record header.
180         ** This magic constant is copied from ssl3_GatherData, with 5 changed
181         ** to 13 (the size of the record header).
182         */
183         if (gs->dtlsPacket.space < MAX_FRAGMENT_LENGTH + 2048 + 13) {
184             err = sslBuffer_Grow(&gs->dtlsPacket,
185                                  MAX_FRAGMENT_LENGTH + 2048 + 13);
186             if (err) {  /* realloc has set error code to no mem. */
187                 return err;
188             }
189         }
190
191         /* recv() needs to read a full datagram at a time */
192         nb = ssl_DefRecv(ss, gs->dtlsPacket.buf, gs->dtlsPacket.space, flags);
193
194         if (nb > 0) {
195             PRINT_BUF(60, (ss, "raw gather data:", gs->dtlsPacket.buf, nb));
196         } else if (nb == 0) {
197             /* EOF */
198             SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd));
199             rv = 0;
200             return rv;
201         } else /* if (nb < 0) */ {
202             SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd,
203                      PR_GetError()));
204             rv = SECFailure;
205             return rv;
206         }
207
208         gs->dtlsPacket.len = nb;
209     }
210
211     /* At this point we should have >=1 complete records lined up in
212      * dtlsPacket. Read off the header.
213      */
214     if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < 13) {
215         SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet "
216                  "too short to contain header", SSL_GETPID(), ss->fd));
217         PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
218         gs->dtlsPacketOffset = 0;
219         gs->dtlsPacket.len = 0;
220         rv = SECFailure;
221         return rv;
222     }
223     memcpy(gs->hdr, gs->dtlsPacket.buf + gs->dtlsPacketOffset, 13);
224     gs->dtlsPacketOffset += 13;
225
226     /* Have received SSL3 record header in gs->hdr. */
227     gs->remainder = (gs->hdr[11] << 8) | gs->hdr[12];
228
229     if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < gs->remainder) {
230         SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet too short "
231                  "to contain rest of body", SSL_GETPID(), ss->fd));
232         PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
233         gs->dtlsPacketOffset = 0;
234         gs->dtlsPacket.len = 0;
235         rv = SECFailure;
236         return rv;
237     }
238
239     /* OK, we have at least one complete packet, copy into inbuf */
240     if (gs->remainder > gs->inbuf.space) {
241         err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
242         if (err) {      /* realloc has set error code to no mem. */
243             return err;
244         }
245     }
246
247     memcpy(gs->inbuf.buf, gs->dtlsPacket.buf + gs->dtlsPacketOffset,
248            gs->remainder);
249     gs->inbuf.len = gs->remainder;
250     gs->offset = gs->remainder;
251     gs->dtlsPacketOffset += gs->remainder;
252     gs->state = GS_INIT;
253
254     return 1;
255 }
256
257 /* Gather in a record and when complete, Handle that record.
258  * Repeat this until the handshake is complete, 
259  * or until application data is available.
260  *
261  * Returns  1 when the handshake is completed without error, or 
262  *                 application data is available.
263  * Returns  0 if ssl3_GatherData hits EOF.
264  * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error.
265  * Returns -2 on SECWouldBlock return from ssl3_HandleRecord.
266  *
267  * Called from ssl_GatherRecord1stHandshake       in sslcon.c, 
268  *    and from SSL_ForceHandshake in sslsecur.c
269  *    and from ssl3_GatherAppDataRecord below (<- DoRecv in sslsecur.c).
270  *
271  * Caller must hold the recv buf lock.
272  */
273 int
274 ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
275 {
276     SSL3Ciphertext cText;
277     int            rv;
278     PRBool         canFalseStart = PR_FALSE;
279
280     SSL_TRC(30, ("ssl3_GatherCompleteHandshake"));
281
282     PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
283     do {
284         PRBool handleRecordNow = PR_FALSE;
285
286         ssl_GetSSL3HandshakeLock(ss);
287
288         /* Without this, we may end up wrongly reporting
289          * SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the
290          * peer while we are waiting to be restarted.
291          */
292         if (ss->ssl3.hs.restartTarget) {
293             ssl_ReleaseSSL3HandshakeLock(ss);
294             PORT_SetError(PR_WOULD_BLOCK_ERROR);
295             return (int) SECFailure;
296         }
297
298         /* Treat an empty msgState like a NULL msgState. (Most of the time
299          * when ssl3_HandleHandshake returns SECWouldBlock, it leaves
300          * behind a non-NULL but zero-length msgState).
301          * Test: async_cert_restart_server_sends_hello_request_first_in_separate_record
302          */
303         if (ss->ssl3.hs.msgState.buf) {
304             if (ss->ssl3.hs.msgState.len == 0) {
305                 ss->ssl3.hs.msgState.buf = NULL;
306             } else {
307                 handleRecordNow = PR_TRUE;
308             }
309         }
310
311         ssl_ReleaseSSL3HandshakeLock(ss);
312
313         if (handleRecordNow) {
314             /* ssl3_HandleHandshake previously returned SECWouldBlock and the
315              * as-yet-unprocessed plaintext of that previous handshake record.
316              * We need to process it now before we overwrite it with the next
317              * handshake record.
318              */
319             rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf);
320         } else {
321             /* bring in the next sslv3 record. */
322             if (!IS_DTLS(ss)) {
323                 rv = ssl3_GatherData(ss, &ss->gs, flags);
324             } else {
325                 rv = dtls_GatherData(ss, &ss->gs, flags);
326                 
327                 /* If we got a would block error, that means that no data was
328                  * available, so we check the timer to see if it's time to
329                  * retransmit */
330                 if (rv == SECFailure &&
331                     (PORT_GetError() == PR_WOULD_BLOCK_ERROR)) {
332                     ssl_GetSSL3HandshakeLock(ss);
333                     dtls_CheckTimer(ss);
334                     ssl_ReleaseSSL3HandshakeLock(ss);
335                     /* Restore the error in case something succeeded */
336                     PORT_SetError(PR_WOULD_BLOCK_ERROR);
337                 }
338             }
339
340             if (rv <= 0) {
341                 return rv;
342             }
343
344             /* decipher it, and handle it if it's a handshake.
345              * If it's application data, ss->gs.buf will not be empty upon return.
346              * If it's a change cipher spec, alert, or handshake message,
347              * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSuccess.
348              */
349             cText.type    = (SSL3ContentType)ss->gs.hdr[0];
350             cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2];
351
352             if (IS_DTLS(ss)) {
353                 int i;
354
355                 cText.version = dtls_DTLSVersionToTLSVersion(cText.version);
356                 /* DTLS sequence number */
357                 cText.seq_num.high = 0; cText.seq_num.low = 0;
358                 for (i = 0; i < 4; i++) {
359                     cText.seq_num.high <<= 8; cText.seq_num.low <<= 8;
360                     cText.seq_num.high |= ss->gs.hdr[3 + i];
361                     cText.seq_num.low |= ss->gs.hdr[7 + i];
362                 }
363             }
364
365             cText.buf     = &ss->gs.inbuf;
366             rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf);
367         }
368         if (rv < 0) {
369             return ss->recvdCloseNotify ? 0 : rv;
370         }
371
372         /* If we kicked off a false start in ssl3_HandleServerHelloDone, break
373          * out of this loop early without finishing the handshake.
374          */
375         if (ss->opt.enableFalseStart) {
376             ssl_GetSSL3HandshakeLock(ss);
377             canFalseStart = ss->ssl3.hs.canFalseStart;
378             ssl_ReleaseSSL3HandshakeLock(ss);
379         }
380     } while (ss->ssl3.hs.ws != idle_handshake &&
381              !canFalseStart &&
382              ss->gs.buf.len == 0);
383
384     ss->gs.readOffset = 0;
385     ss->gs.writeOffset = ss->gs.buf.len;
386     return 1;
387 }
388
389 /* Repeatedly gather in a record and when complete, Handle that record.
390  * Repeat this until some application data is received.
391  *
392  * Returns  1 when application data is available.
393  * Returns  0 if ssl3_GatherData hits EOF.
394  * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error.
395  * Returns -2 on SECWouldBlock return from ssl3_HandleRecord.
396  *
397  * Called from DoRecv in sslsecur.c
398  * Caller must hold the recv buf lock.
399  */
400 int
401 ssl3_GatherAppDataRecord(sslSocket *ss, int flags)
402 {
403     int            rv;
404
405     PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
406     do {
407         rv = ssl3_GatherCompleteHandshake(ss, flags);
408     } while (rv > 0 && ss->gs.buf.len == 0);
409
410     return rv;
411 }