#include <stdio.h>
#include <syslog.h>
#include <stdint.h>
#include <string.h>
#include <openssl/md5.h>

#define MAX_KEY_SIZE 9

uint8_t calculate_key_at_ith_index(uint32_t *bmac, int pos, int octets)
{
	int i = 0;
	int sum = 0;

	while (i < octets)
	{
		sum = sum + bmac[pos - i];
		i++;
	}

	return (sum % 16); /* We are limiting the sum between 0 and 255 */
}

int get_key(const char *macstr, char *key)
{
	int i;
	uint32_t bmac[6] = {0};
	uint8_t bkey[MAX_KEY_SIZE] = {0};
	uint8_t pos_array[8] = {5, 3, 1, 5, 2, 5, 5, 5};
	uint8_t no_of_octets[8] = {2, 2, 2, 3, 3, 4, 5, 6};

	sscanf(macstr, "%02x:%02x:%02x:%02x:%02x:%02x", &bmac[0], &bmac[1], &bmac[2], &bmac[3], &bmac[4], &bmac[5]);

	for (i = 0; i < MAX_KEY_SIZE; i++)
	{
		bkey[i] = calculate_key_at_ith_index(bmac, pos_array[i], no_of_octets[i]);
	}


	snprintf(key, MAX_KEY_SIZE, "%x%x%x%x%x%x%x%x", bkey[0], bkey[1], bkey[2], bkey[3], bkey[4], bkey[5], bkey[6], bkey[7]);

	return 0;
}

int valiadate_mac(char *mac)
{
	int i, len = strlen(mac);

	if (len != 17)
		return -1;

	for (i = 0; i < len; i++)
	{
		if (mac[i] >= 'A' && mac[i] <= 'F')
			mac[i] = mac[i] - 'A' + 'a';

		else if (mac[i] >= 'a' && mac[i] <= 'f')
			continue;

		else if (mac[i] >= '0' && mac[i] <= '9')
			continue;

		else if (mac[i] == ':')
			continue;

		else 
			return -1;
	}

	return 0;
}

int main(int argc, char *argv[])
{
	char *mac = argv[1];
	char key[MAX_KEY_SIZE] = {0};

	if (argc != 2)
	{
		printf("ERROR : Usage : <pwpakey_generator> <00:11:ff:dc:21:aa>\n");
		return -1;
	}

	/* Take care of the case sensitive input mac string */
	if (valiadate_mac(mac) == -1)
	{
		printf("ERROR : Usage : please give a valid mac address : <pwpakey_generator> <00:11:ff:dc:21:aa>\n");
		return -1;
	}

	get_key(mac, key);

	unsigned char final_key[MD5_DIGEST_LENGTH];
	MD5_CTX md_context;


	MD5_Init(&md_context);
	MD5_Update(&md_context, key, MAX_KEY_SIZE);
	MD5_Final(final_key, &md_context);

	snprintf(key, MAX_KEY_SIZE, "%02x%02x%02x%02x", final_key[0], final_key[1], final_key[2], final_key[3]);
	printf("%s\n", key);
	return 0;
}
