File Coverage

inc/matrixssl-3-9-3-open/matrixssl/matrixsslApi.c
Criterion Covered Total %
statement 306 523 58.5
branch 190 440 43.1
condition n/a
subroutine n/a
pod n/a
total 496 963 51.5


line stmt bran cond sub pod time code
1             /**
2             * @file matrixsslApi.c
3             * @version 950bba4 (HEAD -> master)
4             *
5             * MatrixSSL Public API Layer.
6             */
7             /*
8             * Copyright (c) 2013-2017 INSIDE Secure Corporation
9             * Copyright (c) PeerSec Networks, 2002-2011
10             * All Rights Reserved
11             *
12             * The latest version of this code is available at http://www.matrixssl.org
13             *
14             * This software is open source; you can redistribute it and/or modify
15             * it under the terms of the GNU General Public License as published by
16             * the Free Software Foundation; either version 2 of the License, or
17             * (at your option) any later version.
18             *
19             * This General Public License does NOT permit incorporating this software
20             * into proprietary programs. If you are unable to comply with the GPL, a
21             * commercial license for this software may be purchased from INSIDE at
22             * http://www.insidesecure.com/
23             *
24             * This program is distributed in WITHOUT ANY WARRANTY; without even the
25             * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
26             * See the GNU General Public License for more details.
27             *
28             * You should have received a copy of the GNU General Public License
29             * along with this program; if not, write to the Free Software
30             * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31             * http://www.gnu.org/copyleft/gpl.html
32             */
33             /******************************************************************************/
34              
35             #include "matrixsslImpl.h"
36              
37             /******************************************************************************/
38             /*
39             Create a new client SSL session
40             This creates internal SSL buffers and cipher structures
41             Clients initiate the connection with a 'HelloRequest', and this data
42             is placed in the outgoing buffer for the caller to send.
43              
44             ssl The ssl_t session structure is returned using this value, on success
45              
46             keys Keys structure initialized with matrixSslReadKeys
47              
48             sid A pointer to storage for a session ID. If there is not yet session
49             cache information, the sid.cipherId should be set to
50             SSL_NULL_WITH_NULL_NULL. After a successful connection to a server,
51             this sid structure will be populated with session cache credentials
52             and for subsequent connections should be used without modification
53             of the cipherId.
54              
55             cipherSpec Array of requested ciphers to negotiate to (0 for server's choice)
56             If non-zero, and server doesn't have it, conn will fail
57              
58             certCb Optional callback to call when validating cert
59              
60             expectedName Optional certificate subject name to validate in the remote
61             certificate. Typically a client would specify the hostname or
62             IP address it is connecting to.
63              
64             extensions Optional TLS extensions (usually NULL)
65              
66             extCb TLS reply extensions from the server
67              
68             flags TODO out of date
69              
70             Return MATRIXSSL_REQUEST_SEND on success
71             < 0 on error. Do not need to call DeleteSession on failure
72             */
73              
74             #ifdef USE_CLIENT_SIDE_SSL
75 11156           int32_t matrixSslNewClientSession(ssl_t **ssl, const sslKeys_t *keys,
76             sslSessionId_t *sid,
77             const psCipher16_t cipherSpec[], uint8_t cipherSpecLen,
78             sslCertCb_t certCb,
79             const char *expectedName, tlsExtension_t *extensions,
80             sslExtCb_t extCb,
81             sslSessOpts_t *options)
82             {
83             ssl_t *lssl;
84             psBuf_t tmp;
85             uint32 len;
86             int32 rc, i;
87              
88 11156 50         if (!ssl)
89             {
90 0           return PS_ARG_FAIL;
91             }
92 11156 50         if (cipherSpecLen > 0 && (cipherSpec == NULL || cipherSpec[0] == 0))
    0          
    0          
93             {
94 0           return PS_ARG_FAIL;
95             }
96 11156 50         if (options == NULL)
97             {
98 0           return PS_ARG_FAIL;
99             }
100              
101 11156           *ssl = NULL;
102 11156           lssl = NULL;
103              
104             # ifdef USE_EAP_FAST
105             if (sid && sid->sessionTicketState == SESS_TICKET_STATE_EAP_FAST)
106             {
107             /* EAP-FAST mode places some restrictions on session resumption */
108             if (sid->cipherId != 0 || sid->sessionTicket == NULL ||
109             sid->sessionTicketLen == 0 ||
110             sid->sessionTicketLifetimeHint != 0)
111             {
112             return PS_ARG_FAIL;
113             }
114             }
115             # endif
116             /* Give priority to cipher suite if session id is provided and doesn't match */
117 11156 50         if (cipherSpec != NULL && cipherSpec[0] != 0 && sid != NULL &&
    100          
    100          
    100          
118 10520           sid->cipherId != 0)
119             {
120 509           rc = 1;
121 509 50         for (i = 0; i < cipherSpecLen; i++)
122             {
123 0 0         if (cipherSpec[i] == sid->cipherId)
124             {
125 0           rc = 0;
126             }
127             }
128 509 50         if (rc)
129             {
130             psTraceInfo("Explicit cipher suite will override session cache\n");
131 509           memset(sid->id, 0, SSL_MAX_SESSION_ID_SIZE);
132 509           memset(sid->masterSecret, 0, SSL_HS_MASTER_SIZE);
133 509           sid->cipherId = 0;
134             }
135             }
136              
137 11156 50         if ((rc = matrixSslNewSession(&lssl, keys, sid, options)) < 0)
138             {
139 0           return rc;
140             }
141 11156           lssl->userPtr = options->userPtr;
142              
143 11156 50         if (options->clientRejectVersionDowngrade)
144             {
145 0           lssl->clientRejectVersionDowngrade = 1;
146             }
147              
148             # ifndef USE_ONLY_PSK_CIPHER_SUITE
149 11156 50         if (expectedName)
150             {
151 0 0         if (psX509ValidateGeneralName((char *) expectedName) < 0)
152             {
153 0           matrixSslDeleteSession(lssl);
154 0           return rc;
155             }
156 0           rc = strlen(expectedName);
157 0           lssl->expectedName = psMalloc(lssl->sPool, rc + 1);
158 0           strcpy(lssl->expectedName, expectedName);
159 0           memcpy(&lssl->validateCertsOpts,
160 0           &options->validateCertsOpts,
161             sizeof(matrixValidateCertsOptions_t));
162             }
163 11156 100         if (certCb)
164             {
165 10127           matrixSslSetCertValidator(lssl, certCb);
166             }
167             # endif
168 11156 50         if (extCb)
169             {
170 0           lssl->extCb = extCb;
171             }
172             # ifdef USE_EAP_FAST
173             if (sid && sid->sessionTicketState == SESS_TICKET_STATE_EAP_FAST)
174             {
175             /* Flag for EncodeClientHello that we want to resume with a ticket */
176             sid->sessionTicketState = SESS_TICKET_STATE_INIT;
177             options->ticketResumption = 1;
178             /* Indicate we're tunnelled below EAP_FAST */
179             lssl->flags |= SSL_FLAGS_EAP_FAST;
180             }
181             # endif
182             RETRY_HELLO:
183 11156           tmp.size = lssl->outsize;
184 11156           tmp.buf = tmp.start = tmp.end = lssl->outbuf;
185 11156 50         if ((rc = matrixSslEncodeClientHello(lssl, &tmp, cipherSpec, cipherSpecLen,
186             &len, extensions, options)) < 0)
187             {
188 0 0         if (rc == SSL_FULL)
189             {
190 0 0         if ((tmp.buf = psRealloc(lssl->outbuf, len, lssl->bufferPool))
191             == NULL)
192             {
193 0           matrixSslDeleteSession(lssl);
194 0           return PS_MEM_FAIL;
195             }
196 0           lssl->outbuf = tmp.buf;
197 0           lssl->outsize = len;
198 0           goto RETRY_HELLO;
199             }
200             else
201             {
202 0           matrixSslDeleteSession(lssl);
203 0           return rc;
204             }
205             }
206 11156 50         psAssert(tmp.start == tmp.buf);
207 11156           lssl->outlen = tmp.end - tmp.start;
208             # ifdef USE_EXT_CERTIFICATE_VERIFY_SIGNING
209             /*
210             Private key size is used by MatrixSSL to estimate the Cv
211             signature size. When using external Cv signing, we do not
212             have access to the private key. However, we can use the
213             public key size instead, since it is the same.
214             If we don't have a cert, we are likely using a PSK ciphersuite
215             in which case a Cv message is not needed.
216             */
217             if (options->useExtCvSigOp)
218             {
219             if (lssl->keys->cert)
220             {
221             lssl->keys->privKey.keysize = lssl->keys->cert->publicKey.keysize;
222             }
223             /*
224             Enable external Cv signature generation for this connection.
225             */
226             lssl->extCvSigOpInUse = 1;
227             }
228             # endif /* USE_EXT_CERTIFICATE_VERIFY_SIGNING */
229 11156           *ssl = lssl;
230 11156           return MATRIXSSL_REQUEST_SEND;
231             }
232              
233             /* SessionID management functions for clients that wish to perform
234             session resumption. This structure handles both the traditional resumption
235             mechanism and the server-stateless session ticket mechanism
236             */
237 110023           int32 matrixSslNewSessionId(sslSessionId_t **sess, void *poolUserPtr)
238             {
239             sslSessionId_t *ses;
240 110023           psPool_t *pool = NULL;
241              
242 110023 50         if ((ses = psMalloc(pool, sizeof(sslSessionId_t))) == NULL)
243             {
244 0           return PS_MEM_FAIL;
245             }
246 110023           memset(ses, 0x0, sizeof(sslSessionId_t));
247 110023           ses->pool = pool;
248 110023           *sess = ses;
249 110023           return PS_SUCCESS;
250             }
251              
252 1           void matrixSslClearSessionId(sslSessionId_t *sess)
253             {
254             psPool_t *pool;
255              
256 1           pool = sess->pool;
257 1           memset(sess, 0x0, sizeof(sslSessionId_t));
258 1           sess->pool = pool;
259 1           }
260              
261 110023           void matrixSslDeleteSessionId(sslSessionId_t *sess)
262             {
263              
264 110023 50         if (sess == NULL)
265             {
266 0           return;
267             }
268             # ifdef USE_STATELESS_SESSION_TICKETS
269 110023 50         if (sess->sessionTicket)
270             {
271 0           psFree(sess->sessionTicket, sess->pool);
272             }
273             # endif
274              
275 110023           memset(sess, 0x0, sizeof(sslSessionId_t));
276 110023           psFree(sess, NULL);
277             }
278              
279             # ifdef USE_EAP_FAST
280             /**
281             Set the TLS connection to connect using an externally provisioned EAP-FAST
282             Protected Access Credential (PAC).
283             @see https://tools.ietf.org/html/rfc4851
284             @param[in,out] sess SessionID structure to fill in with PAC.
285             @param[in] pac_key 32 byte secret key shared between the EAP-FAST peers.
286             This is used by EAP-FAST peers to do session key derivation and is
287             never sent over the wire (encrypted or unencrypted) by TLS.
288             @param[in] pac_opaque Opaque value to be sent as plaintext to the server
289             within the SessionTicket ClientHello Extension so the server can
290             choose the correct pac_key.
291             @param[in] pac_opaque_len Length in bytes of 'pac_opaque'
292             */
293             void matrixSslSetSessionIdEapFast(sslSessionId_t *sess,
294             const unsigned char pac_key[EAP_FAST_PAC_KEY_LEN],
295             const unsigned char *pac_opaque, psSize_t pac_opaque_len)
296             {
297             psAssert(sess && pac_key && pac_opaque && (pac_opaque_len > 0));
298              
299             /* Indicate we're overriding the default Ticket fields and behavior */
300             sess->sessionTicketState = SESS_TICKET_STATE_EAP_FAST;
301             # if EAP_TLS_PAC_KEY_LEN > SSL_HS_MASTER_SIZE
302             # error EAP_TLS_PAC_KEY_LEN too large
303             # endif
304             /** @note, sess->master_secret must go through tprf() before being used */
305             memcpy(sess->masterSecret, pac_key, EAP_FAST_PAC_KEY_LEN);
306             sess->sessionTicket = psMalloc(sess->pool, pac_opaque_len);
307             memcpy(sess->sessionTicket, pac_opaque, pac_opaque_len);
308             sess->sessionTicketLen = pac_opaque_len;
309             }
310              
311             int32_t matrixSslGetEapFastSKS(const ssl_t *ssl,
312             unsigned char session_key_seed[EAP_FAST_SESSION_KEY_SEED_LEN])
313             {
314             if (!ssl || !session_key_seed)
315             {
316             psAssert(ssl && session_key_seed);
317             return PS_FAIL;
318             }
319             if (!ssl->sec.eap_fast_session_key_seed ||
320             matrixSslHandshakeIsComplete(ssl) != PS_TRUE)
321             {
322             return PS_EAGAIN;
323             }
324             memcpy(session_key_seed, ssl->sec.eap_fast_session_key_seed,
325             EAP_FAST_SESSION_KEY_SEED_LEN);
326             return PS_SUCCESS;
327             }
328             # endif /* USE_EAP_FAST */
329              
330             # ifdef USE_EXT_CERTIFICATE_VERIFY_SIGNING
331             int32_t matrixSslNeedCvSignature(ssl_t *ssl)
332             {
333             psAssert(ssl != NULL);
334              
335             if (ssl->extCvSigOpPending)
336             {
337             return PS_TRUE;
338             }
339             else
340             {
341             return PS_FALSE;
342             }
343             }
344              
345             int32_t matrixSslGetHSMessagesHash(ssl_t *ssl, unsigned char *hash, size_t *hash_len)
346             {
347             psAssert(ssl != NULL || hash != NULL || hash_len != NULL);
348              
349             if (!ssl->extCvSigOpPending)
350             {
351             return PS_FAILURE;
352             }
353              
354             psAssert(ssl->extCvHash != NULL);
355              
356             psAssert(ssl->extCvHashLen == 20 || ssl->extCvHashLen == 32 ||
357             ssl->extCvHashLen == 36 || ssl->extCvHashLen == 48 ||
358             ssl->extCvHashLen == 64);
359              
360             if (*hash_len < ssl->extCvHashLen)
361             {
362             return PS_OUTPUT_LENGTH;
363             }
364              
365             memcpy(hash, ssl->extCvHash, ssl->extCvHashLen);
366             *hash_len = ssl->extCvHashLen;
367              
368             return PS_SUCCESS;
369             }
370              
371             int32_t matrixSslGetCvSignatureAlg(ssl_t *ssl)
372             {
373             psAssert(ssl != NULL);
374              
375             if (!matrixSslNeedCvSignature(ssl))
376             {
377             return PS_FAILURE;
378             }
379              
380             return ssl->extCvSigAlg;
381             }
382              
383             int32_t matrixSslGetPubKeySize(ssl_t *ssl)
384             {
385             int32_t type;
386              
387             psAssert(ssl != NULL);
388              
389             if (!matrixSslNeedCvSignature(ssl))
390             {
391             return PS_FAILURE;
392             }
393              
394             type = matrixSslGetCvSignatureAlg(ssl);
395             if (type < 0)
396             {
397             return type;
398             }
399              
400             switch (type)
401             {
402             # ifdef USE_RSA
403             case PS_RSA:
404             return ssl->keys->cert->publicKey.keysize;
405             # endif
406             # ifdef USE_ECC
407             case PS_ECC:
408             return ssl->keys->cert->publicKey.key.ecc.curve->size;
409             # endif
410             default:
411             psTraceIntInfo("matrixSslGetPubKeySize: unsupported alg type: %d\n", type);
412             return PS_UNSUPPORTED_FAIL;
413             }
414             }
415              
416             int32_t matrixSslSetCvSignature(ssl_t *ssl, const unsigned char *sig, const size_t sig_len)
417             {
418             psAssert(ssl != NULL || sig != NULL || sig_len > 0);
419              
420             if (!ssl->extCvSigOpPending)
421             {
422             return PS_FAILURE;
423             }
424              
425             psAssert(ssl->extCvSigAlg == PS_RSA || ssl->extCvSigAlg == PS_ECC);
426              
427             if (ssl->extCvSigAlg == PS_RSA)
428             {
429             ssl->extCvSig = psMalloc(NULL, sig_len);
430             }
431             else
432             {
433             ssl->extCvSig = psMalloc(NULL, sig_len + 2); /* See below. */
434              
435             }
436             if (ssl->extCvSig == NULL)
437             {
438             return PS_MEM_FAIL;
439             }
440              
441             /*
442             struct {
443             digitally-signed struct {
444             opaque handshake_messages[handshake_messages_length];
445             }
446             } CertificateVerify;
447              
448             struct {
449             SignatureAndHashAlgorithm algorithm;
450             opaque signature<0..2^16-1>;
451             } DigitallySigned;
452             */
453              
454             switch (ssl->extCvSigAlg)
455             {
456             # ifdef USE_ECC
457             case PS_ECC:
458             /*
459             The "signature" vector in the DigitallySigned struct
460             needs a two-byte length specifier (see the struct defs above).
461              
462             @note For RSA, the length bytes are added already in
463             WriteCertificateVerify. For ECDSA, we do not know the size
464             of the signature at that point. That's why we need at add the
465             length encoding here.
466              
467             @note When computing the signature internally (i.e. when
468             USE_EXT_CERTIFICATE_VERIFY_SIGNING is not enabled, psEccDsaSign
469             adds the length bytes (the includeSize parameter).
470             */
471             ssl->extCvSig[0] = (sig_len & 0xFF00) >> 8;
472             ssl->extCvSig[1] = (sig_len & 0xFF);
473             memcpy(ssl->extCvSig + 2, sig, sig_len);
474             ssl->extCvSigLen = sig_len + 2;
475             break;
476             # endif
477             # ifdef USE_RSA
478             case PS_RSA:
479             memcpy(ssl->extCvSig, sig, sig_len);
480             ssl->extCvSigLen = sig_len;
481             break;
482             # endif
483             default:
484             psTraceIntInfo("matrixSslSetCvSignature: unsupported alg type: %d\n",
485             ssl->extCvSigAlg);
486             return PS_UNSUPPORTED_FAIL;
487             }
488              
489             return PS_SUCCESS;
490             }
491             # endif /* USE_EXT_CERTIFICATE_VERIFY_SIGNING */
492             #endif /* USE_CLIENT_SIDE_SSL */
493              
494             #ifdef USE_SERVER_SIDE_SSL
495             /******************************************************************************/
496             /*
497             Create a new server SSL session
498             This creates internal SSL buffers and cipher structures
499             Internal SSL state is set to expect an incoming 'HelloRequest'
500              
501             Return MATRIXSSL_SUCCESS on success
502             < 0 on error
503             */
504              
505 0           int32 matrixSslNewServer(ssl_t **ssl,
506             pubkeyCb_t pubkeyCb, pskCb_t pskCb, sslCertCb_t certCb,
507             sslSessOpts_t *options)
508             {
509             int32 rc;
510              
511 0 0         if ((rc = matrixSslNewServerSession(ssl, NULL, certCb, options)) < 0)
512             {
513 0           return rc;
514             }
515              
516 0           (*ssl)->sec.pskCb = (pskCb_t) pskCb;
517             # ifndef USE_ONLY_PSK_CIPHER_SUITE
518 0           (*ssl)->sec.pubkeyCb = (pubkeyCb_t) pubkeyCb;
519             # endif
520 0           return MATRIXSSL_SUCCESS;
521             }
522              
523 11158           int32 matrixSslNewServerSession(ssl_t **ssl, const sslKeys_t *keys,
524             sslCertCb_t certCb,
525             sslSessOpts_t *options)
526             {
527             ssl_t *lssl;
528              
529 11158 50         if (!ssl)
530             {
531 0           return PS_ARG_FAIL;
532             }
533 11158 50         if (options == NULL)
534             {
535 0           return PS_ARG_FAIL;
536             }
537              
538             /* Add SERVER_FLAGS to versionFlag member of options */
539 11158           options->versionFlag |= SSL_FLAGS_SERVER;
540 11158           *ssl = NULL;
541 11158           lssl = NULL;
542              
543             # ifdef USE_CLIENT_AUTH
544 11158 50         if (certCb)
545             {
546 0           options->versionFlag |= SSL_FLAGS_CLIENT_AUTH;
547 0 0         if (matrixSslNewSession(&lssl, keys, NULL, options) < 0)
548             {
549 0           goto NEW_SVR_ERROR;
550             }
551 0           matrixSslSetCertValidator(lssl, (sslCertCb_t) certCb);
552             }
553 11158 50         else if (matrixSslNewSession(&lssl, keys, NULL, options) < 0)
554             {
555 0           goto NEW_SVR_ERROR;
556             }
557             # else
558             psAssert(certCb == NULL);
559             if (matrixSslNewSession(&lssl, keys, NULL, options) < 0)
560             {
561             goto NEW_SVR_ERROR;
562             }
563             # endif /* USE_CLIENT_AUTH */
564              
565             /*
566             For the server, ssl->expectedName can only be populated with
567             the server name parsed from the Server Name Indication
568             extension sent by the client. Clearly, the client cert
569             should not be validated against that.
570             */
571 11158           lssl->validateCertsOpts.flags |= VCERTS_FLAG_SKIP_EXPECTED_NAME_VALIDATION;
572              
573 11158           lssl->userPtr = options->userPtr;
574 11158 50         if (options->maxFragLen < 0)
575             {
576             /* User wants to deny a client request for changing max frag len */
577 0           lssl->extFlags.deny_max_fragment_len = 1;
578             }
579 11158           lssl->maxPtFrag = SSL_MAX_PLAINTEXT_LEN;
580              
581 11158 50         if (options->truncHmac < 0)
582             {
583 0           lssl->extFlags.deny_truncated_hmac = 1;
584             }
585              
586             /* Extended master secret is enabled by default. If user sets to 1 this
587             is a flag to REQUIRE its use */
588 11158 50         if (options->extendedMasterSecret > 0)
589             {
590 0           lssl->extFlags.require_extended_master_secret = 1;
591             }
592              
593 11158           *ssl = lssl;
594 11158           return MATRIXSSL_SUCCESS;
595              
596             NEW_SVR_ERROR:
597 0 0         if (lssl)
598             {
599 0           matrixSslDeleteSession(lssl);
600             }
601 11158           return PS_FAILURE;
602             }
603              
604 0           void matrixSslRegisterSNICallback(ssl_t *ssl, void (*sni_cb)(void *ssl,
605             char *hostname, int32 hostnameLen, sslKeys_t **newKeys))
606             {
607 0           ssl->sni_cb = sni_cb;
608 0           }
609              
610             # ifdef USE_ALPN
611 0           void matrixSslRegisterALPNCallback(ssl_t *ssl,
612             void (*srv_alpn_cb)(void *ssl, short protoCount,
613             char *proto[MAX_PROTO_EXT], int32 protoLen[MAX_PROTO_EXT],
614             int32 *index))
615             {
616 0           ssl->srv_alpn_cb = srv_alpn_cb;
617 0           }
618             # endif
619              
620             #endif /* USE_SERVER_SIDE_SSL */
621              
622              
623              
624             /******************************************************************************/
625             /*
626             Caller is asking for allocated buffer storage to recv data into
627              
628             buf Populated with a transient area where data can be read into
629              
630             Return > 0, size of 'buf' in bytes
631             <= 0 on error
632             */
633 9678           int32 matrixSslGetReadbuf(ssl_t *ssl, unsigned char **buf)
634             {
635 9678 50         if (!ssl || !buf)
    50          
636             {
637 0           return PS_ARG_FAIL;
638             }
639 9678 50         psAssert(ssl && ssl->insize > 0 && ssl->inbuf != NULL);
    50          
    50          
640             /* If there's unprocessed data in inbuf, have caller append to it */
641 9678           *buf = ssl->inbuf + ssl->inlen;
642 9678           return ssl->insize - ssl->inlen;
643             }
644              
645             /* If the required size is known, grow the buffer here so the caller doesn't
646             have to go through the REQUEST_RECV logic of matrixSslReceivedData
647              
648             The return value MAY be larger than the requested size if the inbuf
649             is already larger than what was requested.
650             */
651 0           int32 matrixSslGetReadbufOfSize(ssl_t *ssl, int32 size, unsigned char **buf)
652             {
653             unsigned char *p;
654              
655 0 0         if (!ssl || !buf)
    0          
656             {
657 0           return PS_ARG_FAIL;
658             }
659 0 0         psAssert(ssl && ssl->insize > 0 && ssl->inbuf != NULL);
    0          
    0          
660              
661 0 0         if ((ssl->insize - ssl->inlen) >= size)
662             {
663             /* Already enough room in current buffer */
664 0           return matrixSslGetReadbuf(ssl, buf);
665             }
666              
667             /* Going to have to grow... but do we have to realloc to save data? */
668 0 0         if (ssl->inlen == 0)
669             {
670             /* buffer is empty anyway so can free before alloc and help keep high
671             water mark down */
672 0           psFree(ssl->inbuf, ssl->bufferPool);
673 0           ssl->inbuf = NULL;
674 0 0         if ((ssl->inbuf = psMalloc(ssl->bufferPool, size)) == NULL)
675             {
676 0           ssl->insize = 0;
677 0           return PS_MEM_FAIL;
678             }
679 0           ssl->insize = size;
680 0           *buf = ssl->inbuf;
681 0           return ssl->insize;
682             }
683             else
684             {
685             /* realloc with: total size = current size + requested size */
686 0 0         if ((p = psRealloc(ssl->inbuf, ssl->inlen + size, ssl->bufferPool))
687             == NULL)
688             {
689 0           ssl->inbuf = NULL; ssl->insize = 0; ssl->inlen = 0;
690 0           return PS_MEM_FAIL;
691             }
692 0           ssl->inbuf = p;
693 0           ssl->insize = ssl->inlen + size;
694 0           *buf = ssl->inbuf + ssl->inlen;
695 0           return size;
696             }
697             return PS_FAILURE; /* can't hit */
698             }
699              
700             /******************************************************************************/
701             /*
702             Caller is asking if there is any encoded, outgoing SSL data that should be
703             sent out the transport layer.
704              
705             buf if provided, is updated to point to the data to be sent
706              
707             Return > 0, the number of bytes to send
708             0 if there is no pending data
709             < 0 on error
710             */
711 11841           int32 matrixSslGetOutdata(ssl_t *ssl, unsigned char **buf)
712             {
713 11841 50         if (!ssl)
714             {
715 0           return PS_ARG_FAIL;
716             }
717 11841 50         psAssert(ssl->outsize > 0 && ssl->outbuf != NULL);
    50          
718 11841 50         if (buf)
719             {
720 11841           *buf = ssl->outbuf;
721             }
722 11841           return ssl->outlen; /* Can be 0 */
723             }
724              
725             /******************************************************************************/
726             /*
727             Caller is asking for an allocated buffer to write plaintext into.
728             That plaintext will then be encoded when the caller subsequently calls
729             matrixSslEncodeWritebuf()
730              
731             This is also explicitly called by matrixSslEncodeToOutdata
732              
733             ssl SSL session context
734              
735             buf The data storage to write into will be populated here on success
736              
737             requestedLen The amount of buffer space the caller would like to use
738              
739             Return > 0, success returns # bytes available for plaintext at buf
740             PS_MEM_FAIL if requiredLen too large for current memory
741             <= 0 on error
742             */
743 4125           int32 matrixSslGetWritebuf(ssl_t *ssl, unsigned char **buf, uint32 requestedLen)
744             {
745             uint32 requiredLen, sz, overhead;
746              
747             # ifdef USE_DTLS
748             int32 pmtu;
749             # endif
750             unsigned char *p;
751              
752 4125 50         if (!ssl || !buf)
    50          
753             {
754 0           return PS_ARG_FAIL;
755             }
756 4125 50         psAssert(ssl->outsize > 0 && ssl->outbuf != NULL);
    50          
757              
758             # ifdef USE_BEAST_WORKAROUND
759             /* This is a client-only feature */
760 4125 100         if (!(ssl->flags & SSL_FLAGS_SERVER))
761             {
762             /* Not a problem at all beginning in TLS 1.1 (version 3.2) and never
763             a problem on stream ciphers */
764 4123 50         if ((ssl->majVer == SSL3_MAJ_VER) && (ssl->minVer <= TLS_MIN_VER)
    50          
765 0 0         && (ssl->enBlockSize > 1) && (requestedLen > 1) &&
    0          
    0          
766 0           !(ssl->bFlags & BFLAG_STOP_BEAST))
767             {
768 0           ssl->bFlags |= BFLAG_STOP_BEAST;
769             }
770             }
771             # endif
772              
773             /*
774             First thing is to ensure under the maximum allowed plaintext len according
775             to the SSL specification (or the negotiated max). If not, set it to the
776             max for the calculations and make sure that exact max is returned to the
777             caller. The responsibilty for fragmenting the message is left to them
778             */
779 4125 50         if (requestedLen > (uint32) ssl->maxPtFrag)
780             {
781 0           requestedLen = ssl->maxPtFrag;
782             }
783              
784             /*
785             What is the total encoded size for a plaintext requestedLen. The overhead
786             includes leading header as well as trailing MAC and pad
787              
788             We want to tweak the overhead an extra block to account for a
789             padding miscalculation in matrixSslGetEncodedSize. If that call was
790             made on an exact-sized message and the user decides to use a
791             different record size than requested, we'll need to make sure
792             there is enough available room for any potential padding length.
793             */
794 4125           requiredLen = matrixSslGetEncodedSize(ssl, requestedLen + ssl->enBlockSize);
795              
796 4125 50         psAssert(requiredLen >= requestedLen);
797 4125           overhead = requiredLen - requestedLen;
798              
799             # ifdef USE_DTLS
800             if (ssl->flags & SSL_FLAGS_DTLS)
801             {
802             pmtu = matrixDtlsGetPmtu();
803             if (requiredLen > (uint32) pmtu)
804             {
805             overhead = matrixSslGetEncodedSize(ssl, 0) + ssl->enBlockSize;
806             requiredLen = matrixSslGetEncodedSize(ssl, pmtu - overhead);
807             }
808             }
809             # endif
810              
811             /*
812             Get current available space in outbuf
813             */
814 4125 50         if (ssl->outsize < ssl->outlen)
815             {
816 0           return PS_FAILURE;
817             }
818 4125           sz = ssl->outsize - ssl->outlen;
819              
820             /*
821             If not enough free space for requiredLen, grow the buffer
822             */
823 4125 100         if (sz < requiredLen)
824             {
825 2063 50         if ((p = psRealloc(ssl->outbuf, ssl->outsize +
826             (requiredLen - sz), ssl->bufferPool)) == NULL)
827             {
828 0           return PS_MEM_FAIL;
829             }
830 2063           ssl->outbuf = p;
831 2063           ssl->outsize = ssl->outsize + (requiredLen - sz);
832             /*
833             Recalculate available free space
834             */
835 2063 50         if (ssl->outsize < ssl->outlen)
836             {
837 0           return PS_FAILURE;
838             }
839 2063           sz = ssl->outsize - ssl->outlen;
840             }
841              
842             /*
843             Now that requiredLen has been confirmed/created, return number of available
844             plaintext bytes
845             */
846 4125 50         if (requestedLen <= (uint32) ssl->maxPtFrag)
847             {
848 4125           requestedLen = sz - overhead;
849 4125 50         if (requestedLen > (uint32) ssl->maxPtFrag)
850             {
851 0           requestedLen = ssl->maxPtFrag;
852             }
853             }
854              
855             /*
856             Now return the pointer that has skipped past the record header
857             */
858             # ifdef USE_TLS_1_1
859             /*
860             If a block cipher is being used TLS 1.1 requires the use
861             of an explicit IV. This is an extra random block of data
862             prepended to the plaintext before encryption. Account for
863             that extra length here.
864             */
865 4125 50         if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) &&
    50          
