/*++

Copyright (C) Microsoft Corporation, 2002 - 2002

Module Name:

    encraption.h

Abstract:

    This module contains simple obfuscation algorithm to hide communication
    keys.

Author:
    Carsten Hansen
    Alper Selcuk


--*/


#ifndef _ENCRAPTION_H
#define _ENCRAPTION_H

//=============================================================================
//
// This routine clears the given key. The encryption/decryption method is 
// developed by CarstenH.
//
NTSTATUS __forceinline ClearKey(
    const BYTE *PrivKey, 
    BYTE *ClearKey,
    ULONG KeySize, 
    ULONG MagicNumber2)
{
    const char * pszName = "Microsoft Corporation";

    /* Convert the obfuscated key to clear */
    BYTE *clearDRMKPriv;

    clearDRMKPriv = (BYTE *) ExAllocatePool(PagedPool, KeySize);
    if (NULL == clearDRMKPriv) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Permute bytes */
    int k = 1;
    clearDRMKPriv[0] = PrivKey[0];
    do {
        int l = k * MagicNumber2 % (KeySize - 1);
        clearDRMKPriv[k] = PrivKey[l];
        if (l == 1)
            break;
        k = l;
    } while (1);
    clearDRMKPriv[KeySize - 1] = PrivKey[KeySize - 1];

    /* Swap nibbles */
    DWORD * pdw = (DWORD *) clearDRMKPriv;
    DWORD * qdw = (DWORD *) (clearDRMKPriv + KeySize);
    DWORD granularity = 4;
    for (; pdw < qdw; ++ pdw)
    {
        DWORD temp = 0xF0F0F0F0;
        temp &= *pdw;
        *pdw ^= temp;
        temp ^= (*pdw << granularity);
        *pdw |= (*pdw << granularity);
        *pdw ^= (temp >> granularity);
    }

    /* XOR with "Microsoft" */
    ULONG len = strlen(pszName);
    for (ULONG i = 0, j = 0; i < KeySize; ++i)
    {
        clearDRMKPriv[i] ^= pszName[j];
        ++j;
        if (j > len)
            j = 0;
    }

    RtlCopyMemory(ClearKey, clearDRMKPriv, KeySize);

    RtlZeroMemory(clearDRMKPriv, KeySize);
    ExFreePool(clearDRMKPriv);

    return STATUS_SUCCESS;
}

/* Obfuscation algorithm.
	{
		// XOR with "Microsoft" 
		int len = strlen(pszName);
		for (int i = 0, j = 0; i < sizeof(objDRMKPriv); ++i)
		{
			objDRMKPriv[i] = DRMKpriv[i] ^ pszName[j];
			++j;
			if (j > len)
				j = 0;
		}

		// Swap nibbles 
		DWORD * pdw = (DWORD *) objDRMKPriv;
		DWORD * qdw = (DWORD *) (objDRMKPriv + sizeof(objDRMKPriv));
		DWORD granularity = 4;
		for (; pdw < qdw; ++ pdw)
		{
			DWORD temp = 0xF0F0F0F0;
			temp &= *pdw;
			*pdw ^= temp;
			temp ^= (*pdw << granularity);
			*pdw |= (*pdw << granularity);
			*pdw ^= (temp >> granularity);
		}

		// Permute bytes
		int k = 1;
		BYTE temp = objDRMKPriv[k];
		do {
			int l = k * MAGIC_NUMBER_1 % (sizeof(objDRMKPriv) - 1);
			if (l == 1)
				break;
			objDRMKPriv[k] = objDRMKPriv[l];
			k = l;
		} while (1);
		objDRMKPriv[k] = temp;
	}
*/

/* Clean Key and Cert
static const BYTE DRMKpriv[20] = {
        0x80, 0x0B, 0x97, 0x30, 0x7A, 0xFB, 0x1B, 0x3B, 
        0xB7, 0xB2, 0x0F, 0x44, 0x63, 0xD8, 0xA5, 0x2D, 
        0xD5, 0xBC, 0x3D, 0x75};
static const BYTE DRMKCert[104] = {
        0x00, 0x01, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
        0x46, 0xB1, 0x18, 0x76, 0x66, 0xBE, 0x91, 0xEC,
        0xBD, 0x06, 0x50, 0x72, 0x1B, 0x8C, 0xD3, 0x55,
        0xD2, 0x1A, 0xB7, 0x60, 0x6C, 0x65, 0xDD, 0xE4,
        0x54, 0xCE, 0xFD, 0xEB, 0x4A, 0x9F, 0x0A, 0x5A,
        0xD1, 0x44, 0xB2, 0x32, 0xB9, 0xA0, 0x84, 0x67,
        0x55, 0xD7, 0xFE, 0x45, 0xD5, 0x16, 0x36, 0x7B,
        0xEC, 0x3C, 0xFF, 0x7D, 0x4C, 0x09, 0x9A, 0x7B,
        0xB4, 0x6C, 0xEF, 0x2B, 0xC5, 0xF8, 0xA3, 0xC4,
        0xE2, 0x57, 0xC5, 0x87, 0xA6, 0x75, 0x85, 0xFE,
        0xE2, 0x34, 0xA3, 0x30, 0xAE, 0x4D, 0xDB, 0x23,
        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x06,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
*/

#endif