Example #1
0
/*
	Encode (encrypt) 'len' bytes of plaintext data that has been placed into
	the buffer given by matrixSslGetWritebuf().  This is an in-situ encode.
	
	CAN ONLY BE CALLED AFTER A PREVIOUS CALL TO matrixSslGetWritebuf

	len		>= 0.If len is zero, we send out a blank ssl record
			len must be <= size returned by matrixSslGetWritebuf()
 
	Returns < 0 on error, total #bytes in outgoing data buf on success
 */
int32 matrixSslEncodeWritebuf(ssl_t *ssl, uint32 len)
{
	unsigned char	*origbuf;
	int32			rc, reserved;
	
	if (!ssl || ((int32)len < 0)) {
		return PS_ARG_FAIL;
	}
	if (ssl->bFlags & BFLAG_CLOSE_AFTER_SENT) {
		return PS_PROTOCOL_FAIL;
	}
	psAssert(ssl->outsize > 0 && ssl->outbuf != NULL);
	/* Caller was given proper locations and lengths in GetWritebuf() */
	origbuf = ssl->outbuf + ssl->outlen;
	if (ssl->outbuf == NULL || (ssl->outsize - ssl->outlen) < (int32)len) {
		return PS_FAILURE;
	}
	
	reserved = ssl->recordHeadLen;
#ifdef USE_BEAST_WORKAROUND
	if (ssl->bFlags & BFLAG_STOP_BEAST) {
		rc = ((ssl->enMacSize + 1) % ssl->enBlockSize) ? ssl->enBlockSize : 0;
		reserved += ssl->recordHeadLen + rc +
			(ssl->enBlockSize * ((ssl->enMacSize + 1)/ssl->enBlockSize)) - 1;
	}
#endif
	
#ifdef USE_TLS_1_1
/*
	If a block cipher is being used TLS 1.1 requires the use
	of an explicit IV.  This is an extra random block of data
	prepended to the plaintext before encryption.  Account for
	that extra length here.
*/
	if ((ssl->flags & SSL_FLAGS_WRITE_SECURE) &&
			(ssl->flags & SSL_FLAGS_TLS_1_1) &&	(ssl->enBlockSize > 1)) {
		reserved += ssl->enBlockSize;
	}
#if defined(USE_TLS_1_2) && defined(USE_AES_GCM)
	if ((ssl->flags & SSL_FLAGS_TLS_1_2) &&	(ssl->flags & SSL_FLAGS_GMAC_W)) {
		reserved += ssl->nonceCtrLen;
	}
#endif /* USE_TLS_1_2 && AES_GCM */
#endif /* USE_TLS_1_1 */

	rc = matrixSslEncode(ssl, origbuf, (ssl->outsize - ssl->outlen),
		origbuf + reserved, &len);
	if (rc < 0) {
		psAssert(rc != SSL_FULL);	/* should not happen */
		return PS_FAILURE;
	}
#ifdef USE_MATRIXSSL_STATS
	matrixsslUpdateStat(ssl, APP_DATA_SENT_STAT, len);
#endif
	ssl->outlen += len;
	return ssl->outlen;
}
Example #2
0
/*
	This public API allows the user to encrypt the plaintext buffer of their
	choice into the internal outbuf that is retrieved when matrixSslGetOutdata
	is called.  This is non-in-situ support and will leave the callers
	plaintext buffer intact

	ptBuf	The plaintext buffer to be converted into an SSL application data
			record.
	len		The length, in bytes, of the ptBuf plaintext data

	Returns < 0 on error, total #bytes in outgoing data buf on success
*/
int32 matrixSslEncodeToOutdata(ssl_t *ssl, unsigned char *ptBuf, uint32 len)
{
	unsigned char	*internalBuf;
	int32			rc, fragLen, recLen, index;

	if (!ssl || !ptBuf) {
		return PS_ARG_FAIL;
	}
	if (ssl->bFlags & BFLAG_CLOSE_AFTER_SENT) {
		return PS_PROTOCOL_FAIL;
	}

#ifdef USE_DTLS
	if (ssl->flags & SSL_FLAGS_DTLS) {
		rc = matrixSslGetEncodedSize(ssl, len);
		if (rc > matrixDtlsGetPmtu()) {
			return PS_LIMIT_FAIL;
		}
	}
#endif

	/* Fragmentation support */
	index = 0;
	while (len > 0) {
		/*	We just call matrixSslGetWritebuf to prepare the buffer */
		if ((rc = matrixSslGetWritebuf(ssl, &internalBuf, len)) < 0) {
			psTraceIntInfo("matrixSslEncodeToOutbuf allocation error: %d\n",
				rc);
			return rc;
		}
		recLen = fragLen = min((uint32)rc, len);
		psAssert(ssl->outsize > 0 && ssl->outbuf != NULL);

		if (ssl->outbuf == NULL ||
				(ssl->outsize - ssl->outlen) < (int32)fragLen) {
			return PS_FAILURE;
		}
		internalBuf = ssl->outbuf + ssl->outlen;

		rc = matrixSslEncode(ssl, internalBuf, (ssl->outsize - ssl->outlen),
			ptBuf + index, (uint32*)&fragLen);
		if (rc < 0) {
			psAssert(rc != SSL_FULL);	/* should not happen */
			return PS_FAILURE;
		}
		index += recLen;
		len -= recLen;
#ifdef USE_MATRIXSSL_STATS
		matrixsslUpdateStat(ssl, APP_DATA_SENT_STAT, fragLen);
#endif
		ssl->outlen += fragLen;
	}
	return ssl->outlen;
}