866 4125 100         (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1))
867             {
868 1           *buf = ssl->outbuf + ssl->outlen + ssl->recordHeadLen + ssl->enBlockSize;
869 1           return requestedLen; /* may not be what was passed in */
870             }
871             /* GCM mode will need to save room for the nonce */
872 4124 50         if (ssl->flags & SSL_FLAGS_AEAD_W)
873             {
874 4124 50         *buf = ssl->outbuf + ssl->outlen + ssl->recordHeadLen +
875 4124           AEAD_NONCE_LEN(ssl);
876 4124           return requestedLen; /* may not be what was passed in */
877             }
878             # endif /* USE_TLS_1_1 */
879              
880             # ifdef USE_BEAST_WORKAROUND
881 0 0         if (ssl->bFlags & BFLAG_STOP_BEAST)
882             {
883             /* The reserved space accounts for a full encoding of a 1 byte record.
884             The final -1 is so that when the second encrypt arrives it will
885             land as an in-situ */
886 0 0         overhead = ((ssl->enMacSize + 1) % ssl->enBlockSize) ?
887 0           ssl->enBlockSize : 0;
888 0           *buf = ssl->outbuf + ssl->outlen + (2 * ssl->recordHeadLen) + overhead +
889 0           (ssl->enBlockSize * ((ssl->enMacSize + 1) / ssl->enBlockSize)) - 1;
890             }
891             else
892             {
893 0           *buf = ssl->outbuf + ssl->outlen + ssl->recordHeadLen;
894             }
895             # else
896             *buf = ssl->outbuf + ssl->outlen + ssl->recordHeadLen;
897             # endif
898 0           return requestedLen; /* may not be what was passed in */
899             }
900              
901             /******************************************************************************/
902             /*
903             ptBuf = plaintext buffer
904             ptLen = length of plaintext in bytes
905             ctBuf = allocated ciphertext destination buffer
906             ctLen = INPUT ctBuf buffer size and OUTPUT is length of ciphertext
907              
908             Return value = SUCCESS is > 0 and FAILURE is < 0
909             */
910 0           int32 matrixSslEncodeToUserBuf(ssl_t *ssl, unsigned char *ptBuf, uint32 ptLen,
911             unsigned char *ctBuf, uint32 *ctLen)
912             {
913             int32 rc;
914              
915 0           rc = matrixSslEncode(ssl, ctBuf, *ctLen, ptBuf, &ptLen);
916 0 0         if (rc > 0)
917             {
918 0           *ctLen = ptLen;
919             }
920 0           return rc;
921             }
922              
923             /******************************************************************************/
924             /*
925             Encode (encrypt) 'len' bytes of plaintext data that has been placed into
926             the buffer given by matrixSslGetWritebuf(). This is an in-situ encode.
927              
928             CAN ONLY BE CALLED AFTER A PREVIOUS CALL TO matrixSslGetWritebuf
929              
930             len >= 0.If len is zero, we send out a blank ssl record
931             len must be <= size returned by matrixSslGetWritebuf()
932              
933             Returns < 0 on error, total #bytes in outgoing data buf on success
934             */
935 0           int32 matrixSslEncodeWritebuf(ssl_t *ssl, uint32 len)
936             {
937             unsigned char *origbuf;
938             int32 rc, reserved;
939              
940 0 0         if (!ssl || ((int32) len < 0))
    0          
941             {
942 0           return PS_ARG_FAIL;
943             }
944 0 0         if (ssl->bFlags & BFLAG_CLOSE_AFTER_SENT)
945             {
946 0           return PS_PROTOCOL_FAIL;
947             }
948 0 0         psAssert(ssl->outsize > 0 && ssl->outbuf != NULL);
    0          
949             /* Caller was given proper locations and lengths in GetWritebuf() */
950 0           origbuf = ssl->outbuf + ssl->outlen;
951 0 0         if (ssl->outbuf == NULL || (ssl->outsize - ssl->outlen) < (int32) len)
    0          
952             {
953 0           return PS_FAILURE;
954             }
955              
956 0           reserved = ssl->recordHeadLen;
957             # ifdef USE_BEAST_WORKAROUND
958 0 0         if (ssl->bFlags & BFLAG_STOP_BEAST)
959             {
960 0 0         rc = ((ssl->enMacSize + 1) % ssl->enBlockSize) ? ssl->enBlockSize : 0;
961 0           reserved += ssl->recordHeadLen + rc +
962 0           (ssl->enBlockSize * ((ssl->enMacSize + 1) / ssl->enBlockSize)) - 1;
963             }
964             # endif
965              
966             # ifdef USE_TLS_1_1
967             /*
968             If a block cipher is being used TLS 1.1 requires the use
969             of an explicit IV. This is an extra random block of data
970             prepended to the plaintext before encryption. Account for
971             that extra length here.
972             */
973 0 0         if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) &&
    0          
