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;

    }
}
void HID_ExcuteCmd (void)
{
    u8 StorageKey_pu8[32];
    u8 Cmd_u8;
    u8* PasswordMatrix_pu8;
    u8 ret_u8;
    u64 timestamp;
    u32 Len;

    Cmd_u8 = HID_CmdGet_u8;


    // Send a smart card status before the lock check
    if (HTML_CMD_CHECK_SMARTCARD_USAGE == Cmd_u8)
    {
        CI_TickLocalPrintf ("Check smartcard usage\r\n");
        if (0 == USB_CCID_GetLockCounter ())
        {
            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
            CI_TickLocalPrintf ("smartcard not busy\r\n");
        }
        else
        {
            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_SMARTCARD_ERROR, 0);
            CI_TickLocalPrintf ("smartcard busy\r\n");
        }
        return;
    }

    // Check for active CCID command
    // If CCID command is active, wait with HID smart card access until CCID access has ended
    if (0 != USB_CCID_GetLockCounter ())
    {
//      UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_BUSY, 0);
//      memset (HID_String_au8, 0, 50); // Clear input data, with possible sent passwords
      return;
    }

    // Check for matrix password > if yes convert the matrix to password
    switch (Cmd_u8)
    {
        case HTML_CMD_ENABLE_AES_LUN:
        case HTML_CMD_ENABLE_HIDDEN_AES_LUN:
        case HTML_CMD_DISABLE_HIDDEN_AES_LUN:
        case HTML_CMD_EXPORT_BINARY:
        case HTML_CMD_GENERATE_NEW_KEYS:
        case HTML_CMD_ENABLE_READWRITE_UNCRYPTED_LUN:
        case HTML_CMD_CLEAR_NEW_SD_CARD_FOUND:
            switch (HID_String_au8[0])
            {
                case 'P':  // normal password
                    // Do nothing
                    break;
                case 'M':  // matrix password
                    // Convert matrix input to password
                    if (FALSE == ConvertMatrixDataToPassword (&HID_String_au8[1]))
                    {
                        UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                        return;
                    }
                    break;
            }
            break;

        case HTML_CMD_FILL_SD_WITH_RANDOM_CHARS:
            switch (HID_String_au8[1])
            {
                case 'P':  // normal password
                    // Do nothing
                    break;
                case 'M':  // matrix password
                    // Convert matrix input to password
                    if (FALSE == ConvertMatrixDataToPassword (&HID_String_au8[2]))
                    {
                        UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                        return;
                    }
                    break;
            }
            break;
    }
    // Check for hidden password

    if (TRUE == HID_NextPasswordIsHiddenPassword_u32)
    {
        switch (Cmd_u8)
        {
            case HTML_CMD_ENABLE_AES_LUN:
                Cmd_u8 = HTML_CMD_ENABLE_HIDDEN_AES_LUN;
                CI_TickLocalPrintf ("Redirect password -%s- to hidden volume\r\n", &HID_String_au8[1]);
                SetSdEncryptedCardEnableState (FALSE);
                SetSdEncryptedHiddenState (FALSE);
                CI_TickLocalPrintf ("Unmount crypted volume\r\n");

                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_BUSY_PROGRESSBAR, 50);

                vTaskDelay (1000);  // Wait that pc unmount old volume
                break;
        }
    }


    //
    switch (Cmd_u8)
    {
        case HTML_CMD_NOTHING:
            break;

        case HTML_CMD_ENABLE_AES_LUN:
            if (TRUE == IW_SendToSC_PW1 (&HID_String_au8[1]))
            {
                SetSdEncryptedHiddenState (FALSE);
                SetSdEncryptedCardEnableState (FALSE);  // Disable crypted or hidden volume
                vTaskDelay (3000);

                CI_TickLocalPrintf ("Get key for crypted volume\r\n");

                u8 isKeyZero = TRUE;
                u8 isKeyValid = GetStorageKey_u32 (&HID_String_au8[1], StorageKey_pu8);

                // check if retrieved key is all-zeroes
                if (TRUE == isKeyValid) {
                    u8 keyByte;
                    for (keyByte = 0; keyByte < sizeof(StorageKey_pu8); keyByte++) {
                        if (StorageKey_pu8[keyByte] != 0) {
                            isKeyZero = FALSE;
                            break;
                        }
                    }
                }

                // Terminate mounting procedure if key could not be retrieved or is all-zero
                if (FALSE == isKeyValid || TRUE == isKeyZero) {
                    UpdateStick20Command (CMD_STATUS_AES_DEC_FAILED, 0);
                    HID_NextPasswordIsHiddenPassword_u32 = FALSE;
                    break;
                }


                AES_SetNewStorageKey (StorageKey_pu8);

                SetSdEncryptedCardEnableState (TRUE);

                DecryptedHiddenVolumeSlotsData ();
                PWS_DecryptedPasswordSafeKey ();

                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
                /*
                   HID_NextPasswordIsHiddenPassword_u32 = TRUE; // switch on redirection of aes volume password CI_TickLocalPrintf ("Next AES volume
                   password is used for hidden volume\r\n"); */
                CI_TickLocalPrintf ("SD card AES LUN enabled\r\n");
            }
            else
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                HID_NextPasswordIsHiddenPassword_u32 = FALSE;
                CI_TickLocalPrintf ("*** wrong password ***\r\n");
            }
            break;

        case HTML_CMD_DISABLE_AES_LUN:
            SetSdEncryptedCardEnableState (FALSE);
            SetSdEncryptedHiddenState (FALSE);
            AES_SetNewStorageKey ((u8 *) AES_DummyKey_au8); // Set dummy key
            HID_NextPasswordIsHiddenPassword_u32 = FALSE;
            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);

            CI_TickLocalPrintf ("SD card AES LUN disabled\r\n");
            break;

        case HTML_CMD_ENABLE_FIRMWARE_UPDATE:
            CI_TickLocalPrintf ("Firmware update - ");
