#include <stdio.h>
#include <stdint.h>
#include <stdio.h>
#include "md5.h"
#include <string.h>

/*
preHandleIndex:
    0: |
    1: &
    2: ^
    3: !^
    4: +
    5: -
*/
int8_t preHandle(uint32_t *preGUIDptr, uint32_t key, uint8_t preHandleIndex)
{
	uint8_t i;
    switch(preHandleIndex)
    {
    case 0: // |
        for(i=0;i<3;i++)
        {
            preGUIDptr[i] |= key;
        }
        break;
    case 1: // &
        for(i=0;i<3;i++)
        {
            preGUIDptr[i] &= key;
        }
        break;
    case 2: // ^
        for(i=0;i<3;i++)
        {
            preGUIDptr[i] ^= key;
        }
        break;
    case 3: // !^
        for(i=0;i<3;i++)
        {
            preGUIDptr[i] ^= key;
            preGUIDptr[i] = ~preGUIDptr[i];
        }
        break;
    case 4: // +
        for(i=0;i<3;i++)
        {
            preGUIDptr[i] += key;
        }
        break;
    case 5: // -
        for(i=0;i<3;i++)
        {
            preGUIDptr[i] -= key;
        }
        break;
    default:
        printf("´íÎóµ±Ç°Ñ¡ÔñµÄÔËËã·½Ê½²»¿ÉÓÃ\r\n");
        return -1;
    }
    return 1;
}
int8_t bitDiffuse(uint8_t decrypt[16], uint8_t License[256], uint8_t bitSelectIndex)
{
	uint8_t i, j;	
    //À©É¢µ½128×Ö½Ú
    switch (bitSelectIndex) {
    case 0:
        for(i=0;i<16;i++)
        {
            for(j=0;j<8;j++)
            {
                if((decrypt[i]&(0x01<<j)))
                    License[i*8+j] |= 0x01;
                else
                    License[i*8+j] &= ~0x01;
            }
        }
        break;
    case 1:
        for(i=0;i<16;i++)
        {
            for(j=0;j<8;j++)
            {
                if((decrypt[i]&(0x01<<j)))
                    License[i*8+j] |= 0x02;
                else
                    License[i*8+j] &= ~0x02;
            }
        }
        break;
    case 2:
        for(i=0;i<16;i++)
        {
            for(j=0;j<8;j++)
            {
                if((decrypt[i]&(0x01<<j)))
                    License[i*8+j] |= 0x04;
                else
                    License[i*8+j] &= ~0x04;
            }
        }
        break;
    case 3:
        for(i=0;i<16;i++)
        {
            for(j=0;j<8;j++)
            {
                if((decrypt[i]&(0x01<<j)))
                    License[i*8+j] |= 0x08;
                else
                    License[i*8+j] &= ~0x08;
            }
        }
        break;
    case 4:
        for(i=0;i<16;i++)
        {
            for(j=0;j<8;j++)
            {
                if((decrypt[i]&(0x01<<j)))
                    License[i*8+j] |= 0x10;
                else
                    License[i*8+j] &= ~0x10;
            }
        }
        break;
    case 5:
        for(i=0;i<16;i++)
        {
            for(j=0;j<8;j++)
            {
                if((decrypt[i]&(0x01<<j)))
                    License[i*8+j] |= 0x20;
                else
                    License[i*8+j] &= ~0x20;
            }
        }
        break;
    case 6:
        for(i=0;i<16;i++)
        {
            for(j=0;j<8;j++)
            {
                if((decrypt[i]&(0x01<<j)))
                    License[i*8+j] |= 0x40;
                else
                    License[i*8+j] &= ~0x40;
            }
        }
        break;
    case 7:
        for(i=0;i<16;i++)
        {
            for(j=0;j<8;j++)
            {
                if((decrypt[i]&(0x01<<j)))
                    License[i*8+j] |= 0x80;
                else
                    License[i*8+j] &= ~0x80;
            }
        }
        break;
    default:
        printf("´íÎóÎÞÐ§µÄÀ©É¢Î»Ñ¡Ôñ\r\n");
        return -1;

    }	
    return 1;
}

