u8 InitRamdomBaseForHiddenKey (void)
{
u8 BaseKey_au8[AES_KEYSIZE_256_BIT];

    LA_SC_StartSmartcard ();

    CI_TickLocalPrintf ("InitRamdomBaseForHiddenKey\r\n");

    // Get a random number for the base key
    if (FALSE == GetRandomNumber_u32 (AES_KEYSIZE_256_BIT / 2, BaseKey_au8))
    {
        CI_LocalPrintf ("GetRandomNumber fails\n\r");
        return (FALSE);
    }

    // Get a random number for the storage key
    if (FALSE == GetRandomNumber_u32 (AES_KEYSIZE_256_BIT / 2, &BaseKey_au8[AES_KEYSIZE_256_BIT / 2]))
    {
        CI_LocalPrintf ("GetRandomNumber fails\n\r");
        return (FALSE);
    }

    CI_LocalPrintf ("Base key       : ");
    HexPrint (AES_KEYSIZE_256_BIT, BaseKey_au8);
    CI_LocalPrintf ("\r\n");

    // Save base key
    WriteHiddenVolumeSlotKey (BaseKey_au8);

    // Invalidate hidden volume data
    DecryptedHiddenVolumeSlotsActive_u8 = FALSE;

    return (TRUE);
}
u8 HV_InitAllSlotData (void)
{
    // u8 RandomCharArray_au8[16];
u32 i;

    // Create salt
    for (i = 0; i < 2; i++)
    {
        // Get a random number from smart card
        if (FALSE == GetRandomNumber_u32 (16, &DecryptedHiddenVolumeSlotsData_au8[i * 16]))
        {
            CI_LocalPrintf ("GetRandomNumber fails\n\r");
            return (FALSE);
        }
    }


    // Fill hidden volume flash page with random chars
    for (i = 0; i < 16; i++)
    {
        // Get a random number from smart card
        if (FALSE == GetRandomNumber_u32 (16, &DecryptedHiddenVolumeSlotsData_au8[HV_SALT_SIZE + i * 16]))
        {
            CI_LocalPrintf ("GetRandomNumber fails\n\r");
            return (FALSE);
        }
    }

    // Write magic number to flash
    DecryptedHiddenVolumeMagicNumber_u32 = HV_MAGIC_NUMBER_INIT;
    flashc_memcpy ((u8 *) HV_MAGIC_NUMBER_ADDRESS, &DecryptedHiddenVolumeMagicNumber_u32, HV_MAGIC_NUMBER_SIZE, TRUE);

    // Write ram data to flash
    flashc_memcpy ((u8 *) HV_SALT_START_ADDRESS, DecryptedHiddenVolumeSlotsData_au8, HV_SALT_SIZE + HV_SLOT_SIZE * HV_SLOT_COUNT, TRUE);

    CI_LocalPrintf ("Init hidden volume slot data\r\n");

    CI_LocalPrintf ("Salt\r\n");
    CI_LocalPrintf ("Encrypted data :\r\n");
    HexPrint (HV_SALT_SIZE, DecryptedHiddenVolumeSlotsData_au8);
    CI_LocalPrintf ("\r\n\r\n");

    for (i = 0; i < HV_SLOT_COUNT; i++)
    {
        CI_LocalPrintf ("Slot %d\r\n", i);
        CI_LocalPrintf ("Encrypted data :\r\n");
        HexPrint (HV_SLOT_SIZE, DecryptedHiddenVolumeSlotsData_au8 + HV_SALT_SIZE + i * HV_SLOT_SIZE);
        CI_LocalPrintf ("\r\n\r\n");
    }

    return (TRUE);
}
u8 PWM_InitRandomChar (void)
{
u8 i;
static u8 InitCalls_u8 = 200;   // First call generates random numbers

    //
    InitCalls_u8++;
    if (100 > InitCalls_u8)
    {
        return (TRUE);
    }
    InitCalls_u8 = 0;

    // LA_RestartSmartcard_u8 (); // Todo lock transcation

    if (FALSE == GetRandomNumber_u32 (PWM_RAMDOMCHAR_BUFFERSIZE, PWM_Randomchars_au8))
    {
        CI_LocalPrintf ("GetRandomNumber_u32: Failed to get random numbers from smartcard\r\n");

        // Get local random numbers
        for (i = 0; i < PWM_RAMDOMCHAR_BUFFERSIZE; i++)
        {
            PWM_Randomchars_au8[i] = rand () % 10;
        }
    }
    else
    {
        for (i = 0; i < PWM_RAMDOMCHAR_BUFFERSIZE; i++)
        {
            PWM_Randomchars_au8[i] = PWM_Randomchars_au8[i] % 10;   // Todo: for testing no symmetric random numbers
        }
    }

    PWM_RandomcharsPointer_u8 = 0;

    // LA_RestartSmartcard_u8 ();
    ISO7816_SetLockCounter (0);
    CCID_SmartcardOff_u8 ();    // To avoid smartcard error - after GetRandomNumber_u32

    return (TRUE);
}
void IBN_HV_Tests (unsigned char nParamsGet_u8, unsigned char CMD_u8, unsigned int Param_u32, unsigned char* String_pu8)
{
    HiddenVolumeKeySlot_tst SlotData_st;
    u8 HiddenVolumeSlotKey_u8[32];
    u8 DummyKey_au8[32];
    u8 i;

    if (0 == nParamsGet_u8)
    {
        CI_LocalPrintf ("Hidden volume test functions\r\n");
        CI_LocalPrintf ("\r\n");
        // CI_LocalPrintf ("0 nr Init slot [nr]\r\n");
        CI_LocalPrintf ("1 nr     Read slot [nr]\r\n");
        // CI_LocalPrintf ("2 Test key generation\r\n");
#ifdef TEST_PBKDF2
        CI_LocalPrintf ("3        PBKDF2 test\r\n");
#endif
        CI_LocalPrintf ("4        Get hidden volume slot key\r\n");
        CI_LocalPrintf ("5 [pw]   Get AES key. pw = password\r\n");
        CI_LocalPrintf ("6        Init hidden slots\r\n");
        CI_LocalPrintf ("7        Hidden slots status\r\n");
        CI_LocalPrintf ("8 nr pw  Write slot [nr] [password]\r\n");
        CI_LocalPrintf ("\r\n");
        return;
    }

    switch (CMD_u8)
    {
        case 0:
            break;

        case 1:
            CI_LocalPrintf ("Read slot : %d\r\n", Param_u32);

            if (FALSE == DecryptedHiddenVolumeSlotsActive_u8)
            {
                CI_LocalPrintf ("\r\nHidden slots key not decrypted\r\n");
                break;
            }
            if (NULL == String_pu8)
            {
                String_pu8 = "aaaa";
                CI_LocalPrintf ("No password set. Set it to -%s-\r\n", String_pu8);
            }
            CI_LocalPrintf ("Check for password : %s\r\n", String_pu8);


            CI_LocalPrintf ("Decrypted slots key : ");
            HexPrint (AES_KEYSIZE_256_BIT, DecryptedHiddenVolumeSlotsKey_au8);
            CI_LocalPrintf ("\r\n");

            GetHiddenVolumeSlotKey (HiddenVolumeSlotKey_u8, String_pu8, strlen ((char *) String_pu8), DecryptedHiddenVolumeSlotsData_au8,
                                    HV_SALT_SIZE);

            CI_LocalPrintf ("Hidden volume slot key : ");
            HexPrint (AES_KEYSIZE_256_BIT, HiddenVolumeSlotKey_u8);
            CI_LocalPrintf ("\r\n");

            HV_ReadSlot_u8 (Param_u32, &SlotData_st, (u8 *) HiddenVolumeSlotKey_u8);
            HV_PrintSlotData_u8 (Param_u32, &SlotData_st);
            break;

        case 2:
            break;
#ifdef TEST_PBKDF2
        case 3:
            pbkdf2_test ();
            break;
#endif
        case 4:
            DecryptedHiddenVolumeSlotsData ();
            break;

        case 5:
            CI_LocalPrintf ("Get key for password : %s\r\n", String_pu8);
            GetHiddenVolumeDataKeyFromUserpassword (String_pu8, DummyKey_au8);
            break;

        case 6:
            CI_LocalPrintf ("Init hidden slots\r\n");
            InitHiddenSlots ();
            break;

        case 7:
            CI_LocalPrintf ("Hidden slots status\r\n");
            if (NULL == String_pu8)
            {
                String_pu8 = "aaaa";
                CI_LocalPrintf ("No password set. Set it to -%s-\r\n", String_pu8);
            }
            CI_LocalPrintf ("Check for password : %s\r\n", String_pu8);

            if (FALSE == DecryptedHiddenVolumeSlotsActive_u8)
            {
                CI_LocalPrintf ("\r\nHidden slots key not decrypted\r\n");
                break;
            }


            CI_LocalPrintf ("Decrypted slots key : ");
            HexPrint (AES_KEYSIZE_256_BIT, DecryptedHiddenVolumeSlotsKey_au8);
            CI_LocalPrintf ("\r\n");

            GetHiddenVolumeSlotKey (HiddenVolumeSlotKey_u8, String_pu8, strlen ((char *) String_pu8), DecryptedHiddenVolumeSlotsData_au8,
                                    HV_SALT_SIZE);

            CI_LocalPrintf ("Hidden volume slot key : ");
            HexPrint (AES_KEYSIZE_256_BIT, HiddenVolumeSlotKey_u8);
            CI_LocalPrintf ("\r\n");

            for (i = 0; i < HV_SLOT_COUNT; i++)
            {
                CI_LocalPrintf ("Slot %d\r\n", i);
                if (TRUE == HV_ReadSlot_u8 (i, &SlotData_st, HiddenVolumeSlotKey_u8))
                {
                    HV_PrintSlotData_u8 (i, &SlotData_st);
                }
                else
                {
                    CI_LocalPrintf ("*** Invalid data ***\r\n");
                }
            }

            break;

        case 8:
            CI_LocalPrintf ("Write slots status\r\n");

            if (FALSE == DecryptedHiddenVolumeSlotsActive_u8)
            {
                CI_LocalPrintf ("\r\nHidden slots key not decrypted\r\n");
                break;
            }
            if (NULL == String_pu8)
            {
                String_pu8 = "aaaa";
                CI_LocalPrintf ("No password set. Set it to -%s-\r\n", String_pu8);
            }
            CI_LocalPrintf ("Check for password : %s\r\n", String_pu8);


            CI_LocalPrintf ("Decrypted slots key : ");
            HexPrint (AES_KEYSIZE_256_BIT, DecryptedHiddenVolumeSlotsKey_au8);
            CI_LocalPrintf ("\r\n");

            GetHiddenVolumeSlotKey (HiddenVolumeSlotKey_u8, String_pu8, strlen ((char *) String_pu8), DecryptedHiddenVolumeSlotsData_au8,
                                    HV_SALT_SIZE);

            CI_LocalPrintf ("Hidden volume slot key : ");
            HexPrint (AES_KEYSIZE_256_BIT, HiddenVolumeSlotKey_u8);
            CI_LocalPrintf ("\r\n");

            SlotData_st.StartBlock_u32 = 1000000;
            SlotData_st.EndBlock_u32 = 2000000;

            // Get a random number for the data key
            if (FALSE == GetRandomNumber_u32 (AES_KEYSIZE_256_BIT / 2, SlotData_st.AesKey_au8))
            {
                CI_LocalPrintf ("GetRandomNumber fails\n\r");
                return;
            }

            // Get a random number for the data key
            if (FALSE == GetRandomNumber_u32 (AES_KEYSIZE_256_BIT / 2, &SlotData_st.AesKey_au8[AES_KEYSIZE_256_BIT / 2]))
            {
                CI_LocalPrintf ("GetRandomNumber fails\n\r");
                return;
            }

            HV_WriteSlot_u8 (Param_u32, &SlotData_st, HiddenVolumeSlotKey_u8);

            break;

    }
}
u8 SetupUpHiddenVolumeSlot (HiddenVolumeSetup_tst * HV_Setup_st)
{
u8 HiddenVolumeSlotKey_u8[AES_KEYSIZE_256_BIT];
HiddenVolumeKeySlot_tst SlotData_st;

    HV_Setup_st->HiddenVolumePassword_au8[MAX_HIDDEN_VOLUME_PASSOWORD_SIZE] = 0;

    CI_LocalPrintf ("SetupUpHiddenVolumeSlot %d\r\n", HV_Setup_st->SlotNr_u8);
    CI_LocalPrintf ("Start block at %d %% of sd size\r\n", HV_Setup_st->StartBlockPercent_u8);
    CI_LocalPrintf ("End   block at %d %% of sd size\r\n", HV_Setup_st->EndBlockPercent_u8);
    CI_LocalPrintf ("Password : -%s-\r\n", HV_Setup_st->HiddenVolumePassword_au8);

    // Is the hidden volume system initialised ?
    if (FALSE == HV_CheckFlashPageIsInitiated ())
    {
        CI_LocalPrintf ("Hidden volume flash page isn't initiated\r\n");
        InitHiddenSlots ();
    }

    // Are the hidden volume slots decrypted ?
    if (TRUE != DecryptedHiddenVolumeSlotsActive_u8)
    {
        if (FALSE == DecryptedHiddenVolumeSlotsData ()) // Decrypt new keys
        {
            CI_LocalPrintf ("Slot data not encrypted - used smartcard user password\r\n");
            return (HIDDEN_VOLUME_OUTPUT_STATUS_NO_USER_PASSWORD_UNLOCK);
        }
    }

    if (HV_SLOT_COUNT <= HV_Setup_st->SlotNr_u8)
    {
        CI_LocalPrintf ("Wrong slot nr\r\n");
        return (HIDDEN_VOLUME_OUTPUT_STATUS_WRONG_PASSWORD);
    }

    CI_LocalPrintf ("Decrypted slots key : ");
    HexPrint (AES_KEYSIZE_256_BIT, DecryptedHiddenVolumeSlotsKey_au8);
    CI_LocalPrintf ("\r\n");

    // Get AES key for slot
    GetHiddenVolumeSlotKey (HiddenVolumeSlotKey_u8, HV_Setup_st->HiddenVolumePassword_au8, strlen ((char *) HV_Setup_st->HiddenVolumePassword_au8),
                            DecryptedHiddenVolumeSlotsData_au8, HV_SALT_SIZE);

    CI_LocalPrintf ("Hidden volume slot key : ");
    HexPrint (AES_KEYSIZE_256_BIT, HiddenVolumeSlotKey_u8);
    CI_LocalPrintf ("\r\n");

    SlotData_st.StartBlock_u32 = (u32) ((u64) gSdEndOfCard_u32 * (u64) HV_Setup_st->StartBlockPercent_u8 / (u64) 100) + 1;
    SlotData_st.EndBlock_u32 = (u32) ((u64) gSdEndOfCard_u32 * (u64) HV_Setup_st->EndBlockPercent_u8 / (u64) 100) - 1;

    // Get a random number for the data key
    if (FALSE == GetRandomNumber_u32 (AES_KEYSIZE_256_BIT / 2, SlotData_st.AesKey_au8))
    {
        CI_LocalPrintf ("GetRandomNumber fails\n\r");
        return (HIDDEN_VOLUME_OUTPUT_STATUS_SMARTCARD_ERROR);
    }

    // Get a random number for the data key
    if (FALSE == GetRandomNumber_u32 (AES_KEYSIZE_256_BIT / 2, &SlotData_st.AesKey_au8[AES_KEYSIZE_256_BIT / 2]))
    {
        CI_LocalPrintf ("GetRandomNumber fails\n\r");
        return (HIDDEN_VOLUME_OUTPUT_STATUS_SMARTCARD_ERROR);
    }

    HV_PrintSlotData_u8 (HV_Setup_st->SlotNr_u8, &SlotData_st);

    HV_WriteSlot_u8 (HV_Setup_st->SlotNr_u8, &SlotData_st, HiddenVolumeSlotKey_u8);

    return (HIDDEN_VOLUME_OUTPUT_STATUS_OK);
}