| 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 |  |  |  |  |  |  |  |