/*
	Add the given data to the running hash of the handshake messages
*/
int32 sslUpdateHSHash(ssl_t *ssl, unsigned char *in, uint32 len)
{

#ifdef USE_TLS_1_2
	/* Keep a running total of each for greatest RFC support when it comes
		to the CertificateVerify message.  Although, trying to be smart
		about MD5 and SHA-2 based on protocol version */
	if ((ssl->majVer == 0 && ssl->minVer == 0) ||
			ssl->minVer == TLS_1_2_MIN_VER) {
		psSha256Update(&ssl->sec.msgHashSha256, in, len);
#ifdef USE_SHA384
		psSha384Update(&ssl->sec.msgHashSha384, in, len);
#endif
	}
#ifndef USE_ONLY_TLS_1_2
	if (ssl->reqMinVer == 0 || ssl->minVer != TLS_1_2_MIN_VER) {
		psMd5Update(&ssl->sec.msgHashMd5, in, len);
	}
	psSha1Update(&ssl->sec.msgHashSha1, in, len);
#endif

#else
	psMd5Update(&ssl->sec.msgHashMd5, in, len);
	psSha1Update(&ssl->sec.msgHashSha1, in, len);
#endif

	return 0;
}
Exemple #2
0
/*
 *	Generates all key material.
 */