/*
            if (TRUE == flashc_is_security_bit_active ())
            {
                CI_TickLocalPrintf ("Security bit is active. No Update\r\n");
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_SECURITY_BIT_ACTIVE, 0);
                break;
            }
*/
            if (TRUE == CheckUpdatePin (&HID_String_au8[1], strlen ((char*)&HID_String_au8[1])))
            {
                CI_TickLocalPrintf ("good bye\r\n");
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
                DelayMs (500);        // Wait to send answer to host
                DFU_EnableFirmwareUpdate ();
                DFU_ResetCPU ();
            }
            else
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                CI_TickLocalPrintf ("wrong password\r\n");
            }
            break;

        case HTML_CMD_FILL_SD_WITH_RANDOM_CHARS:
            if (TRUE == IW_SendToSC_PW3 (&HID_String_au8[2]))
            {
                CI_TickLocalPrintf ("Fill SD card with random numbers - it runs very long, 1 GB ca. 4 minutes\r\n");

                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_BUSY_PROGRESSBAR, 0);

                // Disable all SD card access via USB
//                SetSdUncryptedCardEnableState (FALSE);  // look for >> sd_mmc_mci_test_unit_only_local_access = hard disabel
//                SetSdEncryptedCardEnableState (FALSE);
//                SetSdEncryptedHiddenState (FALSE);
//                vTaskDelay (3000);

                AES_SetNewStorageKey ((u8 *) AES_DummyKey_au8); // Set dummy key


//                   if (STICK20_FILL_SD_CARD_WITH_RANDOM_CHARS_ALL_VOL == HID_String_au8[0]) { SD_SecureEraseHoleCard (); } else {
//                   SD_SecureEraseCryptedVolume (); }
                SD_SecureEraseCryptedVolume ();

                SetSdCardFilledWithRandomsToFlash ();

                // Enable uncrypted SD card access via USB
//                SetSdUncryptedCardEnableState (TRUE);
                // SetSdUncryptedCardReadWriteEnableState (READ_WRITE_ACTIVE);

                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_BUSY_PROGRESSBAR, 100);
                vTaskDelay (500);
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
                vTaskDelay (500);

