Ejemplo n.º 1
0
int32_t psHmacMd5(const unsigned char *key, uint16_t keyLen,
                  const unsigned char *buf, uint32_t len,
                  unsigned char hash[MD5_HASHLEN], unsigned char *hmacKey,
                  uint16_t *hmacKeyLen)
{
    psMd5_t	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) {
        psMd5Init(&md);
        psMd5Update(&md, key, keyLen);
        psMd5Final(&md, hash);
        *hmacKeyLen = MD5_HASHLEN;
        memcpy(hmacKey, hash, *hmacKeyLen);
    } else {
        hmacKey = (unsigned char*)key;
        *hmacKeyLen = keyLen;
    }
    if (HMAC(EVP_md5(), hmacKey, *hmacKeyLen, buf, len, hash, NULL) != NULL) {
        return PS_SUCCESS;
    }
    return PS_FAIL;
}
Ejemplo n.º 2
0
/*
	HMAC-MD5
	http://www.faqs.org/rfcs/rfc2104.html

	the HMAC_MD5 transform looks like:

		MD5(K XOR opad, MD5(K XOR ipad, text))
       
		where K is an n byte key
		ipad is the byte 0x36 repeated 64 times

		opad is the byte 0x5c repeated 64 times
		and text is the data being protected

	If the keyLen is > 64 bytes, we hash the key and use it instead
*/
int32 psHmacMd5(unsigned char *key, uint32 keyLen, 
				const unsigned char *buf, uint32 len, unsigned char *hash,
				unsigned char *hmacKey, uint32 *hmacKeyLen)
{
	psHmacContext_t		ctx;
	psDigestContext_t	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) {
		psMd5Init(&md);
		psMd5Update(&md, key, keyLen);
		*hmacKeyLen = psMd5Final(&md, hash);
		memcpy(hmacKey, hash, *hmacKeyLen);
	} else {
		hmacKey = key;
		*hmacKeyLen = keyLen;
	}

	psHmacMd5Init(&ctx, hmacKey, *hmacKeyLen);
	psHmacMd5Update(&ctx, buf, len);
	return psHmacMd5Final(&ctx, hash);
}
Ejemplo n.º 3
0
/**
    Finalize output of the combined MD5-SHA1
    The output is 36 bytes, first the 16 bytes MD5 then the 20 bytes SHA1
 */
