Hi,

I am a newbie in the cryptography area and learning by writing some test code.
I have setup the apache server and capturing packets using wireshark.
I have a query specific to RC4. With the given server private key, I am able to generate master secret and key block correctly. My test code output matches with Wireshark debug logs (i.e. the master secret generated and key block generated using pseudo-random function).

However, I am unable to understand how to use the RC4_set_key() and RC4() APIs.
What exact part of key_block should I feed to RC4_set_key()?
key_block[0..15] - client MAC
key_block[16..31] - server MAC
key_block[32..48] - client Write key
key_block[49..64] - server Write key

Please see the test code attached (please pardon the code formatting).

--
Thanks,
Nilesh
#include <openssl/rsa.h>
#include <openssl/rc4.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/err.h>
#include <string.h>

void sec_hash_48(unsigned char * out, unsigned char * in, unsigned char * salt1,
		unsigned char * salt2, unsigned char salt);
void sec_hash_64(unsigned char * out, unsigned char * in, unsigned char * salt1,
		unsigned char * salt2, unsigned char salt);
void printmem(char *str, unsigned char *mem, unsigned int len, unsigned char hex);

/* Data extracted from packet. */
unsigned char client_random[] = "\x4e\x95\x38\xa1\x20\x7a\x9e\x47\x4e\xaa\x0c\xfd\xa3\x06\xf9\xa7\x0c\x09\xc7\xc5\x6e\x50\x7d\xbf\xb0\x7d\x4e\x1b\xb4\xbd\xcd\x59";
unsigned char server_random[] = "\x4e\x95\x38\xa0\x05\xf0\x06\x5f\x6d\x06\x2d\xfa\x15\x31\x5e\xa7\xe0\x0e\xc9\x26\x28\x82\x4b\xc8\x66\x87\xff\xbd\x10\x60\x2b\x18";
unsigned char iv[] = "\xe2\x95\x6b\x86\x77\x7e\xed\xfe\xe0\x3c\x09\xab\x99\xea\xcc\x69";
unsigned char to_decrypt_key[] = "\x3b\xdb\x06\x4c\x0d\xd5\x42\xc4\x2e\xb4\xbc\xb9\x2e\x45\x30\xa9\x00\xf8\x4d\xd1\x7b\x0c\x73\x80\xcd\xff\xd1\x7e\x40\x30\x99\x2b\xc0\x8c\xcb\x42\x6c\xe8\x43\x0f\x6c\x0b\xd1\xa5\xdd\x44\x3f\xaa\x2b\x33\xc7\x54\x33\x5e\x14\x1a\x29\x9d\x98\xdb\x08\x6a\x16\xeb\xfe\x7d\xef\x04\x7d\x65\x5a\xf3\xf3\x65\xf4\x75\x77\x3c\xa2\x23\xd4\xdc\x23\xf4\x11\x1f\xb4\x83\x94\x75\xf7\x81\x4f\x14\x59\x1b\xc8\x0d\x27\x9a\x3e\x1b\x03\xf3\x5f\x92\xe3\xd8\x47\x54\xc8\xf5\x68\x2f\xbb\xdf\xe3\xdd\xaa\xf9\x7f\xc9\x8d\x45\x8c\xc0\xc2\x56";