//                usb_restart ();     // Restart USB

                // DFU_ResetCPU (); // Reboot to get correct volume data
            }
            else
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                CI_TickLocalPrintf ("wrong password\r\n");
            }
            break;

        case HTML_CMD_ENABLE_HIDDEN_AES_LUN:
            // SetSdUncryptedCardEnableState (FALSE); // look for >> sd_mmc_mci_test_unit_only_local_access = hard disabel

            // Get w AES key for hidden volume - we use always the password that was send
            memset (StorageKey_pu8, 0, 32);
            ret_u8 = GetHiddenVolumeKeyFromUserpassword ((u8 *) & HID_String_au8[1], StorageKey_pu8);
            switch (ret_u8)
            {
                case HIDDEN_VOLUME_OUTPUT_STATUS_OK:
                    SetSdEncryptedCardEnableState (FALSE);
                    SetSdEncryptedHiddenState (FALSE);
                    AES_SetNewStorageKey ((u8 *) AES_DummyKey_au8); // Set dummy key

                    vTaskDelay (3000);  // Wait 3 sec to send LUN not active

                    AES_SetNewStorageKey (StorageKey_pu8);
                    SetSdEncryptedHiddenState (TRUE);
                    SetSdEncryptedCardEnableState (TRUE);
                    UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
                    CI_TickLocalPrintf ("Hidden volume - SD card hidden AES LUN enabled\r\n");
                    break;
                case HIDDEN_VOLUME_OUTPUT_STATUS_WRONG_PASSWORD:
                    CI_TickLocalPrintf ("Hidden volume - wrong password\r\n");
                    UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                    break;
                case HIDDEN_VOLUME_OUTPUT_STATUS_NO_USER_PASSWORD_UNLOCK:
                    CI_TickLocalPrintf ("Hidden volume - no user password\r\n");
                    UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_NO_USER_PASSWORD_UNLOCK, 0);
                    break;
                case HIDDEN_VOLUME_OUTPUT_STATUS_SMARTCARD_ERROR:
                    CI_TickLocalPrintf ("Hidden volume - smartcard error\r\n");
                    UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_SMARTCARD_ERROR, 0);
                    break;
                default:
                    break;
            }

            HID_NextPasswordIsHiddenPassword_u32 = FALSE;   // switch off redirection of aes volume password
            break;

        case HTML_CMD_DISABLE_HIDDEN_AES_LUN:
            SetSdEncryptedCardEnableState (FALSE);
            SetSdEncryptedHiddenState (FALSE);
            memset (StorageKey_pu8, 0, 32); // Set dummy key
            AES_SetNewStorageKey ((u8 *) AES_DummyKey_au8); // Set dummy key
            HID_NextPasswordIsHiddenPassword_u32 = FALSE;

            vTaskDelay (3000);  // Wait 3 sec to send LUN not active
            CI_TickLocalPrintf ("SD card hidden AES LUN disabled\r\n");
            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
            break;


        case HTML_CMD_EXPORT_BINARY:
            if (TRUE == IW_SendToSC_PW3 (&HID_String_au8[1]))
            {
                CI_TickLocalPrintf ("Export binary\r\n");
                // SetSdUncryptedCardEnableState (FALSE); // todo: Check disable access, don't work here

                FileIO_SaveAppImage_u8 ();

                SetSdUncryptedCardEnableState (FALSE);  // Disable access
                vTaskDelay (3000);
                SetSdUncryptedCardEnableState (TRUE);   // Enable access

                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
            }
            else
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                CI_TickLocalPrintf ("*** wrong password ***\r\n");
            }
            break;

        case HTML_CMD_GENERATE_NEW_KEYS:
        {
            u8 CmdOk_u8 = TRUE;
            u8 SdCardFilledWithRandoms_u8;
            u8 StickKeysNotInitiated_u8;


            // Save old state
            SdCardFilledWithRandoms_u8 = StickConfiguration_st.SDFillWithRandomChars_u8;
            StickKeysNotInitiated_u8   = StickConfiguration_st.StickKeysNotInitiated_u8;

            CI_TickLocalPrintf ("Generate new keys Old State KNI %d, SDF %d\r\n",StickKeysNotInitiated_u8,SdCardFilledWithRandoms_u8);
            if (TRUE == BuildStorageKeys_u32 ((u8 *) & HID_String_au8[1]))
            {
                SetSdEncryptedCardEnableState (FALSE);
                SetSdEncryptedHiddenState (FALSE);
                memset (StorageKey_pu8, 0, 32);

                AES_SetNewStorageKey ((u8 *) AES_DummyKey_au8); // Set dummy key
            }
            else
            {
                CmdOk_u8 = FALSE;
            }

            if (TRUE == SdCardFilledWithRandoms_u8)     // Restore old state
            {
              SetSdCardFilledWithRandomsToFlash ();
            }
            if (FALSE == StickKeysNotInitiated_u8)     // Restore old state
            {
              ClearStickKeysNotInitatedToFlash ();
            }

            if (TRUE == CmdOk_u8)
            {
              CI_TickLocalPrintf ("Generate new keys for hidden volume slots\r\n");
              if (FALSE == InitHiddenSlots ())
              {
                  CmdOk_u8 = FALSE;
              }
            }

            if (TRUE == CmdOk_u8)
            {
              CI_TickLocalPrintf ("Generate new keys for password safe store\r\n");
              if (FALSE == BuildPasswordSafeKey_u32 ())
              {
                  CmdOk_u8 = FALSE;
              }
            }

            if (TRUE == CmdOk_u8)
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
            }
            else
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
            }
        }
            break;

        case HTML_CMD_ENABLE_READONLY_UNCRYPTED_LUN:
            CI_TickLocalPrintf ("Set readonly to unencrypted volume\r\n");

            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
            CI_TickLocalPrintf ("*** wrong password - NOT USED ***\r\n");
            break;

        case HTML_CMD_ENABLE_READWRITE_UNCRYPTED_LUN:
            CI_TickLocalPrintf ("Set readwrite to unencrypted volume\r\n");

            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
            CI_TickLocalPrintf ("*** wrong password - NOT USED ***\r\n");
            break;

        case HTML_CMD_SEND_PASSWORD_MATRIX:
            CI_TickLocalPrintf ("Get SEND_PASSWORD_MATRIX\r\n");

            PasswordMatrix_pu8 = GetCorrectMatrix ();

            Stick20HIDInitSendMatrixData (PasswordMatrix_pu8);

            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_PASSWORD_MATRIX_READY, 0);
            break;

        case HTML_CMD_SEND_PASSWORD_MATRIX_PINDATA:
            CI_TickLocalPrintf ("Get SEND_PASSWORD_MATRIX_PINDATA\r\n");

            CI_TickLocalPrintf ("Data 1 : %s\r\n", HID_String_au8);

            // PasswordMatrix_pu8 = GetCorrectMatrix ();

            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
            break;

        case HTML_CMD_SEND_PASSWORD_MATRIX_SETUP:
            CI_TickLocalPrintf ("Get SEND_PASSWORD_MATRIX_SETUP\r\n");
            CI_TickLocalPrintf ("Data : %s\r\n", HID_String_au8);
            WriteMatrixColumsUserPWToUserPage (&HID_String_au8[1]); // Data is in ASCII
            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
            break;


        case HTML_CMD_GET_DEVICE_STATUS:
            CI_TickLocalPrintf ("Get HTML_CMD_GET_DEVICE_STATUS\r\n");

            StickConfiguration_st.FirmwareLocked_u8 = FALSE;
            if (TRUE == flashc_is_security_bit_active ())
            {
                StickConfiguration_st.FirmwareLocked_u8 = TRUE;
            }

            GetSmartCardStatus (&StickConfiguration_st);
            Stick20HIDInitSendConfiguration (STICK20_SEND_STATUS_PIN);
            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
            break;

        case HTML_CMD_WRITE_STATUS_DATA:
            CI_TickLocalPrintf ("Get HTML_CMD_WRITE_STATUS_DATA\r\n");
            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
            break;


        case HTML_SEND_HIDDEN_VOLUME_SETUP:
            CI_TickLocalPrintf ("Get HTML_SEND_HIDDEN_VOLUME_SETUP\r\n");
            InitRamdomBaseForHiddenKey ();
            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
            break;

        case HTML_CMD_SEND_PASSWORD:
            CI_TickLocalPrintf ("Get HTML_CMD_SEND_PASSWORD\r\n");

            HID_AdminPasswordEnabled_u32 = FALSE;
            HID_UserPasswordEnabled_u32 = FALSE;

            switch (HID_String_au8[0])
            {
                case 'P':
                    ret_u8 = IW_SendToSC_PW1 (&HID_String_au8[1]);
                    HID_UserPasswordEnabled_u32 = ret_u8;
                    strncpy ((char *) HID_UserPassword_au8, (char *) &HID_String_au8[1], HID_PASSWORD_LEN);
                    break;
                case 'A':
                    ret_u8 = IW_SendToSC_PW3 (&HID_String_au8[1]);
                    HID_AdminPasswordEnabled_u32 = ret_u8;
                    strncpy ((char *) HID_AdminPassword_au8, (char *) &HID_String_au8[1], HID_PASSWORD_LEN);
                    break;
            }

            if (TRUE == ret_u8)
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
                CI_TickLocalPrintf ("password ok\r\n");
            }
            else
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                CI_TickLocalPrintf ("*** wrong password ***\r\n");
            }
            break;

        case HTML_CMD_SEND_NEW_PASSWORD:
            CI_TickLocalPrintf ("Get HTML_CMD_SEND_NEW_PASSWORD\r\n");
            ret_u8 = FALSE;
            switch (HID_String_au8[0])
            {
                case 'P':
                    if (TRUE == HID_UserPasswordEnabled_u32)
                    {
                        ret_u8 = LA_OpenPGP_V20_Test_ChangeUserPin (HID_UserPassword_au8, &HID_String_au8[1]);
                    }
                    else
                    {
                        CI_TickLocalPrintf ("** User password not present ***\r\n");
                    }
                    break;
                case 'A':
                    if (TRUE == HID_AdminPasswordEnabled_u32)
                    {
                        ret_u8 = LA_OpenPGP_V20_Test_ChangeAdminPin (HID_AdminPassword_au8, &HID_String_au8[1]);
                    }
                    else
                    {
                        CI_TickLocalPrintf ("** Admin password not present ***\r\n");
                    }
                    break;
            }

            if (TRUE == ret_u8)
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
                CI_TickLocalPrintf ("password change ok\r\n");
            }
            else
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                CI_TickLocalPrintf ("*** password NOT changed ***\r\n");
            }

            // Clear password
            HID_AdminPasswordEnabled_u32 = FALSE;
            HID_UserPasswordEnabled_u32 = FALSE;
            memset (HID_UserPassword_au8, 0, HID_PASSWORD_LEN);
            memset (HID_AdminPassword_au8, 0, HID_PASSWORD_LEN);
            break;

        case HTML_CMD_CLEAR_NEW_SD_CARD_FOUND:
            CI_TickLocalPrintf ("Get HTML_CMD_CLEAR_NEW_SD_CARD_FOUND\r\n");
            if (TRUE == IW_SendToSC_PW3 (&HID_String_au8[1]))
            {
                ClearNewSdCardFoundToFlash ();
                SetSdCardFilledWithRandomCharsToFlash ();
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
                CI_TickLocalPrintf ("password ok\r\n");
            }
            else
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                CI_TickLocalPrintf ("*** wrong password ***\r\n");
            }
            break;

        case HTML_CMD_SEND_STARTUP:
            CI_TickLocalPrintf ("Get HTML_CMD_SEND_STARTUP\r\n");
            timestamp = getu64 (&HID_String_au8[0]);
            if (FALSE == CheckSystemtime ((u32) timestamp))
            {
                // todo
            }

            GetSmartCardStatus (&StickConfiguration_st);

            Stick20HIDInitSendConfiguration (STICK20_SEND_STARTUP);
            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
            break;
            /*
               case STICK20_CMD_SEND_PASSWORD_RETRY_COUNT : CI_TickLocalPrintf ("Get STICK20_CMD_SEND_PASSWORD_RETRY_COUNT\r\n");

               // Stick20HIDInitSendConfiguration (STICK20_SEND_STARTUP); UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK,0); break; */
        case HTML_CMD_HIDDEN_VOLUME_SETUP:
            CI_TickLocalPrintf ("Get HTML_CMD_HIDDEN_VOLUME_SETUP\r\n");
            ret_u8 = SetupUpHiddenVolumeSlot ((HiddenVolumeSetup_tst *) & HID_String_au8[0]);
            switch (ret_u8)
            {
                case HIDDEN_VOLUME_OUTPUT_STATUS_OK:
                    UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
                    break;
                case HIDDEN_VOLUME_OUTPUT_STATUS_WRONG_PASSWORD:
                    UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                    break;
                case HIDDEN_VOLUME_OUTPUT_STATUS_NO_USER_PASSWORD_UNLOCK:
                    UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_NO_USER_PASSWORD_UNLOCK, 0);
                    break;
                case HIDDEN_VOLUME_OUTPUT_STATUS_SMARTCARD_ERROR:
                    UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_SMARTCARD_ERROR, 0);
                    break;
                default:
                    break;
            }
            break;

        case HTML_CMD_CLEAR_STICK_KEYS_NOT_INITIATED:
            CI_TickLocalPrintf ("Get HTML_CMD_CLEAR_STICK_KEYS_NOT_INITIATED\r\n");
            ClearStickKeysNotInitatedToFlash ();
            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
            break;

        case HTML_CMD_CLEAR_LOCK_STICK_HARDWARE:
            CI_TickLocalPrintf ("Get HTML_CMD_CLEAR_LOCK_STICK_HARDWARE\r\n");
            if (TRUE == IW_SendToSC_PW3 (&HID_String_au8[1]))
            {
                CI_TickLocalPrintf ("Lock firmware\r\n");
//                flashc_set_bootloader_protected_size (0x10000);   // Set bootloader protection to the max protection value, to lock the first 56k of the application
                flashc_activate_security_bit ();    // Debugging disabled, only chip erase works (bootloader is save) , AES storage keys and setup
                                                    // are erased
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
            }
            else
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                CI_TickLocalPrintf ("*** worng password ***\r\n");
            }
            break;

        case HTML_CMD_PRODUCTION_TEST:
            CI_TickLocalPrintf ("Get HTML_CMD_PRODUCTION_TEST\r\n");
            GetProductionInfos (&Stick20ProductionInfos_st,FALSE);
            Stick20HIDInitSendConfiguration (STICK20_SEND_PRODUCTION_TEST);
            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
            break;

        case HTML_CMD_PRODUCTION_TEST_WITH_WRITE_TEST:
            CI_TickLocalPrintf ("Get HTML_CMD_PRODUCTION_TEST_WITH_WRITE_TEST\r\n");
            GetProductionInfos (&Stick20ProductionInfos_st,TRUE);
            Stick20HIDInitSendConfiguration (STICK20_SEND_PRODUCTION_TEST);
            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
            break;


        case HTML_CMD_CHANGE_UPDATE_PIN:
            CI_TickLocalPrintf ("Get HTML_CMD_CHANGE_UPDATE_PIN\r\n");

            Len = strlen ((char*)&HID_String_au8[1]);

            if (TRUE == CheckUpdatePin (&HID_String_au8[1], Len))
            {
                Len = strlen ((char*)&HID_String_au8[22]);
                if (TRUE == StoreNewUpdatePinHashInFlash (&HID_String_au8[22], Len))    // Start of new PW
                {
                    CI_TickLocalPrintf ("Update PIN changed\r\n");
                    UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
                }
                else
                {
                    CI_TickLocalPrintf ("*** worng password len ***\r\n");
                    UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                }
            }
            else
            {
                CI_TickLocalPrintf ("*** worng password ***\r\n");
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
            }
            break;

        case HTML_CMD_ENABLE_ADMIN_READONLY_UNCRYPTED_LUN:
            CI_TickLocalPrintf ("Set readonly to unencrypted volume ADMIN\r\n");
            if (TRUE == IW_SendToSC_PW3 (&HID_String_au8[1]))
            {
                SetSdUncryptedCardEnableState (FALSE);  // Disable access
                SetSdEncryptedCardEnableState (FALSE);
                SetSdUncryptedCardReadWriteEnableState (READ_ONLY_ACTIVE);
                vTaskDelay (6000);
                SetSdUncryptedCardEnableState (TRUE);   // Enable access

                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
                CI_TickLocalPrintf ("ok\r\n");
            }
            else
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                CI_TickLocalPrintf ("*** wrong password ***\r\n");
            }
            break;

        case HTML_CMD_ENABLE_ADMIN_READWRITE_UNCRYPTED_LUN:
            CI_TickLocalPrintf ("Set readwrite to unencrypted volume ADMIN\r\n");
            if (TRUE == IW_SendToSC_PW3 (&HID_String_au8[1]))
            {
                SetSdUncryptedCardEnableState (FALSE);  // Disable access
                SetSdEncryptedCardEnableState (FALSE);
                SetSdUncryptedCardReadWriteEnableState (READ_WRITE_ACTIVE);
                vTaskDelay (6000);
                SetSdUncryptedCardEnableState (TRUE);   // Enable access

                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
                CI_TickLocalPrintf ("ok\r\n");
            }
            else
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                CI_TickLocalPrintf ("*** wrong password ***\r\n");
            }
            break;

        case HTML_CMD_ENABLE_ADMIN_READONLY_ENCRYPTED_LUN:
            CI_TickLocalPrintf ("Set readonly to encrypted volume\r\n");
            if (TRUE == IW_SendToSC_PW3 (&HID_String_au8[1]))
            {
                SetSdUncryptedCardEnableState (FALSE);  // Disable access
                SetSdEncryptedCardEnableState (FALSE);
                SetSdEncryptedCardReadWriteEnableState (READ_ONLY_ACTIVE);
                vTaskDelay (6000);
//                SetSdEncryptedCardEnableState (TRUE);   // Enable access

                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
                CI_TickLocalPrintf ("ok\r\n");
            }
            else
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                CI_TickLocalPrintf ("*** wrong password ***\r\n");
            }
            break;

        case HTML_CMD_ENABLE_ADMIN_READWRITE_ENCRYPTED_LUN:
            CI_TickLocalPrintf ("Set readwrite to encrypted volume ADMIN\r\n");
            if (TRUE == IW_SendToSC_PW3 (&HID_String_au8[1]))
            {
                SetSdUncryptedCardEnableState (FALSE);  // Disable access
                SetSdEncryptedCardEnableState (FALSE);
                SetSdEncryptedCardReadWriteEnableState (READ_WRITE_ACTIVE);
                vTaskDelay (6000);
//                SetSdEncryptedCardEnableState (TRUE);   // Enable access

                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
                CI_TickLocalPrintf ("ok\r\n");
            }
            else
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_WRONG_PASSWORD, 0);
                CI_TickLocalPrintf ("*** wrong password ***\r\n");
            }
            break;

        case HTML_CMD_CHECK_SMARTCARD_USAGE:
            CI_TickLocalPrintf ("Check smartcard usage\r\n");
            if (0 == USB_CCID_GetLockCounter ())
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
                CI_TickLocalPrintf ("smartcard not busy\r\n");
            }
            else
            {
                UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_SMARTCARD_ERROR, 0);
                CI_TickLocalPrintf ("smartcard busy\r\n");
            }
            break;

        case HTML_CMD_WINK:
            CI_TickLocalPrintf ("Get HTML_CMD_WINK\r\n");
            LED_WinkOn ();
            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_OK, 0);
            break;


        default:
            CI_TickLocalPrintf ("HID_ExcuteCmd: Get unknown command: %d \r\n", Cmd_u8);
            UpdateStick20Command (OUTPUT_CMD_STICK20_STATUS_IDLE, 0);
            break;
    }

    HID_CmdGet_u8 = HTML_CMD_NOTHING;
    memset (HID_String_au8, 0, 50); // Clear input data, with possible sent passwords

    /*
       HID_SmartcardAccess_u8 = FALSE; */


}
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);
}