void psMd5Sha1Final(psMd5Sha1_t *md, unsigned char hash[MD5SHA1_HASHLEN])
{
# ifdef CRYPTO_ASSERT
    psAssert(md && hash);
# endif
    psMd5Final(&md->md5, hash);
    psSha1Final(&md->sha1, hash + MD5_HASHLEN);
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
int32 psHmacMd5Final(psHmacContext_t *ctx, unsigned char *hash)
{
	psAssert(ctx != NULL);
	if (hash == NULL) {
		psTraceCrypto("NULL hash storage passed to psHmacMd5Final\n");
		return PS_ARG_FAIL;
	}
	psMd5Final(&ctx->u.md5, hash);

	psMd5Init(&ctx->u.md5);
	psMd5Update(&ctx->u.md5, ctx->pad, 64);
	psMd5Update(&ctx->u.md5, hash, MD5_HASH_SIZE);
	psMd5Final(&ctx->u.md5, hash);

	memset(ctx->pad, 0x0, 64);
	return MD5_HASH_SIZE;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
Archivo: hmac.c Proyecto: Deadolus/ecc
void psHmacMd5Final(psHmacMd5_t *ctx, unsigned char hash[MD5_HASHLEN])
{
	int32_t		rc;
#ifdef CRYPTO_ASSERT
	psAssert(ctx != NULL);
	if (hash == NULL) {
		psTraceCrypto("NULL hash storage passed to psHmacMd5Final\n");
		return;
	}
#endif
	psMd5Final(&ctx->md5, hash);

	/* This Init should succeed, even if it allocates memory since an 
		psMd5_t was just Finalized the line above */
	if ((rc = psMd5Init(&ctx->md5)) < 0) {
		psAssert(rc >= 0);
		return;
	}
	psMd5Update(&ctx->md5, ctx->pad, 64);
	psMd5Update(&ctx->md5, hash, MD5_HASHLEN);
	psMd5Final(&ctx->md5, hash);

	memset(ctx->pad, 0x0, sizeof(ctx->pad));
}
Ejemplo n.º 8
0
Archivo: tls.c Proyecto: B-Rich/NUL
/*
	TLS handshake has computation
*/
int32 tlsGenerateFinishedHash(ssl_t *ssl, psDigestContext_t *md5,
				psDigestContext_t *sha1, psDigestContext_t *sha256,
				unsigned char *masterSecret, unsigned char *out, int32 sender)
{
	unsigned char	tmp[FINISHED_LABEL_SIZE + MD5_HASH_SIZE + SHA1_HASH_SIZE];

	if (sender >= 0) {
		memcpy(tmp, (sender & SSL_FLAGS_SERVER) ? LABEL_SERVER : LABEL_CLIENT, 
			FINISHED_LABEL_SIZE);
		psMd5Final(md5, tmp + FINISHED_LABEL_SIZE);
		psSha1Final(sha1, tmp + FINISHED_LABEL_SIZE + MD5_HASH_SIZE);
		return prf(masterSecret, SSL_HS_MASTER_SIZE, tmp, sizeof(tmp), 
			out, TLS_HS_FINISHED_SIZE);
	} else {
/*
		The handshake snapshot for client authentication is simply the
		appended MD5 and SHA1 hashes
*/
		psMd5Final(md5, out);
		psSha1Final(sha1, out + MD5_HASH_SIZE);
		return MD5_HASH_SIZE + SHA1_HASH_SIZE;
	}
	return PS_FAILURE; /* Should not reach this */
}
Ejemplo n.º 9
0
/**
	Maintain MD5 and SHA1 hashes of the same data.
	@note This could be done more optimally, give the use of this in TLS.
		Some state is shared between the two contexts, and some paralellism
		could be used in calculation.
*/
int32_t psMd5Sha1Init(psMd5Sha1_t *md)
{
	int32_t		rc;
#ifdef CRYPTO_ASSERT
	psAssert(md);
#endif
	if ((rc = psMd5Init(&md->md5)) < 0) {
		return rc;
	}
	if ((rc = psSha1Init(&md->sha1)) < 0) {
		/* We call Final to clear the state, ignoring the output */
		psMd5Final(&md->md5, NULL);
		return rc;
	}
	return PS_SUCCESS;
}
Ejemplo n.º 10
0
char *websMD5binary(unsigned char *buf, int length)
{
    const char		*hex = "0123456789abcdef";
    psDigestContext_t	md5ctx;
    unsigned char	hash[HASH_SIZE];
    char			*r, *strReturn;
	char			result[(HASH_SIZE * 2) + 1];
    int				i;

/*
 *	Take the MD5 hash of the string argument.
 */
	psMd5Init(&md5ctx);
	psMd5Update(&md5ctx, buf, (unsigned int)length);
	psMd5Final(&md5ctx, hash);

/*
 *	Prepare the resulting hash string
 */
    for (i = 0, r = result; i < 16; i++) {
		*r++ = hex[hash[i] >> 4];
		*r++ = hex[hash[i] & 0xF];
    }

/*
 *	Zero terminate the hash string
 */
    *r = '\0';

/*
 *	Allocate a new copy of the hash string
 */
	i = elementsof(result);
	strReturn = balloc(B_L, i);
	strncpy(strReturn, result, i);

    return strReturn;
}
Ejemplo n.º 11
0
Archivo: hmac.c Proyecto: Deadolus/ecc
int32_t psHmacMd5(const unsigned char *key, uint16_t keyLen,
				const unsigned char *buf, uint32_t len,
				unsigned char hash[MD5_HASHLEN],
				unsigned char *hmacKey, uint16_t *hmacKeyLen)
{
	int32_t				rc;
	union {
		psHmacMd5_t		mac;
		psMd5_t			md;
	} u;
	psHmacMd5_t			*mac = &u.mac;
	psMd5_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 = psMd5Init(md)) < 0) {
			return rc;
		}
		psMd5Update(md, key, keyLen);
		psMd5Final(md, hash);
		*hmacKeyLen = MD5_HASHLEN;
		memcpy(hmacKey, hash, *hmacKeyLen);
	} else {
		hmacKey = (unsigned char *)key; /* @note typecasting from const */
		*hmacKeyLen = keyLen;
	}
	if ((rc = psHmacMd5Init(mac, hmacKey, *hmacKeyLen)) < 0) {
		return rc;
	}
	psHmacMd5Update(mac, buf, len);
	psHmacMd5Final(mac, hash);
	return PS_SUCCESS;
}
Ejemplo n.º 12
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;
}
Ejemplo n.º 13
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

}
/*
	TLS handshake hash computation
*/
static int32 tlsGenerateFinishedHash(ssl_t *ssl, psDigestContext_t *md5,
				psDigestContext_t *sha1, psDigestContext_t *sha256,
				psDigestContext_t *sha384, unsigned char *masterSecret,
				unsigned char *out, int32 sender)
{
	unsigned char	tmp[FINISHED_LABEL_SIZE + SHA384_HASH_SIZE];
	int32			tlsTmpSize;

	if (sender >= 0) {
		memcpy(tmp, (sender & SSL_FLAGS_SERVER) ? LABEL_SERVER : LABEL_CLIENT,
			FINISHED_LABEL_SIZE);
		tlsTmpSize = FINISHED_LABEL_SIZE + SHA1_HASH_SIZE + MD5_HASH_SIZE;
#ifdef USE_TLS_1_2
		if (ssl->flags & SSL_FLAGS_TLS_1_2) {
			if (ssl->cipher->flags & CRYPTO_FLAGS_SHA3) {
#ifdef USE_SHA384
				psSha384Final(sha384, tmp + FINISHED_LABEL_SIZE);
				return prf2(masterSecret, SSL_HS_MASTER_SIZE, tmp,
					FINISHED_LABEL_SIZE + SHA384_HASH_SIZE, out,
					TLS_HS_FINISHED_SIZE, CRYPTO_FLAGS_SHA3);
#endif
			} else {
				psSha256Final(sha256, tmp + FINISHED_LABEL_SIZE);
				return prf2(masterSecret, SSL_HS_MASTER_SIZE, tmp,
					FINISHED_LABEL_SIZE + SHA256_HASH_SIZE, out,
					TLS_HS_FINISHED_SIZE, CRYPTO_FLAGS_SHA2);
			}
#ifndef USE_ONLY_TLS_1_2
		} else {
			psMd5Final(md5, tmp + FINISHED_LABEL_SIZE);
			psSha1Final(sha1, tmp + FINISHED_LABEL_SIZE + MD5_HASH_SIZE);
			return prf(masterSecret, SSL_HS_MASTER_SIZE, tmp, tlsTmpSize,
				out, TLS_HS_FINISHED_SIZE);
#endif
		}
#else
		psMd5Final(md5, tmp + FINISHED_LABEL_SIZE);
		psSha1Final(sha1, tmp + FINISHED_LABEL_SIZE + MD5_HASH_SIZE);
		return prf(masterSecret, SSL_HS_MASTER_SIZE, tmp, tlsTmpSize,
			out, TLS_HS_FINISHED_SIZE);
#endif
	} else {
		/* Overloading this function to handle the client auth needs of
			handshake hashing. */
#ifdef USE_TLS_1_2
		if (ssl->flags & SSL_FLAGS_TLS_1_2) {
			psSha256Final(sha256, out);
#if defined(USE_SERVER_SIDE_SSL) && defined(USE_CLIENT_AUTH)
#ifdef USE_SHA384
			psSha384Final(sha384, ssl->sec.sha384Snapshot);
#endif
#ifndef USE_ONLY_TLS_1_2
			psSha1Final(sha1, ssl->sec.sha1Snapshot);
#endif
#endif
			return SHA256_HASH_SIZE;
#ifndef USE_ONLY_TLS_1_2
		} else {
			psMd5Final(md5, out);
			psSha1Final(sha1, out + MD5_HASH_SIZE);
			return MD5_HASH_SIZE + SHA1_HASH_SIZE;
#endif
		}
#else
/*
		The handshake snapshot for client authentication is simply the
		appended MD5 and SHA1 hashes
*/
		psMd5Final(md5, out);
		psSha1Final(sha1, out + MD5_HASH_SIZE);
		return MD5_HASH_SIZE + SHA1_HASH_SIZE;
#endif
	}
	return PS_FAILURE; /* Should not reach this */
}