unsigned char inbuf[4096] = "\x0f\xc6\xcd\x17\xa8\x0b\xaa\xa2\x9c\xed\xe9\x7f\xba\x10\xcb\x23\xd0\x0b\x23\xba\x4b\x8b\x9b\xfc\x96\xab\x9e\x14\x46\x94\xaa\xfa\xbb\x81\xc5\x91\x17\x7c\xba\xd7\x27\x17\x31\xd1\xfe\xd2\x8b\x00\xa1\x46\x19\xe6\xdd\x94\xd0\x71\xab\x03\xcf\xe7\xbe\xb8\x37\xd9\xe0\xcb\x46\x23\x08\xe7\x7b\xc0\xae\xc2\x5d\x3e\x93\x07\xc7\x75\x31\x34\x41\x4e\x6e\x90\x42\xf7\x47\xc5\x53\x07\x2a\x98\x71\x0d\x8b\x50\x03\xd0\xa1\x7a\x12\xbe\x71\x35\x30\x19\x1e\xf1\x1a\x5e\xf4\x96\x1d\x25\x3a\x9d\x35\xb6\x79\x0e\xbd\xb7\xc8\x11\xae\x81\x86\x75\x7a\x36\x29\x22\x27\x78\x92\xe7\x8a\x52\x81\x57\x01\x62\x39\x9d\x66\xb2\xf5\xe5\x4f\x2c\x05\x4e\x71\x30\x77\xf4\x1e\xcf\x30\xe0\x78\x4a\x1c\x53\x1e\xd2\x1f\x37\x91\x4e\x6f\xe6\xc1\x68\x02\x01\x01\x4d\x24\xf0\xe9\xa2\x6e\x63\x2c\xc1\xfa\x47\xc2\x00\x01\x07\x0b\xed\xcf\x1a\x1e\x45\x5d\x71\xbd\x1d\xe5\x4b\xf3\xbb\x56\xb4\x19\x68\x09\xdc\x9c\x96\xbe\x1e\x0f\xf1\x87\x39\x9e\x5a\x1b\x42\x94\x00\x04\xc0\x6f\x94\xaf\x72\x25\xaa\xf5\xf3\x31\x2e\x24\x61\xb4\xa0\xb1\x09\xfe\x2e\xaf\x80\xa7\x11\x20\x60\x9d\x7d\x35\x4d\xf6\xb4\x2b\x21\xa7\x9f\xa8\x73\x13\x86\x5f\x95\x27\x17\x9d\x3b\xe2\xdc\x92\x98\xbc\xea\x8f\xff\xb1\xa7\x15\x9f\x5e\x66\x96\xe2\x0d\x6e\x39\x32\x59\x88\x58\xcd\x79\x37\xaa\xe0\x97\xff\x71\x78\x44\x43\x2f\x43\x4e\xd3\xb8\xde\x7c\xbc\xac\x8e\x8d\xa7\xcc\xee\x27\xe8\x05\x8c\xe1\x82\xc8\x2c\x7f\x58\x1b\xb3\x40\x5a\x7d\x68\x10\x19\x52\x39\xf7\x37\x8c\xe0\xa3\x9b\x61\x19\x04\xc8\x4d\x4e\x6b\x27\xad\xc4\x3a\xe1\x19\xb3\x94\x6d\xe2\x84\x18\x51\xcc\x1a\xea\x91\xfd\xba\x00\x1e\x2a\x7d\x95\x3f\x2b\x9b\xfe\xf9\x93\x1a\x2f\x2a\x9d\x26\xcd\x42\x1d\x95\x21\xa6\x0c\x45\xbf";


/* This matches with wireshark debug logs.
 Premaster: 3 0 80 4a 1c 2b 72 4a 88 19 c1 5c 6b 55 1c 63 46 1 16 b9 94 3b 7c 6b 12 80 a a4 24 d6 b1 ac 3d 71 87 12 b9 7 1 47 a4 3c c3 8b 31 54 c3 f4
 
 Master secret: 9f e3 1 2c 47 8b 56 bf 78 1a f7 9f a6 1c b0 40 ff f5 68 5b 67 31 90 83 a9 a0 e e4 72 64 ee 6a 1d 5a e1 19 61 a8 96 21 3e da 5e dc c9 ef 36 fc 

 key block: 1 ec 86 47 58 3b 4b 62 60 90 fd 43 84 aa 55 f2 85 41 fc 87 6f c7 61 38 c fd a6 48 ef 9e 14 98 e7 88 10 68 38 54 4 9a 22 1c 23 8c 87 82 bd 7a 4b b9 1a 35 26 ac 93 bb 48 96 84 9e eb d1 43 da
 */
#define DEBUG
#ifdef DEBUG
#define PRINT(str, mem, len, hex) printmem(str, mem, len, hex);
#else
#define PRINT(str, mem, len, hex) 0
#endif

