2 * Gather (Read) entire SSL2 records from socket into buffer.
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/. */
12 /* Forward static declarations */
13 static SECStatus
ssl2_HandleV3HandshakeRecord(sslSocket
*ss
);
16 ** Gather a single record of data from the receiving stream. This code
17 ** first gathers the header (2 or 3 bytes long depending on the value of
18 ** the most significant bit in the first byte) then gathers up the data
19 ** for the record into gs->buf. This code handles non-blocking I/O
20 ** and is to be called multiple times until ss->sec.recordLen != 0.
21 ** This function decrypts the gathered record in place, in gs_buf.
23 * Caller must hold RecvBufLock.
25 * Returns +1 when it has gathered a complete SSLV2 record.
26 * Returns 0 if it hits EOF.
27 * Returns -1 (SECFailure) on any error
28 * Returns -2 (SECWouldBlock) when it gathers an SSL v3 client hello header.
30 ** The SSL2 Gather State machine has 4 states:
31 ** GS_INIT - Done reading in previous record. Haven't begun to read in
32 ** next record. When ssl2_GatherData is called with the machine
33 ** in this state, the machine will attempt to read the first 3
34 ** bytes of the SSL2 record header, and will advance the state
37 ** GS_HEADER - The machine is in this state while waiting for the completion
38 ** of the first 3 bytes of the SSL2 record. When complete, the
39 ** machine will compute the remaining unread length of this record
40 ** and will initiate a read of that many bytes. The machine will
41 ** advance to one of two states, depending on whether the record
42 ** is encrypted (GS_MAC), or unencrypted (GS_DATA).
44 ** GS_MAC - The machine is in this state while waiting for the remainder
45 ** of the SSL2 record to be read in. When the read is completed,
46 ** the machine checks the record for valid length, decrypts it,
47 ** and checks and discards the MAC, then advances to GS_INIT.
49 ** GS_DATA - The machine is in this state while waiting for the remainder
50 ** of the unencrypted SSL2 record to be read in. Upon completion,
51 ** the machine advances to the GS_INIT state and returns the data.
54 ssl2_GatherData(sslSocket
*ss
, sslGather
*gs
, int flags
)
60 PORT_Assert( ss
->opt
.noLocks
|| ssl_HaveRecvBufLock(ss
) );
62 if (gs
->state
== GS_INIT
) {
63 /* Initialize gathering engine */
64 gs
->state
= GS_HEADER
;
69 gs
->recordPadding
= 0;
76 PORT_Assert(ss
->sec
.hash
!= 0);
81 SSL_TRC(30, ("%d: SSL[%d]: gather state %d (need %d more)",
82 SSL_GETPID(), ss
->fd
, gs
->state
, gs
->remainder
));
83 bp
= ((gs
->state
!= GS_HEADER
) ? pBuf
: gs
->hdr
) + gs
->offset
;
84 nb
= ssl_DefRecv(ss
, bp
, gs
->remainder
, flags
);
86 PRINT_BUF(60, (ss
, "raw gather data:", bp
, nb
));
90 SSL_TRC(30, ("%d: SSL[%d]: EOF", SSL_GETPID(), ss
->fd
));
95 SSL_DBG(("%d: SSL[%d]: recv error %d", SSL_GETPID(), ss
->fd
,
104 if (gs
->remainder
> 0) {
108 /* Probably finished this piece */
111 if (!SSL3_ALL_VERSIONS_DISABLED(&ss
->vrange
) && !ss
->firstHsDone
) {
113 PORT_Assert( ss
->opt
.noLocks
|| ssl_Have1stHandshakeLock(ss
) );
115 /* If this looks like an SSL3 handshake record,
116 ** and we're expecting an SSL2 Hello message from our peer,
119 if (gs
->hdr
[0] == content_handshake
) {
120 if ((ss
->nextHandshake
== ssl2_HandleClientHelloMessage
) ||
121 (ss
->nextHandshake
== ssl2_HandleServerHelloMessage
)) {
122 rv
= ssl2_HandleV3HandshakeRecord(ss
);
123 if (rv
== SECFailure
) {
127 /* XXX_1 The call stack to here is:
128 * ssl_Do1stHandshake -> ssl_GatherRecord1stHandshake ->
129 * ssl2_GatherRecord -> here.
130 * We want to return all the way out to ssl_Do1stHandshake,
131 * and have it call ssl_GatherRecord1stHandshake again.
132 * ssl_GatherRecord1stHandshake will call
133 * ssl3_GatherCompleteHandshake when it is called again.
135 * Returning SECWouldBlock here causes
136 * ssl_GatherRecord1stHandshake to return without clearing
137 * ss->handshake, ensuring that ssl_Do1stHandshake will
138 * call it again immediately.
140 * If we return 1 here, ssl_GatherRecord1stHandshake will
141 * clear ss->handshake before returning, and thus will not
142 * be called again by ssl_Do1stHandshake.
144 return SECWouldBlock
;
145 } else if (gs
->hdr
[0] == content_alert
) {
146 if (ss
->nextHandshake
== ssl2_HandleServerHelloMessage
) {
147 /* XXX This is a hack. We're assuming that any failure
148 * XXX on the client hello is a failure to match
151 PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP
);
157 /* we've got the first 3 bytes. The header may be two or three. */
158 if (gs
->hdr
[0] & 0x80) {
159 /* This record has a 2-byte header, and no padding */
160 gs
->count
= ((gs
->hdr
[0] & 0x7f) << 8) | gs
->hdr
[1];
161 gs
->recordPadding
= 0;
163 /* This record has a 3-byte header that is all read in now. */
164 gs
->count
= ((gs
->hdr
[0] & 0x3f) << 8) | gs
->hdr
[1];
165 /* is_escape = (gs->hdr[0] & 0x40) != 0; */
166 gs
->recordPadding
= gs
->hdr
[2];
169 PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG
);
173 if (gs
->count
> gs
->buf
.space
) {
174 err
= sslBuffer_Grow(&gs
->buf
, gs
->count
);
182 if (gs
->hdr
[0] & 0x80) {
183 /* we've already read in the first byte of the body.
184 ** Put it into the buffer.
186 pBuf
[0] = gs
->hdr
[2];
188 gs
->remainder
= gs
->count
- 1;
191 gs
->remainder
= gs
->count
;
196 gs
->recordLen
= gs
->count
- gs
->recordPadding
197 - ss
->sec
.hash
->length
;
200 gs
->recordLen
= gs
->count
;
207 /* Have read in entire rest of the ciphertext.
208 ** Check for valid length.
212 PORT_Assert(gs
->encrypted
);
217 unsigned char mac
[SSL_MAX_MAC_BYTES
];
219 ssl_GetSpecReadLock(ss
); /**********************************/
221 /* If this is a stream cipher, blockSize will be 1,
222 * and this test will always be false.
223 * If this is a block cipher, this will detect records
224 * that are not a multiple of the blocksize in length.
226 if (gs
->count
& (ss
->sec
.blockSize
- 1)) {
227 /* This is an error. Sender is misbehaving */
228 SSL_DBG(("%d: SSL[%d]: sender, count=%d blockSize=%d",
229 SSL_GETPID(), ss
->fd
, gs
->count
,
231 PORT_SetError(SSL_ERROR_BAD_BLOCK_PADDING
);
233 goto spec_locked_done
;
235 PORT_Assert(gs
->count
== gs
->offset
);
237 if (gs
->offset
== 0) {
238 rv
= 0; /* means EOF. */
239 goto spec_locked_done
;
242 /* Decrypt the portion of data that we just received.
243 ** Decrypt it in place.
245 rv
= (*ss
->sec
.dec
)(ss
->sec
.readcx
, pBuf
, &nout
, gs
->offset
,
247 if (rv
!= SECSuccess
) {
248 goto spec_locked_done
;
252 /* Have read in all the MAC portion of record
254 ** Prepare MAC by resetting it and feeding it the shared secret
256 macLen
= ss
->sec
.hash
->length
;
257 if (gs
->offset
>= macLen
) {
258 PRUint32 sequenceNumber
= ss
->sec
.rcvSequence
++;
259 unsigned char seq
[4];
261 seq
[0] = (unsigned char) (sequenceNumber
>> 24);
262 seq
[1] = (unsigned char) (sequenceNumber
>> 16);
263 seq
[2] = (unsigned char) (sequenceNumber
>> 8);
264 seq
[3] = (unsigned char) (sequenceNumber
);
266 (*ss
->sec
.hash
->begin
)(ss
->sec
.hashcx
);
267 (*ss
->sec
.hash
->update
)(ss
->sec
.hashcx
, ss
->sec
.rcvSecret
.data
,
268 ss
->sec
.rcvSecret
.len
);
269 (*ss
->sec
.hash
->update
)(ss
->sec
.hashcx
, pBuf
+ macLen
,
270 gs
->offset
- macLen
);
271 (*ss
->sec
.hash
->update
)(ss
->sec
.hashcx
, seq
, 4);
272 (*ss
->sec
.hash
->end
)(ss
->sec
.hashcx
, mac
, &macLen
, macLen
);
274 PORT_Assert(macLen
== ss
->sec
.hash
->length
);
276 ssl_ReleaseSpecReadLock(ss
); /******************************/
278 if (NSS_SecureMemcmp(mac
, pBuf
, macLen
) != 0) {
279 /* MAC's didn't match... */
280 SSL_DBG(("%d: SSL[%d]: mac check failed, seq=%d",
281 SSL_GETPID(), ss
->fd
, ss
->sec
.rcvSequence
));
282 PRINT_BUF(1, (ss
, "computed mac:", mac
, macLen
));
283 PRINT_BUF(1, (ss
, "received mac:", pBuf
, macLen
));
284 PORT_SetError(SSL_ERROR_BAD_MAC_READ
);
289 ssl_ReleaseSpecReadLock(ss
); /******************************/
292 if (gs
->recordPadding
+ macLen
<= gs
->offset
) {
293 gs
->recordOffset
= macLen
;
294 gs
->readOffset
= macLen
;
295 gs
->writeOffset
= gs
->offset
- gs
->recordPadding
;
298 PORT_SetError(SSL_ERROR_BAD_BLOCK_PADDING
);
300 /* nothing in the buffer any more. */
301 gs
->recordOffset
= 0;
307 gs
->recordLen
= gs
->writeOffset
- gs
->readOffset
;
308 gs
->recordPadding
= 0; /* forget we did any padding. */
313 PRINT_BUF(50, (ss
, "recv clear record:",
314 pBuf
+ gs
->recordOffset
, gs
->recordLen
));
319 ssl_ReleaseSpecReadLock(ss
);
324 /* Have read in all the DATA portion of record */
326 gs
->recordOffset
= 0;
328 gs
->writeOffset
= gs
->offset
;
329 PORT_Assert(gs
->recordLen
== gs
->writeOffset
- gs
->readOffset
);
330 gs
->recordLen
= gs
->offset
;
331 gs
->recordPadding
= 0;
334 ++ss
->sec
.rcvSequence
;
336 PRINT_BUF(50, (ss
, "recv clear record:",
337 pBuf
+ gs
->recordOffset
, gs
->recordLen
));
340 } /* end switch gs->state */
341 } /* end gather loop. */
346 ** Gather a single record of data from the receiving stream. This code
347 ** first gathers the header (2 or 3 bytes long depending on the value of
348 ** the most significant bit in the first byte) then gathers up the data
349 ** for the record into the readBuf. This code handles non-blocking I/O
350 ** and is to be called multiple times until ss->sec.recordLen != 0.
352 * Returns +1 when it has gathered a complete SSLV2 record.
353 * Returns 0 if it hits EOF.
354 * Returns -1 (SECFailure) on any error
355 * Returns -2 (SECWouldBlock)
357 * Called by ssl_GatherRecord1stHandshake in sslcon.c,
358 * and by DoRecv in sslsecur.c
359 * Caller must hold RecvBufLock.
362 ssl2_GatherRecord(sslSocket
*ss
, int flags
)
364 return ssl2_GatherData(ss
, &ss
->gs
, flags
);
367 /* Caller should hold RecvBufLock. */
369 ssl_InitGather(sslGather
*gs
)
376 gs
->dtlsPacketOffset
= 0;
377 gs
->dtlsPacket
.len
= 0;
378 status
= sslBuffer_Grow(&gs
->buf
, 4096);
382 /* Caller must hold RecvBufLock. */
384 ssl_DestroyGather(sslGather
*gs
)
386 if (gs
) { /* the PORT_*Free functions check for NULL pointers. */
387 PORT_ZFree(gs
->buf
.buf
, gs
->buf
.space
);
388 PORT_Free(gs
->inbuf
.buf
);
389 PORT_Free(gs
->dtlsPacket
.buf
);
393 /* Caller must hold RecvBufLock. */
395 ssl2_HandleV3HandshakeRecord(sslSocket
*ss
)
399 PORT_Assert( ss
->opt
.noLocks
|| ssl_HaveRecvBufLock(ss
) );
400 PORT_Assert( ss
->opt
.noLocks
|| ssl_Have1stHandshakeLock(ss
) );
402 /* We've read in 3 bytes, there are 2 more to go in an ssl3 header. */
403 ss
->gs
.remainder
= 2;
406 /* Clearing these handshake pointers ensures that
407 * ssl_Do1stHandshake won't call ssl2_HandleMessage when we return.
409 ss
->nextHandshake
= 0;
410 ss
->securityHandshake
= 0;
412 /* Setting ss->version to an SSL 3.x value will cause
413 ** ssl_GatherRecord1stHandshake to invoke ssl3_GatherCompleteHandshake()
414 ** the next time it is called.
416 rv
= ssl3_NegotiateVersion(ss
, SSL_LIBRARY_VERSION_MAX_SUPPORTED
,
418 if (rv
!= SECSuccess
) {
422 ss
->sec
.send
= ssl3_SendApplicationData
;