int8_t Authorize(uint8_t decrypt[16], uint8_t License[128], uint8_t bitSelectIndex)
{
	uint8_t i, j;	
    //À©É¢µ½128×Ö½Ú
    switch (bitSelectIndex) {
    case 0:
        for(i=0;i<16;i++)
        {
            for(j=0;j<8;j++)
            {			
							if ( ( License[i*8+j] & 0x01 ) == ( (decrypt[i] >> j) & 0x01 ) )
							{		
								//printf("run\r\n");
							}
							else{
								return -1;
								//printf("bitDiffuse2 error\r\n");
							}
            }
        }
        //printf("bitDiffuse2 ok\r\n");
        break;
    case 1:
        for(i=0;i<16;i++)
        {
            for(j=0;j<8;j++)
            {
                 
							if ( ( (License[i*8+j] >> 1) & 0x01 ) == ( (decrypt[i] >> j) & 0x01 ) )
							{		
								//printf("run\r\n");
							}
							else{
								return -1;
								//printf("bitDiffuse2 error\r\n");
							}                   
            }
        }
        //printf("bitDiffuse2 ok\r\n");
        break;
    case 2:
        for(i=0;i<16;i++)
        {
            for(j=0;j<8;j++)
            {
							if ( ( (License[i*8+j] >> 2) & 0x01 ) == ( (decrypt[i] >> j) & 0x01 ) )
							{		
								//printf("run\r\n");
							}
							else{
								return -1;
								//printf("bitDiffuse2 error\r\n");
							}  
            }
        }
        //printf("bitDiffuse2 ok\r\n"); 
        break;
    case 3:
        for(i=0;i<16;i++)
        {
            for(j=0;j<8;j++)
            {
							if ( ( (License[i*8+j] >> 3) & 0x01 ) == ( (decrypt[i] >> j) & 0x01 ) )
							{		
								//printf("run\r\n");
							}
							else{
								return -1;
								//printf("bitDiffuse2 error\r\n");
							}  
            }
        }
        //printf("bitDiffuse2 ok\r\n");        
        break;
    case 4:
        for(i=0;i<16;i++)
        {
            for(j=0;j<8;j++)
            {
							if ( ( (License[i*8+j] >> 4) & 0x01 ) == ( (decrypt[i] >> j) & 0x01 ) )
							{		
								//printf("run\r\n");
							}
							else{
								return -1;
								//printf("bitDiffuse2 error\r\n");
							}  
            }
        }
        //printf("bitDiffuse2 ok\r\n");       
        break;
    case 5:
        for(i=0;i<16;i++)
        {
            for(j=0;j<8;j++)
            {
							if ( ( (License[i*8+j] >> 5) & 0x01 ) == ( (decrypt[i] >> j) & 0x01 ) )
							{		
								//printf("run\r\n");
							}
							else{
								return -1;
								//printf("bitDiffuse2 error\r\n");
							}  
            }
        }
        //printf("bitDiffuse2 ok\r\n");
        break;
    case 6:
        for(i=0;i<16;i++)
        {
            for(j=0;j<8;j++)
            {
							if ( ( (License[i*8+j] >> 6) & 0x01 ) == ( (decrypt[i] >> j) & 0x01 ) )
							{		
								//printf("run\r\n");
							}
							else{
								return -1;
								//printf("bitDiffuse2 error\r\n");
							}  
            }
        }
        //printf("bitDiffuse2 ok\r\n");        
        break;
    case 7:
        for(i=0;i<16;i++)
        {
            for(j=0;j<8;j++)
            {
							if ( ( (License[i*8+j] >> 7) & 0x01 ) == ( (decrypt[i] >> j) & 0x01 ) )
							{		
								//printf("run\r\n");
							}
							else{
								return -1;
								//printf("bitDiffuse2 error\r\n");
							}  
            }
        }
        //printf("bitDiffuse2 ok\r\n");        
        break;
    default:
        //printf("´íÎóÎÞÐ§µÄÀ©É¢Î»Ñ¡Ôñ\r\n");
        return -1;

    }	
    return 1;
}