int main(void)
{
	// For reading the key.
	RSA *rsa;
	FILE *fp;
	int i, check, pre_master_len = 128;
	// The decrypted premaster secret.
	unsigned char pre_master[48]; 
	// The decrypted master secret.
	unsigned char master_secret[48];
	// Key block generated.
	unsigned char key_block[144];
	// The decrypted data buff.
	unsigned char outbuf[4096];

	unsigned int  rid = 0;
	unsigned char err_buf[1024];
	Uint64  context_handle;
	int rc;
	RC4_KEY sch;

	SSL3_RECORD *rec = (SSL3_RECORD *) malloc (sizeof(SSL3_RECORD));
	if (!rec) {
		printf("Malloc failure.\n");
		return -1;
	}

	printf("Cavium initialization....\n");
	if (CspInitialize(CAVIUM_DIRECT, CAVIUM_DEV_ID)) {
		printf("Error! Cavium init failed!!\n");
		return -1;
	}
	if (CspAllocContext(CONTEXT_SSL, &context_handle, CAVIUM_DEV_ID)) {
		printf("Error! Context alloc failed!!\n");
		return -1;
	}
	rsa = RSA_new();
	/* 1 Open server's private key file */
	if ((fp = fopen("server.key", "rb")) == NULL) {
		printf("Cannot open server key file.\n");
		return;
	}

	/* 2 Generate RSA struct from private key file */
	PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL);

	/* 3 Check for successful key generation */
	if (RSA_check_key(rsa) != 1) {
		printf("RSA_check_key(): PrivateKey check failed\n");
		return;
	}

	/* 4 Using Private RSA Key, decode the client_pre_master_secret */
	check = RSA_private_decrypt(pre_master_len, to_decrypt_key,
			pre_master, rsa, RSA_PKCS1_PADDING);
	if (check == -1) {
		printf("RSA_private_decrypt() failed : %d\n", check);
		printf("Decrypt failed: %s\n",
				ERR_error_string(ERR_get_error(), err_buf));
		exit(1);
	}
	PRINT("\nPremaster: ",pre_master,check,1);

	/* 5 Generate master secret */
	sec_hash_48(master_secret, pre_master, client_random, server_random, 'A');
	PRINT("\nMaster secret: ",master_secret,48,1);

	/* 6 Generate key block. For RC4 it will be 64bytes.*/
	sec_hash_64(key_block, master_secret, server_random, client_random, 'A'); 
	PRINT("\nkey block: ",key_block, 64,1);
	RC4_set_key(&sch, 16, &key_block[48]);
	memset(&outbuf[0], 0, sizeof(outbuf));
	RC4(&sch, 399, inbuf, outbuf);

	printf("\nData : %s", outbuf);	
	PRINT("\nHttp : \n",outbuf,4096,1);
	printf("\n");

	return 0;
}

/* 48-byte transformation used to generate master secret and key material. Both SHA1 and MD5 algorithms are used. */
void sec_hash_48(unsigned char * out, unsigned char * in, unsigned char * salt1, unsigned char * salt2, unsigned char salt)
{
	unsigned char shasig[20];
	unsigned char pad[4];
	SHA_CTX sha;
	MD5_CTX md5;
	int i;

	for (i = 0; i < 3; i++)
	{
		memset(pad, salt + i, i + 1);

		SHA1_Init(&sha);
		SHA1_Update(&sha, pad, i + 1);
		SHA1_Update(&sha, in, 48);
		SHA1_Update(&sha, salt1, 32);
		SHA1_Update(&sha, salt2, 32);
		SHA1_Final(shasig, &sha);

		MD5_Init(&md5);
		MD5_Update(&md5, in, 48);
		MD5_Update(&md5, shasig, 20);
		MD5_Final(&out[i * 16], &md5);
	}
}

void sec_hash_64(unsigned char * out, unsigned char * in, unsigned char * salt1, unsigned char * salt2, unsigned char salt)
{
	unsigned char shasig[20];
	unsigned char pad[10];
	SHA_CTX sha;
	MD5_CTX md5;
	int i;

	for (i = 0; i < 4; i++)
	{
		memset(pad, salt + i, i + 1);

		SHA1_Init(&sha);
		SHA1_Update(&sha, pad, i + 1);
		SHA1_Update(&sha, in, 48);
		SHA1_Update(&sha, salt1, 32);
		SHA1_Update(&sha, salt2, 32);
		SHA1_Final(shasig, &sha);

		MD5_Init(&md5);
		MD5_Update(&md5, in, 48);
		MD5_Update(&md5, shasig, 20);
		MD5_Final(&out[i * 16], &md5);
	}
}

void printmem(char *str, unsigned char *mem, unsigned int len, unsigned char hex)
{
	int i=0;
	printf("\n%s",str);
	if(hex)
		while(i<len)
			printf("%x ", mem[i++]);
	else
		while(i<len)
			printf("%c",mem[i++]);
	return;
}

Reply via email to