int32 sslDeriveKeys(ssl_t *ssl)
{
	psDigestContext_t	md5Ctx, sha1Ctx;
	unsigned char		buf[MD5_HASH_SIZE + SHA1_HASH_SIZE];
	unsigned char		*tmp;
	uint32				i;

/*
	If this session is resumed, we want to reuse the master secret to 
	regenerate the key block with the new random values.
*/
	if (ssl->flags & SSL_FLAGS_RESUMED) {
		goto skipPremaster;
	}
/*
	master_secret =
		MD5(pre_master_secret + SHA('A' + pre_master_secret +
			ClientHello.random + ServerHello.random)) +
		MD5(pre_master_secret + SHA('BB' + pre_master_secret +
			ClientHello.random + ServerHello.random)) +
		MD5(pre_master_secret + SHA('CCC' + pre_master_secret +
			ClientHello.random + ServerHello.random));
*/
	tmp = ssl->sec.masterSecret;
	for (i = 0; i < 3; i++) {
		psSha1Init(&sha1Ctx);
		psSha1Update(&sha1Ctx, salt[i], i + 1);
		psSha1Update(&sha1Ctx, ssl->sec.premaster, ssl->sec.premasterSize);
		psSha1Update(&sha1Ctx, ssl->sec.clientRandom, SSL_HS_RANDOM_SIZE);
		psSha1Update(&sha1Ctx, ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE);
		psSha1Final(&sha1Ctx, buf);
		
		psMd5Init(&md5Ctx);
		psMd5Update(&md5Ctx, ssl->sec.premaster, ssl->sec.premasterSize);
		psMd5Update(&md5Ctx, buf, SHA1_HASH_SIZE);
		psMd5Final(&md5Ctx, tmp);
		tmp += MD5_HASH_SIZE;
	}
	memset(buf, 0x0, MD5_HASH_SIZE + SHA1_HASH_SIZE);
/*
	premaster is now allocated for DH reasons.  Can free here
*/
	psFree(ssl->sec.premaster);
	ssl->sec.premaster = NULL;
	ssl->sec.premasterSize = 0;

skipPremaster:
	if (createKeyBlock(ssl, ssl->sec.clientRandom, ssl->sec.serverRandom, 
			ssl->sec.masterSecret, SSL_HS_MASTER_SIZE) < 0) {
		psTraceInfo("Unable to create key block\n");
		return PS_FAILURE;
	}
	
	return SSL_HS_MASTER_SIZE;
}
Exemple #3
0
int32 psHmacSha1(unsigned char *key, uint32 keyLen, const unsigned char *buf,
				uint32 len, unsigned char *hash, unsigned char *hmacKey,
				uint32 *hmacKeyLen)
{
	psHmacContext_t		ctx;
	psDigestContext_t	sha;
/*
	Support for keys larger than 64 bytes.  In this case, we take the
	hash of the key itself and use that instead.  Inform the caller by
	updating the hmacKey and hmacKeyLen outputs
*/
	if (keyLen > 64) {
		psSha1Init(&sha);
		psSha1Update(&sha, key, keyLen);
		*hmacKeyLen = psSha1Final(&sha, hash);
		memcpy(hmacKey, hash, *hmacKeyLen);
	} else {
		hmacKey = key;
		*hmacKeyLen = keyLen;
	}

	psHmacSha1Init(&ctx, hmacKey, *hmacKeyLen);
	psHmacSha1Update(&ctx, buf, len);
	return psHmacSha1Final(&ctx, hash);
}
Exemple #4
0
int32_t psHmacSha1(const unsigned char *key, uint16_t keyLen,
                   const unsigned char *buf, uint32_t len,
                   unsigned char hash[SHA1_HASHLEN], unsigned char *hmacKey,
                   uint16_t *hmacKeyLen)
{
    psSha1_t	sha;
    /*
    	Support for keys larger than 64 bytes.  In this case, we take the
    	hash of the key itself and use that instead.  Inform the caller by
    	updating the hmacKey and hmacKeyLen outputs
    */
    if (keyLen > 64) {
        psSha1Init(&sha);
        psSha1Update(&sha, key, keyLen);
        psSha1Final(&sha, hash);
        *hmacKeyLen = SHA1_HASHLEN;
        memcpy(hmacKey, hash, *hmacKeyLen);
    } else {
        hmacKey = (unsigned char*)key;
        *hmacKeyLen = keyLen;
    }
    if (HMAC(EVP_sha1(), hmacKey, *hmacKeyLen, buf, len, hash, NULL) != NULL) {
        return PS_SUCCESS;
    }
    return PS_FAIL;
}
Exemple #5
0
int32_t psHmacSha1Init(psHmacSha1_t *ctx,
				const unsigned char *key, uint16_t keyLen)
{
	int32_t		rc, i;
#ifdef CRYPTO_ASSERT
	psAssert(keyLen <= 64);
#endif
	for (i = 0; (uint32)i < keyLen; i++) {
		ctx->pad[i] = key[i] ^ 0x36;
	}
	for (i = keyLen; (uint32)i < 64; i++) {
		ctx->pad[i] = 0x36;
	}
	if ((rc = psSha1Init(&ctx->sha1)) < 0) {
		return rc;
	}
	psSha1Update(&ctx->sha1, ctx->pad, 64);
	for (i = 0; (uint32)i < keyLen; i++) {
		ctx->pad[i] = key[i] ^ 0x5c;
	}
	for (i = keyLen; i < 64; i++) {
		ctx->pad[i] = 0x5c;
	}
	return PS_SUCCESS;
}
Exemple #6
0
void psHmacSha1Update(psHmacContext_t *ctx, const unsigned char *buf,
						uint32 len)
{
	psAssert(ctx != NULL && buf != NULL);

	psSha1Update(&ctx->u.sha1, buf, len);
}
Exemple #7
0
void psHmacSha1Update(psHmacSha1_t *ctx,
				const unsigned char *buf, uint32_t len)
{
#ifdef CRYPTO_ASSERT
	psAssert(ctx != NULL && buf != NULL);
#endif
	psSha1Update(&ctx->sha1, buf, len);
}
Exemple #8
0
int32 psHmacSha1Final(psHmacContext_t *ctx, unsigned char *hash)
{
	psAssert(ctx != NULL);
	if (hash == NULL) {
		psTraceCrypto("NULL hash storage passed to psHmacSha1Final\n");
		return PS_ARG_FAIL;
	}
	psSha1Final(&ctx->u.sha1, hash);

	psSha1Init(&ctx->u.sha1);
	psSha1Update(&ctx->u.sha1, ctx->pad, 64);
	psSha1Update(&ctx->u.sha1, hash, SHA1_HASH_SIZE);
	psSha1Final(&ctx->u.sha1, hash);

	memset(ctx->pad, 0x0, 64);
	return SHA1_HASH_SIZE;
}
Exemple #9
0
/**
    Update MD5 and SHA1 hashes of the same data.
 */