974 0 0         (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1))
975             {
976 0           reserved += ssl->enBlockSize;
977             }
978 0 0         if (ssl->flags & SSL_FLAGS_AEAD_W)
979             {
980 0 0         reserved += AEAD_NONCE_LEN(ssl);
981             }
982             # endif /* USE_TLS_1_1 */
983              
984 0           rc = matrixSslEncode(ssl, origbuf, (ssl->outsize - ssl->outlen),
985             origbuf + reserved, &len);
986 0 0         if (rc < 0)
987             {
988 0 0         psAssert(rc != SSL_FULL); /* should not happen */
989 0           return PS_FAILURE;
990             }
991             # ifdef USE_MATRIXSSL_STATS
992             matrixsslUpdateStat(ssl, APP_DATA_SENT_STAT, len);
993             # endif
994 0           ssl->outlen += len;
995 0           return ssl->outlen;
996             }
997              
998             /******************************************************************************/
999             /*
1000             This public API allows the user to encrypt the plaintext buffer of their
1001             choice into the internal outbuf that is retrieved when matrixSslGetOutdata
1002             is called. This is non-in-situ support and will leave the callers
1003             plaintext buffer intact
1004              
1005             ptBuf The plaintext buffer to be converted into an SSL application data
1006             record.
1007             len The length, in bytes, of the ptBuf plaintext data
1008              
1009             Returns < 0 on error, total #bytes in outgoing data buf on success
1010             */
1011 4126           int32 matrixSslEncodeToOutdata(ssl_t *ssl, unsigned char *ptBuf, uint32 len)
1012             {
1013             unsigned char *internalBuf;
1014             int32 rc, fragLen, recLen, index;
1015              
1016 4126 50         if (!ssl || !ptBuf)
    50          
1017             {
1018 0           return PS_ARG_FAIL;
1019             }
1020 4126 100         if (ssl->bFlags & BFLAG_CLOSE_AFTER_SENT)
1021             {
1022 1           return PS_PROTOCOL_FAIL;
1023             }
1024              
1025             # ifdef USE_DTLS
1026             if (ssl->flags & SSL_FLAGS_DTLS)
1027             {
1028             rc = matrixSslGetEncodedSize(ssl, len);
1029             if (rc > matrixDtlsGetPmtu())
1030             {
1031             return PS_LIMIT_FAIL;
1032             }
1033             }
1034             # endif
1035              
1036             /* Fragmentation support */
1037 4125           index = 0;
1038 8249 100         while (len > 0)
1039             {
1040             /* We just call matrixSslGetWritebuf to prepare the buffer */
1041 4125 50         if ((rc = matrixSslGetWritebuf(ssl, &internalBuf, len)) < 0)
1042             {
1043             psTraceIntInfo("matrixSslEncodeToOutbuf allocation error: %d\n",
1044             rc);
1045 0           return rc;
1046             }
1047 4125           recLen = fragLen = min((uint32) rc, len);
1048 4125 50         psAssert(ssl->outsize > 0 && ssl->outbuf != NULL);
    50          
1049              
1050 4125 50         if (ssl->outbuf == NULL ||
    50          
1051 4125           (ssl->outsize - ssl->outlen) < (int32) fragLen)
1052             {
1053 0           return PS_FAILURE;
1054             }
1055 4125           internalBuf = ssl->outbuf + ssl->outlen;
1056              
1057 4125           rc = matrixSslEncode(ssl, internalBuf, (ssl->outsize - ssl->outlen),
1058             ptBuf + index, (uint32 *) &fragLen);
1059 4125 100         if (rc < 0)
1060             {
1061 1 50         psAssert(rc != SSL_FULL); /* should not happen */
1062 1           return PS_FAILURE;
1063             }
1064 4124           index += recLen;
1065 4124           len -= recLen;
1066             # ifdef USE_MATRIXSSL_STATS
1067             matrixsslUpdateStat(ssl, APP_DATA_SENT_STAT, fragLen);
1068             # endif
1069 4124           ssl->outlen += fragLen;
1070             }
1071 4126           return ssl->outlen;
1072             }
1073              
1074             /******************************************************************************/
1075             /*
1076             Helper to shrink buffers down to default size
1077             */
1078             #define SSL_INBUF 0
1079             #define SSL_OUTBUF 1
1080              
1081 15017           static void revertToDefaultBufsize(ssl_t *ssl, uint16 inOrOut)
1082             {
1083             int32 defaultSize;
1084              
1085             unsigned char *p;
1086              
1087 15017 100         if (inOrOut == SSL_INBUF)
1088             {
1089             #ifdef USE_DTLS
1090             if (ssl->flags & SSL_FLAGS_DTLS)
1091             {
1092             defaultSize = matrixDtlsGetPmtu();
1093             }
1094             else
1095             {
1096             defaultSize = SSL_DEFAULT_IN_BUF_SIZE;
1097             }
1098             #else
1099 8540           defaultSize = SSL_DEFAULT_IN_BUF_SIZE;
1100             #endif
1101 8540 100         if (ssl->insize > defaultSize && ssl->inlen < defaultSize)
    50          
1102             {
1103             /* It's not fatal if we can't realloc it smaller */
1104 2064 50         if ((p = psRealloc(ssl->inbuf, defaultSize, ssl->bufferPool))
1105             != NULL)
1106             {
1107 2064           ssl->inbuf = p;
1108 8540           ssl->insize = defaultSize;
1109             }
1110             }
1111             }
1112             else
1113             {
1114             #ifdef USE_DTLS
1115             if (ssl->flags & SSL_FLAGS_DTLS)
1116             {
1117             defaultSize = matrixDtlsGetPmtu();
1118             }
1119             else
1120             {
1121             defaultSize = SSL_DEFAULT_OUT_BUF_SIZE;
1122             }
1123             #else
1124 6477           defaultSize = SSL_DEFAULT_OUT_BUF_SIZE;
1125             #endif
1126 6477 100         if (ssl->outsize > defaultSize && ssl->outlen < defaultSize)
    50          
1127             {
1128             /* It's not fatal if we can't realloc it smaller */
1129 1025 50         if ((p = psRealloc(ssl->outbuf, defaultSize, ssl->bufferPool))
1130             != NULL)
1131             {
1132 1025           ssl->outbuf = p;
1133 1025           ssl->outsize = defaultSize;
1134             }
1135             }
1136             }
1137 15017           }
1138              
1139             /******************************************************************************/
1140             /*
1141             Caller has received data from the network and is notifying the SSL layer
1142             */
1143 10699           int32 matrixSslReceivedData(ssl_t *ssl, uint32 bytes, unsigned char **ptbuf,
1144             uint32 *ptlen)
1145             {
1146             unsigned char *buf, *prevBuf;
1147             int32 rc, decodeRet, size, sanity, decodeErr;
1148             uint32 processed, start, len, reqLen;
1149             unsigned char alertLevel, alertDesc;
1150              
1151             unsigned char *p;
1152              
1153 10699 50         if (!ssl || !ptbuf || !ptlen)
    50          
    50          
1154             {
1155 0           return PS_ARG_FAIL;
1156             }
1157              
1158 10699 50         psAssert(ssl->outsize > 0 && ssl->outbuf != NULL);
    50          
1159 10699 50         psAssert(ssl->insize > 0 && ssl->inbuf != NULL);
    50          
1160 10699           *ptbuf = NULL;
1161 10699           *ptlen = 0;
1162 10699           ssl->inlen += bytes;
1163 10699 50         if (ssl->inlen == 0)
1164             {
1165 0           return PS_SUCCESS; /* Nothing to do. Basically a poll */
1166             }
1167             /* This is outside the loop b/c we may want to parse within inbuf later */
1168 10699           buf = ssl->inbuf;
1169             DECODE_MORE:
1170             /* Parameterized sanity check to avoid infinite loops */
1171 17143 100         if (matrixSslHandshakeIsComplete(ssl))
1172             {
1173             /* Minimum possible record size once negotiated */
1174 6194           sanity = ssl->inlen / (SSL3_HEADER_LEN + MD5_HASH_SIZE);
1175             }
1176             else
1177             {
1178             /* Even with an SSLv2 hello, the sanity check will let 1 pass through */
1179 10949           sanity = ssl->inlen / (SSL3_HEADER_LEN + SSL3_HANDSHAKE_HEADER_LEN);
1180             }
1181 17143 50         if (sanity-- < 0)
1182             {
1183 0           return PS_PROTOCOL_FAIL; /* We've tried to decode too many times */
1184             }
1185 17143           len = ssl->inlen;
1186 17143           size = ssl->insize - (buf - ssl->inbuf);
1187 17143           prevBuf = buf;
1188 17143           decodeRet = matrixSslDecode(ssl, &buf, &len, size, &start, &reqLen,
1189             &decodeErr, &alertLevel, &alertDesc);
1190              
1191             /*
1192             Convenience for the cases that expect buf to have moved
1193             - calculate the number of encoded bytes that were decoded
1194             */
1195 17143           processed = buf - prevBuf;
1196 17143           rc = PS_PROTOCOL_FAIL;
1197 17143           switch (decodeRet)
1198             {
1199              
1200             case MATRIXSSL_SUCCESS:
1201              
1202 7501           ssl->inlen -= processed;
1203 7501 100         if (ssl->inlen > 0)
1204             {
1205 6440 50         psAssert(buf > ssl->inbuf);
1206             /*
1207             Pack ssl->inbuf so there is immediate maximum room for potential
1208             outgoing data that needs to be written
1209             */
1210 6440           memmove(ssl->inbuf, buf, ssl->inlen);
1211 6440           buf = ssl->inbuf;
1212 6440           goto DECODE_MORE; /* More data in buffer to process */
1213             }
1214             /*
1215             In this case, we've parsed a finished message and no additional data is
1216             available to parse. We let the client know the handshake is complete,
1217             which can be used as a trigger to begin for example a HTTP request.
1218             */
1219 1061 50         if (!(ssl->bFlags & BFLAG_HS_COMPLETE))
1220             {
1221 1061 100         if (matrixSslHandshakeIsComplete(ssl))
1222             {
1223 1060           ssl->bFlags |= BFLAG_HS_COMPLETE;
1224             #ifdef USE_CLIENT_SIDE_SSL
1225 1060           matrixSslGetSessionId(ssl, ssl->sid);
1226             #endif /* USE_CLIENT_SIDE_SSL */
1227 1060           rc = MATRIXSSL_HANDSHAKE_COMPLETE;
1228             }
1229             else
1230             {
1231 1061           rc = MATRIXSSL_REQUEST_RECV; /* Need to recv more handshake data */
1232             }
1233             }
1234             else
1235             {
1236             #ifdef USE_DTLS
1237             rc = MATRIXSSL_REQUEST_RECV; /* Got FINISHED without CCS */
1238             #else
1239             /* This is an error - we shouldn't get here */
1240             #endif
1241             }
1242 1061           break;
1243              
1244             #ifdef USE_DTLS
1245             case DTLS_RETRANSMIT:
1246             /* Only request a resend if last record in buffer */
1247             ssl->inlen -= processed;
1248             if (ssl->inlen > 0)
1249             {
1250             psAssert(buf > ssl->inbuf);
1251             /*
1252             Pack ssl->inbuf so there is immediate maximum room for potential
1253             outgoing data that needs to be written
1254             */
1255             memmove(ssl->inbuf, buf, ssl->inlen);
1256             buf = ssl->inbuf;
1257             goto DECODE_MORE; /* More data in buffer to process */
1258             }
1259              
1260             /* Flight will be rebuilt when matrixDtlsGetOutdata is called while
1261             outbuf is empty. This is the return case where we are actually
1262             seeing a repeat handshake message so we know something was lost in
1263             flight. */
1264             return MATRIXSSL_REQUEST_SEND;
1265             #endif
1266              
1267             case SSL_SEND_RESPONSE:
1268             #ifdef ENABLE_FALSE_START
1269             /*
1270             If FALSE START is supported, there may be APPLICATION_DATA directly
1271             following the FINISHED message, even though we haven't sent our
1272             CHANGE_CIPHER_SPEC or FINISHED message. This is signalled by buf
1273             having been moved forward, and our response being put directly into
1274             ssl->outbuf, rather than in buf (ssl->inbuf). Return a REQUEST_SEND
1275             so that the data in outbuf is flushed before the remaining data in
1276             ssl->inbuf is parsed.
1277             */
1278 3356 50         if ((ssl->flags & SSL_FLAGS_FALSE_START) && buf != prevBuf)
    0          
1279             {
1280 0           ssl->inlen -= processed;
1281 0 0         psAssert(ssl->inlen > 0);
1282 0 0         psAssert((uint32) ssl->inlen == start);
1283 0 0         psAssert(buf > ssl->inbuf);
1284 0           memmove(ssl->inbuf, buf, ssl->inlen); /* Pack ssl->inbuf */
1285 0           buf = ssl->inbuf;
1286 0           return MATRIXSSL_REQUEST_SEND;
1287             }
1288             #endif
1289             /*
1290             This must be handshake data (or alert) or we'd be in PROCESS_DATA
1291             so there is no way there is anything left inside inbuf to process.
1292             ...so processed isn't valid because the output params are outbuf
1293             related and we simply reset inlen
1294             */
1295 3356           ssl->inlen = 0;
1296              
1297             /* If alert, close connection after sending */
1298 3356 100         if (alertDesc != SSL_ALERT_NONE)
1299             {
1300 90           ssl->bFlags |= BFLAG_CLOSE_AFTER_SENT;
1301             }
1302 3356 50         psAssert(prevBuf == buf);
1303 3356 50         psAssert(ssl->insize >= (int32) len);
1304 3356 50         psAssert(start == 0);
1305 3356 50         psAssert(buf == ssl->inbuf);
1306 3356 50         if (ssl->outlen > 0)
1307             {
1308             /* If data's in outbuf, append inbuf. This is a corner case that
1309             can happen if application data is queued but then incoming data
1310             is processed and discovered to be a re-handshake request.
1311             matrixSslDecode will have constructed the response flight but
1312             we don't want to forget about the app data we haven't sent */
1313 0 0         if (ssl->outlen + (int32) len > ssl->outsize)
1314             {
1315 0 0         if ((p = psRealloc(ssl->outbuf, ssl->outlen + len,
1316             ssl->bufferPool)) == NULL)
1317             {
1318 0           return PS_MEM_FAIL;
1319             }
1320 0           ssl->outbuf = p;
1321 0           ssl->outsize = ssl->outlen + len;
1322             }
1323 0           memcpy(ssl->outbuf + ssl->outlen, ssl->inbuf, len);
1324 0           ssl->outlen += len;
1325             }
1326             else /* otherwise, swap inbuf and outbuf */
1327             {
1328 3356           buf = ssl->outbuf; ssl->outbuf = ssl->inbuf; ssl->inbuf = buf;
1329 3356           ssl->outlen = len;
1330 3356           len = ssl->outsize; ssl->outsize = ssl->insize; ssl->insize = len;
1331 3356           buf = ssl->inbuf;
1332 3356           len = ssl->outlen;
1333             }
1334 3356           rc = MATRIXSSL_REQUEST_SEND; /* We queued data to send out */
1335 3356           break;
1336              
1337             case MATRIXSSL_ERROR:
1338 0           if (decodeErr >= 0)
1339             {
1340             /* printf("THIS SHOULD BE A NEGATIVE VALUE?\n"); */
1341             }
1342 0           return decodeErr; /* Will be a negative value */
1343              
1344             case SSL_ALERT:
1345 91 100         if (alertLevel == SSL_ALERT_LEVEL_FATAL)
1346             {
1347             psTraceIntInfo("Received FATAL alert %d.\n", alertDesc);
1348             }
1349             else
1350             {
1351             /* Closure notify is the normal case */
1352 1           if (alertDesc == SSL_ALERT_CLOSE_NOTIFY)
1353             {
1354             psTraceInfo("Normal SSL closure alert\n");
1355             }
1356             else
1357             {
1358             psTraceIntInfo("Received WARNING alert %d\n", alertDesc);
1359             }
1360             }
1361             /* Let caller access the 2 data bytes (severity and description) */
1362             # ifdef USE_TLS_1_1
1363             /* Been ignoring the explicit IV up to this final return point. */
1364 91 100         if ((ssl->flags & SSL_FLAGS_READ_SECURE) &&
    50          
1365 1 50         (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->enBlockSize > 1))
1366             {
1367 0           prevBuf += ssl->enBlockSize;
1368             }
1369             # endif /* USE_TLS_1_1 */
1370 91 50         psAssert(len == 2);
1371 91           *ptbuf = prevBuf;
1372 91           *ptlen = len;
1373 91           ssl->inlen -= processed;
1374 91           return MATRIXSSL_RECEIVED_ALERT;
1375              
1376             case SSL_PARTIAL:
1377 2068 50         if (reqLen > SSL_MAX_BUF_SIZE)
1378             {
1379 0           return PS_MEM_FAIL;
1380             }
1381 2068 100         if (reqLen > (uint32) ssl->insize)
1382             {
1383 2064 50         if ((p = psRealloc(ssl->inbuf, reqLen, ssl->bufferPool)) == NULL)
1384             {
1385 0           return PS_MEM_FAIL;
1386             }
1387 2064           ssl->inbuf = p;
1388 2064           ssl->insize = reqLen;
1389 2064           buf = ssl->inbuf;
1390             /* Don't need to change inlen */
1391             }
1392              
1393 2068           rc = MATRIXSSL_REQUEST_RECV; /* Expecting more data */
1394 2068           break;
1395              
1396             /* We've got outgoing data that's larger than our buffer */
1397             case SSL_FULL:
1398 4 50         if (reqLen > SSL_MAX_BUF_SIZE)
1399             {
1400 0           return PS_MEM_FAIL;
1401             }
1402             /* We balk if we get a large handshake message */
1403 4           if (reqLen > SSL_MAX_PLAINTEXT_LEN &&
1404 0           !matrixSslHandshakeIsComplete(ssl))
1405             {
1406 0 0         if (reqLen > SSL_MAX_PLAINTEXT_LEN)
1407             {
1408 0           return PS_MEM_FAIL;
1409             }
1410             }
1411             /*
1412             Can't envision any possible case where there is remaining data
1413             in inbuf to process and are getting SSL_FULL.
1414             */
1415 4           ssl->inlen = 0;
1416              
1417             /* Grow inbuf */
1418 4 50         if (reqLen > (uint32) ssl->insize)
1419             {
1420 4           len = ssl->inbuf - buf;
1421 4 50         if ((p = psRealloc(ssl->inbuf, reqLen, ssl->bufferPool)) == NULL)
1422             {
1423 0           return PS_MEM_FAIL;
1424             }
1425 4           ssl->inbuf = p;
1426 4           ssl->insize = reqLen;
1427 4           buf = ssl->inbuf + len;
1428             /* Note we leave inlen untouched here */
1429             }
1430             else
1431             {
1432             psTraceInfo("Encoding error. Possible wrong flight messagSize\n");
1433 0           return PS_PROTOCOL_FAIL; /* error in our encoding */
1434             }
1435 4           goto DECODE_MORE;
1436              
1437             case SSL_PROCESS_DATA:
1438             /*
1439             Possible we received a finished message and app data in the same
1440             flight. In this case, the caller is not notified that the handshake
1441             is complete, but rather is notified that there is application data to
1442             process.
1443             */
1444 4123           if (!(ssl->bFlags & BFLAG_HS_COMPLETE) &&
1445 0           matrixSslHandshakeIsComplete(ssl))
1446             {
1447 0           ssl->bFlags |= BFLAG_HS_COMPLETE;
1448             #ifdef USE_CLIENT_SIDE_SSL
1449 0           matrixSslGetSessionId(ssl, ssl->sid);
1450             #endif /* USE_CLIENT_SIDE_SSL */
1451             }
1452             /*
1453             . prevbuf points to start of unencrypted data
1454             . buf points to start of any remaining unencrypted data
1455             . start is length of remaining encrypted data yet to decode
1456             . len is length of unencrypted data ready for user processing
1457             */
1458 4123           ssl->inlen -= processed;
1459 4123 50         psAssert((uint32) ssl->inlen == start);
1460              
1461             /* Call user plaintext data handler */
1462             #ifdef USE_TLS_1_1
1463             /* Been ignoring the explicit IV up to this final return point. */
1464             /* NOTE: This test has been on enBlockSize for a very long time but
1465             it looks like it should be on deBlockSize since this a decryption.
1466             Changed and added an assert to see if these ever don't match */
1467 4123 50         psAssert(ssl->enBlockSize == ssl->deBlockSize);
1468 4123 50         if ((ssl->flags & SSL_FLAGS_READ_SECURE) &&
    50          
1469 4123 100         (ssl->flags & SSL_FLAGS_TLS_1_1) && (ssl->deBlockSize > 1))
1470             {
1471 1           len -= ssl->deBlockSize;
1472 1           prevBuf += ssl->deBlockSize;
1473             }
1474             /* END enBlockSize to deBlockSize change */
1475             #endif /* USE_TLS_1_1 */
1476 4123           *ptbuf = prevBuf;
1477 4123           *ptlen = len;
1478             #ifdef USE_DTLS
1479             /*
1480             This flag is used in conjuction with flightDone in the buffer
1481             management API set to determine whether we are still in a handshake
1482             state for attempting flight resends. If we are getting app data we
1483             know for certain we are out of the hs states. Testing HandshakeComplete
1484             is not enough because you never know if the other side got FINISHED.
1485             */
1486             if (ssl->flags & SSL_FLAGS_DTLS)
1487             {
1488             ssl->appDataExch = 1;
1489             }
1490             #endif
1491             #ifdef USE_ZLIB_COMPRESSION
1492             if (ssl->compression > 0)
1493             {
1494             return MATRIXSSL_APP_DATA_COMPRESSED;
1495             }
1496             #endif
1497 4123           return MATRIXSSL_APP_DATA;
1498             } /* switch decodeRet */
1499              
1500 6485 100         if (ssl->inlen > 0 && (buf != ssl->inbuf))
    50          
1501             {
1502 0           psAssert(0);
1503             }
1504             /*
1505             Shrink inbuf to default size once inlen < default size, and we aren't
1506             expecting any more data in the buffer. If SSL_PARTIAL, don't shrink the
1507             buffer, since we expect to fill it up shortly.
1508             */
1509 6485 100         if (decodeRet != SSL_PARTIAL)
1510             {
1511 4417           revertToDefaultBufsize(ssl, SSL_INBUF);
1512             }
1513              
1514 10699           return rc;
1515             }
1516              
1517             /******************************************************************************/
1518             /*
1519             Plaintext data has been processed as a response to MATRIXSSL_APP_DATA or
1520             MATRIXSSL_RECEIVED_ALERT return codes from matrixSslReceivedData()
1521             Return:
1522             < 0 on error
1523             0 if there is no more incoming ssl data in the buffer
1524             Caller should take whatever action is appropriate to the specific
1525             protocol implementation, eg. read for more data, close, etc.
1526             > 0 error code is same meaning as from matrixSslReceivedData()
1527             In this case, ptbuf and ptlen will be modified and caller should
1528             handle return code identically as from matrixSslReceivedData()
1529             This is the case when more than one SSL record is in the buffer
1530             */
1531 4123           int32 matrixSslProcessedData(ssl_t *ssl, unsigned char **ptbuf, uint32 *ptlen)
1532             {
1533             uint32 ctlen;
1534              
1535 4123 50         if (!ssl || !ptbuf || !ptlen)
    50          
    50          
1536             {
1537 0           return PS_ARG_FAIL;
1538             }
1539 4123           *ptbuf = NULL;
1540 4123           *ptlen = 0;
1541              
1542 4123 50         psAssert(ssl->insize > 0 && ssl->inbuf != NULL);
    50          
1543             /* Move any remaining data to the beginning of the buffer */
1544 4123 100         if (ssl->inlen > 0)
1545             {
1546 1021           ctlen = ssl->rec.len + ssl->recordHeadLen;
1547 1021 50         if (ssl->flags & SSL_FLAGS_AEAD_R)
1548             {
1549             /* This overhead was removed from rec.len after the decryption
1550             to keep buffer logic working. */
1551 1021 50         ctlen += AEAD_TAG_LEN(ssl) + AEAD_NONCE_LEN(ssl);
    50          
1552             }
1553 1021           memmove(ssl->inbuf, ssl->inbuf + ctlen, ssl->inlen);
1554             }
1555             /* Shrink inbuf to default size once inlen < default size */
1556 4123           revertToDefaultBufsize(ssl, SSL_INBUF);
1557              
1558             /* If there's more data, try to decode it here and return that code */
1559 4123 100         if (ssl->inlen > 0)
1560             {
1561             /* NOTE: ReceivedData cannot return 0 */
1562 1021           return matrixSslReceivedData(ssl, 0, ptbuf, ptlen);
1563             }
1564 3102           return MATRIXSSL_SUCCESS;
1565             }
1566              
1567              
1568             /******************************************************************************/
1569             /*
1570             Returns < 0 on error
1571             */
1572 1           int32 matrixSslEncodeClosureAlert(ssl_t *ssl)
1573             {
1574             sslBuf_t sbuf;
1575             int32 rc;
1576             uint32 reqLen, newLen;
1577              
1578             unsigned char *p;
1579              
1580 1 50         if (!ssl)
1581             {
1582 0           return PS_ARG_FAIL;
1583             }
1584 1 50         psAssert(ssl->outsize > 0 && ssl->outbuf != NULL);
    50          
1585             /*
1586             Only encode the closure alert if we aren't already flagged for close
1587             If we are flagged, we do not want to send any more data
1588             */
1589 1           newLen = 0;
1590 1 50         if (!(ssl->bFlags & BFLAG_CLOSE_AFTER_SENT))
1591             {
1592 1           ssl->bFlags |= BFLAG_CLOSE_AFTER_SENT;
1593             L_CLOSUREALERT:
1594 1           sbuf.buf = sbuf.start = sbuf.end = ssl->outbuf + ssl->outlen;
1595 1           sbuf.size = ssl->outsize - ssl->outlen;
1596 1           rc = sslEncodeClosureAlert(ssl, &sbuf, &reqLen);
1597 1 50         if (rc == SSL_FULL && newLen == 0)
    0          
1598             {
1599 0           newLen = ssl->outlen + reqLen;
1600 0 0         if ((p = psRealloc(ssl->outbuf, newLen, ssl->bufferPool)) == NULL)
1601             {
1602 0           return PS_MEM_FAIL;
1603             }
1604 0           ssl->outbuf = p;
1605 0           ssl->outsize = newLen;
1606 0           goto L_CLOSUREALERT; /* Try one more time */
1607             }
1608 1 50         else if (rc != PS_SUCCESS)
1609             {
1610 0           return rc;
1611             }
1612 1           ssl->outlen += sbuf.end - sbuf.start;
1613             }
1614 1           return MATRIXSSL_SUCCESS;
1615             }
1616              
1617             # ifdef SSL_REHANDSHAKES_ENABLED
1618             /******************************************************************************/
1619             /*
1620             Encode a CLIENT_HELLO or HELLO_REQUEST to re-handshake an existing
1621             connection.
1622              
1623             Can't "downgrade" the re-handshake. This means if keys or certCb are
1624             NULL we stick with whatever the session already has loaded.
1625              
1626             keys should be NULL if no change in key material is being made
1627              
1628             cipherSpec is only used by clients
1629             */
1630 8           int32_t matrixSslEncodeRehandshake(ssl_t *ssl, sslKeys_t *keys,
1631             int32 (*certCb)(ssl_t *ssl, psX509Cert_t *cert, int32 alert),
1632             uint32 sessionOption,
1633             const psCipher16_t cipherSpec[], uint8_t cipherSpecLen)
1634             {
1635             sslBuf_t sbuf;
1636             int32 rc, i;
1637             uint32 reqLen, newLen;
1638              
1639             unsigned char *p;
1640             sslSessOpts_t options;
1641              
1642             /* Clear extFlags for rehandshakes */
1643 8           ssl->extFlags.truncated_hmac = 0;
1644 8           ssl->extFlags.sni = 0;
1645              
1646 8 50         if (!ssl)
1647             {
1648 0           return PS_ARG_FAIL;
1649             }
1650 8 100         if (cipherSpecLen > 0 && (cipherSpec == NULL || cipherSpec[0] == 0))
    50          
    50          
1651             {
1652 0           return PS_ARG_FAIL;
1653             }
1654 8 50         if (ssl->bFlags & BFLAG_CLOSE_AFTER_SENT)
1655             {
1656 0           return PS_PROTOCOL_FAIL;
1657             }
1658 8 50         psAssert(ssl->outsize > 0 && ssl->outbuf != NULL);
    50          
1659              
1660             # ifdef DISABLE_DTLS_CLIENT_CHANGE_CIPHER_FROM_GCM_TO_GCM
1661             # endif /* DISABLE_DTLS_CLIENT_CHANGE_CIPHER_FROM_GCM_TO_GCM */
1662              
1663             # ifdef USE_ZLIB_COMPRESSION
1664             /* Re-handshakes are not currently supported for compressed sessions. */
1665             if (ssl->compression > 0)
1666             {
1667             psTraceInfo("Re-handshakes not supported for compressed sessions\n");
1668             return PS_UNSUPPORTED_FAIL;
1669             }
1670             # endif
1671             /*
1672             The only explicit option that can be passsed in is
1673             SSL_OPTION_FULL_HANDSHAKE to indicate no resumption is allowed
1674             */
1675 8 100         if (sessionOption == SSL_OPTION_FULL_HANDSHAKE)
1676             {
1677 3           matrixSslSetSessionOption(ssl, sessionOption, NULL);
1678             }
1679             /*
1680             If the key material or cert callback are provided we have to assume it
1681             was intentional to "upgrade" the re-handshake and we force full handshake
1682             No big overhead calling SetSessionOption with FULL_HS multiple times.
1683             */
1684 8 100         if (keys != NULL)
1685             {
1686 2           ssl->keys = keys;
1687 2           matrixSslSetSessionOption(ssl, SSL_OPTION_FULL_HANDSHAKE, NULL);
1688             }
1689              
1690             # ifndef USE_ONLY_PSK_CIPHER_SUITE
1691 8 100         if (certCb != NULL)
1692             {
1693 2           matrixSslSetSessionOption(ssl, SSL_OPTION_FULL_HANDSHAKE, NULL);
1694             # if defined(USE_CLIENT_AUTH) || defined(USE_CLIENT_SIDE_SSL)
1695 2           matrixSslSetCertValidator(ssl, certCb);
1696             # endif /* USE_CLIENT_AUTH || USE_CLIENT_SIDE_SSL */
1697             # if defined(USE_CLIENT_AUTH) && defined(USE_SERVER_SIDE_SSL)
1698             /*
1699             If server, a certCb is an explicit flag to set client auth just as
1700             it is in matrixSslNewServerSession
1701             */
1702 2 50         if (ssl->flags & SSL_FLAGS_SERVER)
1703             {
1704 0           matrixSslSetSessionOption(ssl, SSL_OPTION_ENABLE_CLIENT_AUTH, NULL);
1705             }
1706             # endif /* USE_CLIENT_AUTH && USE_SERVER_SIDE_SSL */
1707             }
1708             # endif /* !USE_ONLY_PSK_CIPHER_SUITE */
1709              
1710             /*
1711             If cipher spec is explicitly different from current, force a full handshake
1712             */
1713 8 50         if (!(ssl->flags & SSL_FLAGS_SERVER))
1714             {
1715 8           rc = 0;
1716 8 100         if (cipherSpecLen > 0)
1717             {
1718 2           rc = 1;
1719 4 100         for (i = 0; i < cipherSpecLen; i++)
1720             {
1721 2 50         if (cipherSpec[i] == ssl->cipher->ident)
1722             {
1723 0           rc = 0;
1724             }
1725             }
1726             }
1727 8 100         if (rc)
1728             {
1729 2           matrixSslSetSessionOption(ssl, SSL_OPTION_FULL_HANDSHAKE, NULL);
1730             }
1731             }
1732             # ifdef USE_DTLS
1733             if (ssl->flags & SSL_FLAGS_DTLS)
1734             {
1735             /* Resend epoch should be brought up-to-date with new epoch */
1736             ssl->resendEpoch[0] = ssl->epoch[0];
1737             ssl->resendEpoch[1] = ssl->epoch[1];
1738              
1739             ssl->msn = ssl->resendMsn = 0;
1740             }
1741             # endif /* USE_DTLS */
1742             /*
1743             Options are set. Encode the HELLO message
1744             */
1745 8           newLen = 0;
1746             L_REHANDSHAKE:
1747 8 50         if (ssl->flags & SSL_FLAGS_SERVER)
1748             {
1749 0           sbuf.buf = sbuf.start = sbuf.end = ssl->outbuf + ssl->outlen;
1750 0           sbuf.size = ssl->outsize - ssl->outlen;
1751 0 0         if ((rc = matrixSslEncodeHelloRequest(ssl, &sbuf, &reqLen)) < 0)
1752             {
1753 0 0         if (rc == SSL_FULL && newLen == 0)
    0          
1754             {
1755 0           newLen = ssl->outlen + reqLen;
1756 0 0         if (newLen < SSL_MAX_BUF_SIZE)
1757             {
1758 0 0         if ((p = psRealloc(ssl->outbuf, newLen, ssl->bufferPool))
1759             == NULL)
1760             {
1761 0           return PS_MEM_FAIL;
1762             }
1763 0           ssl->outbuf = p;
1764 0           ssl->outsize = newLen;
1765 0           goto L_REHANDSHAKE;
1766             }
1767             }
1768 0           return rc;
1769             }
1770             }
1771             else
1772             {
1773 8           sbuf.buf = sbuf.start = sbuf.end = ssl->outbuf + ssl->outlen;
1774 8           sbuf.size = ssl->outsize - ssl->outlen;
1775 8           memset(&options, 0x0, sizeof(sslSessOpts_t));
1776             # ifdef USE_ECC_CIPHER_SUITE
1777 8           options.ecFlags = ssl->ecInfo.ecFlags;
1778             # endif
1779             /* Use extended master secret if original connection used it */
1780 8 50         if (ssl->extFlags.extended_master_secret == 1)
1781             {
1782 8           options.extendedMasterSecret = 1;
1783 8           ssl->extFlags.extended_master_secret = 0;
1784             }
1785             else
1786             {
1787 0           options.extendedMasterSecret = -1;
1788             }
1789              
1790 8 100         if ((rc = matrixSslEncodeClientHello(ssl, &sbuf, cipherSpec,
1791             cipherSpecLen, &reqLen, NULL, &options)) < 0)
1792             {
1793 1 50         if (rc == SSL_FULL && newLen == 0)
    0          
1794             {
1795 0           newLen = ssl->outlen + reqLen;
1796 0 0         if (newLen < SSL_MAX_BUF_SIZE)
1797             {
1798 0 0         if ((p = psRealloc(ssl->outbuf, newLen, ssl->bufferPool))
1799             == NULL)
1800             {
1801 0           return PS_MEM_FAIL;
1802             }
1803 0           ssl->outbuf = p;
1804 0           ssl->outsize = newLen;
1805 0           goto L_REHANDSHAKE;
1806             }
1807             }
1808 1           return rc;
1809             }
1810             }
1811 7           ssl->outlen += sbuf.end - sbuf.start;
1812 8           return MATRIXSSL_SUCCESS;
1813             }
1814              
1815             /* Disabling and re-enabling of re-handshakes is a receive feature. In other
1816             words, a NO_RENEGOTIATION alert will be sent if a request is sent from the
1817             peer. */
1818 0           int32 matrixSslDisableRehandshakes(ssl_t *ssl)
1819             {
1820 0 0         if (ssl == NULL)
1821             {
1822 0           return PS_ARG_FAIL;
1823             }
1824 0           matrixSslSetSessionOption(ssl, SSL_OPTION_DISABLE_REHANDSHAKES, NULL);
1825 0           return PS_SUCCESS;
1826             }
1827              
1828 0           int32 matrixSslReEnableRehandshakes(ssl_t *ssl)
1829             {
1830 0 0         if (ssl == NULL)
1831             {
1832 0           return PS_ARG_FAIL;
1833             }
1834 0           matrixSslSetSessionOption(ssl, SSL_OPTION_REENABLE_REHANDSHAKES, NULL);
1835 0           return PS_SUCCESS;
1836             }
1837              
1838             /* Undocumented helper functions to manage rehandshake credits for testing */
1839 0           int32 matrixSslGetRehandshakeCredits(ssl_t *ssl)
1840             {
1841 0 0         if (ssl)
1842             {
1843 0           return ssl->rehandshakeCount;
1844             }
1845 0           return -1;
1846             }
1847              
1848 0           void matrixSslAddRehandshakeCredits(ssl_t *ssl, int32 credits)
1849             {
1850 0 0         if (ssl)
1851             {
1852             /* User must re-enable rehandshaking before adding credits */
1853 0 0         if (ssl->rehandshakeCount >= 0)
1854             {
1855 0 0         if ((ssl->rehandshakeCount + credits) < 0x8000)
1856             {
1857 0           ssl->rehandshakeCount += credits;
1858             }
1859             }
1860             }
1861 0           }
1862              
1863             # else /* !SSL_REHANDSHAKES_ENABLED */
1864             int32_t matrixSslEncodeRehandshake(ssl_t *ssl, sslKeys_t *keys,
1865             int32 (*certCb)(ssl_t *ssl, psX509Cert_t *cert, int32 alert),
1866             uint32_t sessionOption,
1867             const psCipher16_t cipherSpec[], uint8_t cipherSpecLen)
1868             {
1869             psTraceInfo("Rehandshaking is disabled. matrixSslEncodeRehandshake off\n");
1870             return PS_FAILURE;
1871             }
1872             int32 matrixSslDisableRehandshakes(ssl_t *ssl)
1873             {
1874             psTraceInfo("Rehandshaking is not compiled into library at all.\n");
1875             return PS_FAILURE;
1876             }
1877              
1878             int32 matrixSslReEnableRehandshakes(ssl_t *ssl)
1879             {
1880             psTraceInfo("Rehandshaking is not compiled into library at all.\n");
1881             return PS_FAILURE;
1882             }
1883             # endif /* SSL_REHANDSHAKES_ENABLED */
1884              
1885             /******************************************************************************/
1886             /*
1887             Caller is indicating 'bytes' of data was written
1888             */
1889 6568           int32 matrixSslSentData(ssl_t *ssl, uint32 bytes)
1890             {
1891             int32 rc;
1892              
1893 6568 50         if (!ssl)
1894             {
1895 0           return PS_ARG_FAIL;
1896             }
1897 6568 50         if (bytes == 0)
1898             {
1899 0 0         if (ssl->outlen > 0)
1900             {
1901 0           return MATRIXSSL_REQUEST_SEND;
1902             }
1903             else
1904             {
1905 0           return MATRIXSSL_SUCCESS; /* Nothing to do */
1906             }
1907             }
1908 6568 50         psAssert(ssl->outsize > 0 && ssl->outbuf != NULL);
    50          
1909 6568           ssl->outlen -= bytes;
1910              
1911 6568           rc = MATRIXSSL_SUCCESS;
1912 6568 50         if (ssl->outlen > 0)
1913             {
1914 0           memmove(ssl->outbuf, ssl->outbuf + bytes, ssl->outlen);
1915             /* This was changed during 3.7.1 DTLS work. The line below used to be:
1916             rc = MATRIXSSL_REQUEST_SEND; and it was possible for it to be
1917             overridden with HANDSHAKE_COMPLETE below. This was a problem
1918             if only the ChangeCipherSpec portion of the final flight was
1919             just set becuase matrixSslHandshakeIsComplete would return 1
1920             because the state looks right. However, there would still be a
1921             FINISHED message sitting in outbuf when COMPLETE is returned.
1922              
1923             This seemed like a bigger problem than just the DTLS test case
1924             that caught it. If the transport layer of straight TLS sent off
1925             only the CCS message for some reason, this would cause the same
1926             odd combo of COMPLETE but with a FINISHED message that hasn't
1927             been sent.
1928              
1929             It seems fine to return REQUEST_SEND whenever there is data left
1930             in the outgoing buffer but it is suspecious it wasn't written
1931             this way to begin with so maybe there was another corner case
1932             the COMPLETE was solving. Hope not.
1933              
1934             In any case, it looks safe to make this a global change but if you
1935             are reading this because you are trying to track down a change in
1936             behavior in matrixSslSentData, maybe this documentation will help.
1937             */
1938 0           return MATRIXSSL_REQUEST_SEND;
1939             }
1940             /* If there's nothing left to flush, reallocate the buffer smaller. */
1941 6568 50         if ((ssl->outlen == 0) && (ssl->bFlags & BFLAG_CLOSE_AFTER_SENT))
    100          
1942             {
1943             /* We want to close the connection now */
1944 91           rc = MATRIXSSL_REQUEST_CLOSE;
1945             }
1946             else
1947             {
1948 6477           revertToDefaultBufsize(ssl, SSL_OUTBUF);
1949             }
1950             /* Indicate the handshake is complete, in this case, the finished message
1951             is being/has been just sent. Occurs in session resumption. */
1952 11074           if (!(ssl->bFlags & BFLAG_HS_COMPLETE) &&
1953 4506           matrixSslHandshakeIsComplete(ssl))
1954             {
1955 1059           ssl->bFlags |= BFLAG_HS_COMPLETE;
1956             # ifdef USE_CLIENT_SIDE_SSL
1957 1059           matrixSslGetSessionId(ssl, ssl->sid);
1958             # endif /* USE_CLIENT_SIDE_SSL */
1959 1059           rc = MATRIXSSL_HANDSHAKE_COMPLETE;
1960             # ifdef USE_SSL_INFORMATIONAL_TRACE
1961             /* Client side resumed completion or server standard completion */
1962             matrixSslPrintHSDetails(ssl);
1963             # endif
1964             }
1965 6568           return rc;
1966             }
1967              
1968             # ifdef USE_ZLIB_COMPRESSION
1969             int32 matrixSslIsSessionCompressionOn(ssl_t *ssl)
1970             {
1971             if (ssl->compression > 0)
1972             {
1973             return PS_TRUE;
1974             }
1975             return PS_FALSE;
1976             }
1977             # endif
1978              
1979             /******************************************************************************/
1980