int8_t ExchangeCharToByte(uint8_t *LicenseKeySrc256, uint8_t *LicenseKeyDst128)
{
	uint8_t i, index;
	uint8_t tmp;
	uint8_t tmp2;
	for(i=0;i<128;i++)
	{
		index = i*2;
		if(LicenseKeySrc256[index] >= '0' && LicenseKeySrc256[index] <= '9')
		{
			tmp = LicenseKeySrc256[index] - '0';	
		}
		else if(LicenseKeySrc256[index] >= 'A' && LicenseKeySrc256[index] <= 'F')
		{
			tmp = LicenseKeySrc256[index] - 'A'+10;
		}
		else if(LicenseKeySrc256[index] >= 'a' && LicenseKeySrc256[index] <= 'f')
		{
			tmp = LicenseKeySrc256[index] - 'a'+10;
		}
		else
		{
			return -1;
			//printf("error\r\n");
		}
				
		if(LicenseKeySrc256[index+1] >= '0' && LicenseKeySrc256[index+1] <= '9')
		{
			tmp2 = LicenseKeySrc256[index+1] - '0';
		}
		else if(LicenseKeySrc256[index+1] >= 'A' && LicenseKeySrc256[index+1] <= 'F')
		{
			tmp2 = LicenseKeySrc256[index+1] - 'A'+10;
		}
		else if(LicenseKeySrc256[index+1] >= 'a' && LicenseKeySrc256[index+1] <= 'f')
		{
			tmp2 = LicenseKeySrc256[index+1] - 'a'+10;
		}
		else
		{
			return -1;
			//printf("error\r\n");
		}		

		LicenseKeyDst128[i] = ((tmp&0x0f) << 4) | (tmp2&0x0f);
	}
	return 1;
}


int CheckLicense()
{
    uint32_t *pUID = (uint32_t*)0x1FFF7A10;
    uint8_t  GUID[12] = {0};
    uint8_t  guidback[12] = {0};
    uint32_t tmp = 0;
    uint8_t  *pLicense = (uint8_t*)0x08060000; 
    uint8_t  LICENSE[128] = {0};    //从Flash中读出的带随机数填充的128字节License
    uint8_t  CalLicense[16] = {0};  //计算得出的有效的16字节License
    MD5_CTX md5;
    int i;

    //获取GUID
    //printf("GUID: ");
    for(i=0;i<3;i++)
    {
        tmp = *pUID;
        GUID[4*i+0] = tmp&0xff;
        GUID[4*i+1] = (tmp>>8)&0xff;
        GUID[4*i+2] = (tmp>>16)&0xff;
        GUID[4*i+3] = (tmp>>24)&0xff;
        pUID++;
        //printf("%02x %02x %02x %02x ",  GUID[4*i+0],GUID[4*i+1],GUID[4*i+2],GUID[4*i+3]);
    }
    //printf("\n");
    memcpy(guidback, GUID, 12);

    //获取License
    //printf("License: ");
    for(i=0;i<128;i++)
    {
        LICENSE[i] = *pLicense;
        pLicense++;
        //printf("%02x ", LICENSE[i]);
    }
    //printf("\n" );

    //根据GUID计算License    
    preHandle((uint32_t*)GUID, 0x33445566, 2);    //预处理
    MD5_Init(&md5);
    MD5_Update(&md5,GUID,12);
    MD5_Final(CalLicense, &md5);

    // printf("CalLicense: ");
    // for(i=0;i<16;i++)
    // {
    //     printf("%02x ", CalLicense[i]);
    // }
    // printf("\n");

    //比对License
    if(Authorize(CalLicense, LICENSE, 0) == 1) //授权通过
    {
        printf("\r\nAlready Auth Success\r\n");         
        return 0;
    }
    else    //授权不通过
    {
        printf("\n\n====================================================\n");
        printf("\n\tLicense is invalid, Please authorize! \n");
        printf("\tGUID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x \n", 
            guidback[0], guidback[1], guidback[2], guidback[3], guidback[4], guidback[5], 
            guidback[6], guidback[7], guidback[8], guidback[9], guidback[10], guidback[11] );
        printf("====================================================\n\n");
        return -1;
    }
}