void psMd5Sha1Update(psMd5Sha1_t *md, const unsigned char *buf,
    uint32_t len)
{
# ifdef CRYPTO_ASSERT
    psAssert(md && buf);
# endif
    psMd5Update(&md->md5, buf, len);
    psSha1Update(&md->sha1, buf, len);
}
/**
  Add entropy to the PRNG state
  @param in       The data to add
  @param inlen    Length of the data to add
  @param prng     PRNG state to update
*/
int32 psYarrowAddEntropy(unsigned char *in, uint32 inlen, psYarrow_t *prng)
{
	psDigestContext_t md;
	int32 err;

	if (in == NULL || prng == NULL) {
		return PS_ARG_FAIL;
	}

#ifdef USE_SHA256
	/* start the hash */
	psSha256Init(&md);

	/* hash the current pool */
	psSha256Update(&md, prng->pool, SHA256_HASH_SIZE);

	/* add the new entropy */
	psSha256Update(&md, in, inlen);

	/* store result */
	if ((err = psSha256Final(&md, prng->pool)) != SHA256_HASH_SIZE) {
		return err;
	}
#else
	/* start the hash */
	psSha1Init(&md);

	/* hash the current pool */
	psSha1Update(&md, prng->pool, SHA1_HASH_SIZE);

	/* add the new entropy */
	psSha1Update(&md, in, inlen);

	/* store result */
	if ((err = psSha1Final(&md, prng->pool)) != SHA1_HASH_SIZE) {
		return err;
	}
#endif
	return PS_SUCCESS;
}
Exemple #11
0
void psHmacSha1Final(psHmacSha1_t *ctx, unsigned char hash[SHA1_HASHLEN])
{
	int32_t		rc;
#ifdef CRYPTO_ASSERT
	psAssert(ctx != NULL);
	if (hash == NULL) {
		psTraceCrypto("NULL hash storage passed to psHmacSha1Final\n");
		return;
	}
#endif
	psSha1Final(&ctx->sha1, hash);

	if ((rc = psSha1Init(&ctx->sha1)) < 0) {
		psAssert(rc >= 0);
		return;
	}
	psSha1Update(&ctx->sha1, ctx->pad, 64);
	psSha1Update(&ctx->sha1, hash, SHA1_HASHLEN);
	psSha1Final(&ctx->sha1, hash);

	memset(ctx->pad, 0x0, sizeof(ctx->pad));
}
Exemple #12
0
/*
	SSLv3 uses a method similar to HMAC to generate the SHA1 message MAC.
	For SHA1, 40 bytes of the pad are used.

	SHA1(MAC_write_secret + pad2 + 
		SHA1(MAC_write_secret + pad1 + seq_num + length + content));
*/
int32 ssl3HMACSha1(ssl_t *ssl, int32 mode, unsigned char *key, unsigned char *seq, 
						unsigned char type, unsigned char *data, uint32 len,
						unsigned char *mac)
{
	psDigestContext_t	sha1;
	unsigned char		ihash[SHA1_HASH_SIZE];
	int32				i;
	psDigestContext_t* psha = &sha1;
#ifdef USE_APP_DATA_PARTIAL_PARSING
	if(ssl->rec.type == SSL_RECORD_TYPE_APPLICATION_DATA && mode == HMAC_VERIFY && ssl->deBlockSize <= 1)
		psha = &ssl->hmac_ctx;
	if(ssl->rec.type != SSL_RECORD_TYPE_APPLICATION_DATA || mode == HMAC_CREATE || ssl->deBlockSize > 1 || (data == NULL && len > 0)){
#endif
	psSha1Init(psha);
	psSha1Update(psha, key, SHA1_HASH_SIZE);
	psSha1Update(psha, pad1, 40);
	psSha1Update(psha, seq, 8);
	ihash[0] = type;
	ihash[1] = (len & 0xFF00) >> 8;
	ihash[2] = len & 0xFF;
	psSha1Update(psha, ihash, 3);
#ifdef USE_APP_DATA_PARTIAL_PARSING
	}
Exemple #13
0
void psHmacSha1Init(psHmacContext_t *ctx, unsigned char *key, uint32 keyLen)
{
	int32	i;

	psAssert(keyLen <= 64);

	for (i = 0; (uint32)i < keyLen; i++) {
		ctx->pad[i] = key[i] ^ 0x36;
	}
	for (i = keyLen; (uint32)i < 64; i++) {
		ctx->pad[i] = 0x36;
	}
	psSha1Init(&ctx->u.sha1);
	psSha1Update(&ctx->u.sha1, ctx->pad, 64);
	for (i = 0; (uint32)i < keyLen; i++) {
		ctx->pad[i] = key[i] ^ 0x5c;
	}
	for (i = keyLen; i < 64; i++) {
		ctx->pad[i] = 0x5c;
	}
}
Exemple #14
0
/*
	Combine the running hash of the handshake mesages with some constants
	and mix them up a bit more.  Output the result to the given buffer.
	This data will be part of the Finished handshake message.
*/
int32 sslGenerateFinishedHash(psDigestContext_t *md5, psDigestContext_t *sha1, 
								unsigned char *masterSecret,
								unsigned char *out, int32 sender)
{
	psDigestContext_t	omd5,osha1;
	unsigned char		ihash[SHA1_HASH_SIZE];

/*
	md5Hash = MD5(master_secret + pad2 + 
		MD5(handshake_messages + sender + master_secret + pad1));
*/
	if (sender >= 0) {
		psMd5Update(md5,
			(sender & SSL_FLAGS_SERVER) ? SENDER_SERVER : SENDER_CLIENT, 4);
	}
	psMd5Update(md5, masterSecret, SSL_HS_MASTER_SIZE);
	psMd5Update(md5, pad1, sizeof(pad1));
	psMd5Final(md5, ihash);

	psMd5Init(&omd5);
	psMd5Update(&omd5, masterSecret, SSL_HS_MASTER_SIZE);
	psMd5Update(&omd5, pad2, sizeof(pad2));
	psMd5Update(&omd5, ihash, MD5_HASH_SIZE);
	psMd5Final(&omd5, out);
/*
	The SHA1 hash is generated in the same way, except only 40 bytes
	of pad1 and pad2 are used.
	sha1Hash = SHA1(master_secret + pad2 + 
		SHA1(handshake_messages + sender + master_secret + pad1));
*/
	if (sender >= 0) {
		psSha1Update(sha1, 
			(sender & SSL_FLAGS_SERVER) ? SENDER_SERVER : SENDER_CLIENT, 4);
	}
	psSha1Update(sha1, masterSecret, SSL_HS_MASTER_SIZE);
	psSha1Update(sha1, pad1, 40);
	psSha1Final(sha1, ihash);

	psSha1Init(&osha1);
	psSha1Update(&osha1, masterSecret, SSL_HS_MASTER_SIZE);
	psSha1Update(&osha1, pad2, 40);
	psSha1Update(&osha1, ihash, SHA1_HASH_SIZE);
	psSha1Final(&osha1, out + MD5_HASH_SIZE);

	return MD5_HASH_SIZE + SHA1_HASH_SIZE;
}
Exemple #15
0
int32_t psHmacSha1(const unsigned char *key, uint16_t keyLen,
				const unsigned char *buf, uint32_t len,
				unsigned char hash[SHA1_HASHLEN],
				unsigned char *hmacKey, uint16_t *hmacKeyLen)
{
	int32_t				rc;
	union {
		psHmacSha1_t	mac;
		psSha1_t		md;
	} u;
	psHmacSha1_t		*mac = &u.mac;
	psSha1_t			*md = &u.md;
/*
	Support for keys larger than 64 bytes.  In this case, we take the
	hash of the key itself and use that instead.  Inform the caller by
	updating the hmacKey and hmacKeyLen outputs
*/
	if (keyLen > 64) {
		if ((rc = psSha1Init(md)) < 0) {
			return rc;
		}
		psSha1Update(md, key, keyLen);
		psSha1Final(md, hash);
		*hmacKeyLen = SHA1_HASHLEN;
		memcpy(hmacKey, hash, *hmacKeyLen);
	} else {
		hmacKey = (unsigned char *)key; /* @note typecasting from const */
		*hmacKeyLen = keyLen;
	}

	if ((rc = psHmacSha1Init(mac, hmacKey, *hmacKeyLen)) < 0) {
		return rc;
	}
	psHmacSha1Update(mac, buf, len);
	psHmacSha1Final(mac, hash);
	return PS_SUCCESS;
}
Exemple #16
0
/*
    Parse DER encoded asn.1 RSA public key out of a certificate stream.
    We reach here with 'pp' pointing to the byte after the algorithm identifier.
 */
int32_t psRsaParseAsnPubKey(psPool_t *pool,
    const unsigned char **pp, psSize_t len,
    psRsaKey_t *key, unsigned char sha1KeyHash[SHA1_HASH_SIZE])
{
# ifdef USE_SHA1
    psDigestContext_t dc;
# endif
    const unsigned char *p = *pp;
    RSA *rsa;
    psSize_t keylen;
# ifndef USE_D2I
    psSize_t seqlen;
# endif

    if (len < 1 || (*(p++) != ASN_BIT_STRING) ||
        getAsnLength(&p, len - 1, &keylen))
    {
        goto L_FAIL;
    }
    /* ignored bits field should be zero */
    if (*p++ != 0)
    {
        goto L_FAIL;
    }
    keylen--;
# ifdef USE_SHA1
    /* A public key hash is used in PKI tools (OCSP, Trusted CA indication).
        Standard RSA form - SHA-1 hash of the value of the BIT STRING
        subjectPublicKey [excluding the tag, length, and number of unused
        bits] */
    psSha1Init(&dc.sha1);
    psSha1Update(&dc.sha1, p, keylen);
    psSha1Final(&dc.sha1, sha1KeyHash);
# endif

# ifdef USE_D2I
    /* OpenSSL expects to parse after the ignored bits field */
    if ((rsa = d2i_RSAPublicKey(NULL, &p, keylen)) == NULL)
    {
        goto L_FAIL;
    }
# else
    /* We can manually create the structures as OpenSSL would */
    rsa = RSA_new();
    if (getAsnSequence(&p, keylen, &seqlen) < 0 ||
        getBig(&p, seqlen, &rsa->n) < 0 ||
        getBig(&p, seqlen, &rsa->e) < 0)
    {

        RSA_free(rsa);
        goto L_FAIL;
    }
# endif
    /* RSA_print_fp(stdout, rsa, 0); */
    *pp = p;
    *key = rsa;
    return PS_SUCCESS;
L_FAIL:
    psTraceIntCrypto("psRsaParseAsnPubKey error on byte %d\n", p - *pp);
    return PS_PARSE_FAIL;
}
Exemple #17
0
void runDigestTime(psDigestContext_t *ctx, int32 chunk, int32 alg)
{
	psTime_t			start, end;
	unsigned char		*dataChunk;
	unsigned char		hashout[64];
	int32				bytesSent, bytesToSend, round;
#ifdef USE_HIGHRES_TIME
	int32				mod;
	int64				diffu;
#else
	int32				diffm;
#endif

	dataChunk = psMalloc(NULL, chunk);
	bytesToSend = (DATABYTES_AMOUNT / chunk) * chunk;
	bytesSent = 0;

	switch (alg) {
#ifdef USE_SHA1
	case SHA1_ALG:
		psGetTime(&start, NULL);
		while (bytesSent < bytesToSend) {
			psSha1Update(&ctx->sha1, dataChunk, chunk);
			bytesSent += chunk;
		}
		psSha1Final(&ctx->sha1, hashout);
		psGetTime(&end, NULL);
		break;
#endif
#ifdef USE_SHA256
	case SHA256_ALG:
		psGetTime(&start, NULL);
		while (bytesSent < bytesToSend) {
			psSha256Update(&ctx->sha256, dataChunk, chunk);
			bytesSent += chunk;
		}
		psSha256Final(&ctx->sha256, hashout);
		psGetTime(&end, NULL);
		break;
#endif
#ifdef USE_SHA384
	case SHA384_ALG:
		psGetTime(&start, NULL);
		while (bytesSent < bytesToSend) {
			psSha384Update(&ctx->sha384, dataChunk, chunk);
			bytesSent += chunk;
		}
		psSha384Final(&ctx->sha384, hashout);
		psGetTime(&end, NULL);
		break;
#endif
#ifdef USE_SHA512
	case SHA512_ALG:
		psGetTime(&start, NULL);
		while (bytesSent < bytesToSend) {
			psSha512Update(&ctx->sha512, dataChunk, chunk);
			bytesSent += chunk;
		}
		psSha512Final(&ctx->sha512, hashout);
		psGetTime(&end, NULL);
		break;
#endif
#ifdef USE_MD5
	case MD5_ALG:
		psGetTime(&start, NULL);
		while (bytesSent < bytesToSend) {
			psMd5Update(&ctx->md5, dataChunk, chunk);
			bytesSent += chunk;
		}
		psMd5Final(&ctx->md5, hashout);
		psGetTime(&end, NULL);
		break;
#endif
	default:
		printf("Skipping Digest Tests\n");
		return;
	}

#ifdef USE_HIGHRES_TIME
	diffu = psDiffUsecs(start, end);
	round = (bytesToSend / diffu);
	mod = (bytesToSend % diffu);
	printf("%d byte chunks in %lld usecs total for rate of %d.%d MB/sec\n",
		chunk, (unsigned long long)diffu, round, mod);
#else
	diffm = psDiffMsecs(start, end, NULL);
	round = (bytesToSend / diffm) / 1000;
	printf("%d byte chunks in %d msecs total for rate of %d MB/sec\n",
		chunk, diffm, round);
#endif

}
Exemple #18
0
/*
	Generate the key block as follows.  '+' indicates concatination.  
	key_block =
		MD5(master_secret + SHA(`A' + master_secret +
			ServerHello.random + ClientHello.random)) +
		MD5(master_secret + SHA(`BB' + master_secret +
			ServerHello.random + ClientHello.random)) +
		MD5(master_secret + SHA(`CCC' + master_secret +
			ServerHello.random + ClientHello.random)) + 
		[...];
*/
static int32 createKeyBlock(ssl_t *ssl, unsigned char *clientRandom,
						  unsigned char *serverRandom,
						  unsigned char *masterSecret, uint32 secretLen)
{
	psDigestContext_t	md5Ctx, sha1Ctx;
	unsigned char		buf[MD5_HASH_SIZE + SHA1_HASH_SIZE];
	unsigned char		*tmp;
	int32				ret = 0;
	uint32				i, keyIter, reqKeyLen;

/*
	We must generate enough key material to fill the various keys
*/
	reqKeyLen = 2 * ssl->cipher->macSize + 
				2 * ssl->cipher->keySize + 
				2 * ssl->cipher->ivSize;
/*
	Find the right number of iterations to make the requested length key block
*/
	keyIter = 1;
	while (MD5_HASH_SIZE * keyIter < reqKeyLen) {
		keyIter++;
	}
	if (keyIter > sizeof(salt)/sizeof(char*)) {
		psTraceIntInfo("Error: Not enough salt for key length %d\n", reqKeyLen);
		return PS_FAILURE;
	}

	tmp = ssl->sec.keyBlock;
	for (i = 0; i < keyIter; i++) {
		psSha1Init(&sha1Ctx);
		psSha1Update(&sha1Ctx, salt[i], i + 1);
		psSha1Update(&sha1Ctx, masterSecret, secretLen);
		psSha1Update(&sha1Ctx, serverRandom, SSL_HS_RANDOM_SIZE);
		psSha1Update(&sha1Ctx, clientRandom, SSL_HS_RANDOM_SIZE);
		psSha1Final(&sha1Ctx, buf);
		
		psMd5Init(&md5Ctx);
		psMd5Update(&md5Ctx, masterSecret, secretLen);
		psMd5Update(&md5Ctx, buf, SHA1_HASH_SIZE);
		psMd5Final(&md5Ctx, tmp);
		tmp += MD5_HASH_SIZE;
		ret += MD5_HASH_SIZE;
	}
	memset(buf, 0x0, MD5_HASH_SIZE + SHA1_HASH_SIZE);
/*
	Client and server use different read/write values, with the Client 
	write value being the server read value.
*/
	if (ssl->flags & SSL_FLAGS_SERVER) {
		ssl->sec.rMACptr = ssl->sec.keyBlock;
		ssl->sec.wMACptr = ssl->sec.rMACptr + ssl->cipher->macSize;
		ssl->sec.rKeyptr = ssl->sec.wMACptr + ssl->cipher->macSize;
		ssl->sec.wKeyptr = ssl->sec.rKeyptr + ssl->cipher->keySize;
		ssl->sec.rIVptr = ssl->sec.wKeyptr + ssl->cipher->keySize;
		ssl->sec.wIVptr = ssl->sec.rIVptr + ssl->cipher->ivSize;
	} else {
		ssl->sec.wMACptr = ssl->sec.keyBlock;
		ssl->sec.rMACptr = ssl->sec.wMACptr + ssl->cipher->macSize;
		ssl->sec.wKeyptr = ssl->sec.rMACptr + ssl->cipher->macSize;
		ssl->sec.rKeyptr = ssl->sec.wKeyptr + ssl->cipher->keySize;
		ssl->sec.wIVptr = ssl->sec.rKeyptr + ssl->cipher->keySize;
		ssl->sec.rIVptr = ssl->sec.wIVptr + ssl->cipher->ivSize;
	}

	return ret;
}